diff options
242 files changed, 7303 insertions, 2847 deletions
diff --git a/.reuse/dep5 b/.reuse/dep5 index d98b78087..b9ae96d0b 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 | |||
| @@ -155,3 +155,7 @@ License: MIT | |||
| 155 | Files: externals/gamemode/* | 155 | Files: externals/gamemode/* |
| 156 | Copyright: Copyright 2017-2019 Feral Interactive | 156 | Copyright: Copyright 2017-2019 Feral Interactive |
| 157 | License: BSD-3-Clause | 157 | License: BSD-3-Clause |
| 158 | |||
| 159 | Files: src/android/app/debug.keystore | ||
| 160 | Copyright: 2023 yuzu Emulator Project | ||
| 161 | License: GPL-3.0-or-later | ||
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index 06e59d1ac..188ef9469 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts | |||
| @@ -82,8 +82,8 @@ android { | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE") | 84 | val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE") |
| 85 | if (keystoreFile != null) { | 85 | signingConfigs { |
| 86 | signingConfigs { | 86 | if (keystoreFile != null) { |
| 87 | create("release") { | 87 | create("release") { |
| 88 | storeFile = file(keystoreFile) | 88 | storeFile = file(keystoreFile) |
| 89 | storePassword = System.getenv("ANDROID_KEYSTORE_PASS") | 89 | storePassword = System.getenv("ANDROID_KEYSTORE_PASS") |
| @@ -91,6 +91,12 @@ android { | |||
| 91 | keyPassword = System.getenv("ANDROID_KEYSTORE_PASS") | 91 | keyPassword = System.getenv("ANDROID_KEYSTORE_PASS") |
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | create("default") { | ||
| 95 | storeFile = file("$projectDir/debug.keystore") | ||
| 96 | storePassword = "android" | ||
| 97 | keyAlias = "androiddebugkey" | ||
| 98 | keyPassword = "android" | ||
| 99 | } | ||
| 94 | } | 100 | } |
| 95 | 101 | ||
| 96 | // Define build types, which are orthogonal to product flavors. | 102 | // Define build types, which are orthogonal to product flavors. |
| @@ -101,7 +107,7 @@ android { | |||
| 101 | signingConfig = if (keystoreFile != null) { | 107 | signingConfig = if (keystoreFile != null) { |
| 102 | signingConfigs.getByName("release") | 108 | signingConfigs.getByName("release") |
| 103 | } else { | 109 | } else { |
| 104 | signingConfigs.getByName("debug") | 110 | signingConfigs.getByName("default") |
| 105 | } | 111 | } |
| 106 | 112 | ||
| 107 | resValue("string", "app_name_suffixed", "yuzu") | 113 | resValue("string", "app_name_suffixed", "yuzu") |
| @@ -118,7 +124,7 @@ android { | |||
| 118 | register("relWithDebInfo") { | 124 | register("relWithDebInfo") { |
| 119 | isDefault = true | 125 | isDefault = true |
| 120 | resValue("string", "app_name_suffixed", "yuzu Debug Release") | 126 | resValue("string", "app_name_suffixed", "yuzu Debug Release") |
| 121 | signingConfig = signingConfigs.getByName("debug") | 127 | signingConfig = signingConfigs.getByName("default") |
| 122 | isMinifyEnabled = true | 128 | isMinifyEnabled = true |
| 123 | isDebuggable = true | 129 | isDebuggable = true |
| 124 | proguardFiles( | 130 | proguardFiles( |
| @@ -133,6 +139,7 @@ android { | |||
| 133 | // Signed by debug key disallowing distribution on Play Store. | 139 | // Signed by debug key disallowing distribution on Play Store. |
| 134 | // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. | 140 | // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. |
| 135 | debug { | 141 | debug { |
| 142 | signingConfig = signingConfigs.getByName("default") | ||
| 136 | resValue("string", "app_name_suffixed", "yuzu Debug") | 143 | resValue("string", "app_name_suffixed", "yuzu Debug") |
| 137 | isDebuggable = true | 144 | isDebuggable = true |
| 138 | isJniDebuggable = true | 145 | isJniDebuggable = true |
diff --git a/src/android/app/debug.keystore b/src/android/app/debug.keystore new file mode 100644 index 000000000..e4e194af9 --- /dev/null +++ b/src/android/app/debug.keystore | |||
| Binary files differ | |||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index b7556e353..c408485c6 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | |||
| @@ -21,6 +21,9 @@ import org.yuzu.yuzu_emu.utils.DocumentsTree | |||
| 21 | import org.yuzu.yuzu_emu.utils.FileUtil | 21 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 22 | import org.yuzu.yuzu_emu.utils.Log | 22 | import org.yuzu.yuzu_emu.utils.Log |
| 23 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable | 23 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable |
| 24 | import org.yuzu.yuzu_emu.model.InstallResult | ||
| 25 | import org.yuzu.yuzu_emu.model.Patch | ||
| 26 | import org.yuzu.yuzu_emu.model.GameVerificationResult | ||
| 24 | 27 | ||
| 25 | /** | 28 | /** |
| 26 | * Class which contains methods that interact | 29 | * Class which contains methods that interact |
| @@ -235,9 +238,12 @@ object NativeLibrary { | |||
| 235 | /** | 238 | /** |
| 236 | * Installs a nsp or xci file to nand | 239 | * Installs a nsp or xci file to nand |
| 237 | * @param filename String representation of file uri | 240 | * @param filename String representation of file uri |
| 238 | * @param extension Lowercase string representation of file extension without "." | 241 | * @return int representation of [InstallResult] |
| 239 | */ | 242 | */ |
| 240 | external fun installFileToNand(filename: String, extension: String): Int | 243 | external fun installFileToNand( |
| 244 | filename: String, | ||
| 245 | callback: (max: Long, progress: Long) -> Boolean | ||
| 246 | ): Int | ||
| 241 | 247 | ||
| 242 | external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean | 248 | external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean |
| 243 | 249 | ||
| @@ -535,9 +541,49 @@ object NativeLibrary { | |||
| 535 | * | 541 | * |
| 536 | * @param path Path to game file. Can be a [Uri]. | 542 | * @param path Path to game file. Can be a [Uri]. |
| 537 | * @param programId String representation of a game's program ID | 543 | * @param programId String representation of a game's program ID |
| 538 | * @return Array of pairs where the first value is the name of an addon and the second is the version | 544 | * @return Array of available patches |
| 539 | */ | 545 | */ |
| 540 | external fun getAddonsForFile(path: String, programId: String): Array<Pair<String, String>>? | 546 | external fun getPatchesForFile(path: String, programId: String): Array<Patch>? |
| 547 | |||
| 548 | /** | ||
| 549 | * Removes an update for a given [programId] | ||
| 550 | * @param programId String representation of a game's program ID | ||
| 551 | */ | ||
| 552 | external fun removeUpdate(programId: String) | ||
| 553 | |||
| 554 | /** | ||
| 555 | * Removes all DLC for a [programId] | ||
| 556 | * @param programId String representation of a game's program ID | ||
| 557 | */ | ||
| 558 | external fun removeDLC(programId: String) | ||
| 559 | |||
| 560 | /** | ||
| 561 | * Removes a mod installed for a given [programId] | ||
| 562 | * @param programId String representation of a game's program ID | ||
| 563 | * @param name The name of a mod as given by [getPatchesForFile]. This corresponds with the name | ||
| 564 | * of the mod's directory in a game's load folder. | ||
| 565 | */ | ||
| 566 | external fun removeMod(programId: String, name: String) | ||
| 567 | |||
| 568 | /** | ||
| 569 | * Verifies all installed content | ||
| 570 | * @param callback UI callback for verification progress. Return true in the callback to cancel. | ||
| 571 | * @return Array of content that failed verification. Successful if empty. | ||
| 572 | */ | ||
| 573 | external fun verifyInstalledContents( | ||
| 574 | callback: (max: Long, progress: Long) -> Boolean | ||
| 575 | ): Array<String> | ||
| 576 | |||
| 577 | /** | ||
| 578 | * Verifies the contents of a game | ||
| 579 | * @param path String path to a game | ||
| 580 | * @param callback UI callback for verification progress. Return true in the callback to cancel. | ||
| 581 | * @return Int that is meant to be converted to a [GameVerificationResult] | ||
| 582 | */ | ||
| 583 | external fun verifyGameContents( | ||
| 584 | path: String, | ||
| 585 | callback: (max: Long, progress: Long) -> Boolean | ||
| 586 | ): Int | ||
| 541 | 587 | ||
| 542 | /** | 588 | /** |
| 543 | * Gets the save location for a specific game | 589 | * Gets the save location for a specific game |
| @@ -609,15 +655,4 @@ object NativeLibrary { | |||
| 609 | const val RELEASED = 0 | 655 | const val RELEASED = 0 |
| 610 | const val PRESSED = 1 | 656 | const val PRESSED = 1 |
| 611 | } | 657 | } |
| 612 | |||
| 613 | /** | ||
| 614 | * Result from installFileToNand | ||
| 615 | */ | ||
| 616 | object InstallFileToNandResult { | ||
| 617 | const val Success = 0 | ||
| 618 | const val SuccessFileOverwritten = 1 | ||
| 619 | const val Error = 2 | ||
| 620 | const val ErrorBaseGame = 3 | ||
| 621 | const val ErrorFilenameExtension = 4 | ||
| 622 | } | ||
| 623 | } | 658 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt index 94c151325..ff254d9b7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt | |||
| @@ -6,27 +6,32 @@ package org.yuzu.yuzu_emu.adapters | |||
| 6 | import android.view.LayoutInflater | 6 | import android.view.LayoutInflater |
| 7 | import android.view.ViewGroup | 7 | import android.view.ViewGroup |
| 8 | import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding | 8 | import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding |
| 9 | import org.yuzu.yuzu_emu.model.Addon | 9 | import org.yuzu.yuzu_emu.model.Patch |
| 10 | import org.yuzu.yuzu_emu.model.AddonViewModel | ||
| 10 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder | 11 | import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder |
| 11 | 12 | ||
| 12 | class AddonAdapter : AbstractDiffAdapter<Addon, AddonAdapter.AddonViewHolder>() { | 13 | class AddonAdapter(val addonViewModel: AddonViewModel) : |
| 14 | AbstractDiffAdapter<Patch, AddonAdapter.AddonViewHolder>() { | ||
| 13 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { | 15 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { |
| 14 | ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) | 16 | ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) |
| 15 | .also { return AddonViewHolder(it) } | 17 | .also { return AddonViewHolder(it) } |
| 16 | } | 18 | } |
| 17 | 19 | ||
| 18 | inner class AddonViewHolder(val binding: ListItemAddonBinding) : | 20 | inner class AddonViewHolder(val binding: ListItemAddonBinding) : |
| 19 | AbstractViewHolder<Addon>(binding) { | 21 | AbstractViewHolder<Patch>(binding) { |
| 20 | override fun bind(model: Addon) { | 22 | override fun bind(model: Patch) { |
| 21 | binding.root.setOnClickListener { | 23 | binding.root.setOnClickListener { |
| 22 | binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked | 24 | binding.addonCheckbox.isChecked = !binding.addonCheckbox.isChecked |
| 23 | } | 25 | } |
| 24 | binding.title.text = model.title | 26 | binding.title.text = model.name |
| 25 | binding.version.text = model.version | 27 | binding.version.text = model.version |
| 26 | binding.addonSwitch.setOnCheckedChangeListener { _, checked -> | 28 | binding.addonCheckbox.setOnCheckedChangeListener { _, checked -> |
| 27 | model.enabled = checked | 29 | model.enabled = checked |
| 28 | } | 30 | } |
| 29 | binding.addonSwitch.isChecked = model.enabled | 31 | binding.addonCheckbox.isChecked = model.enabled |
| 32 | binding.buttonDelete.setOnClickListener { | ||
| 33 | addonViewModel.setAddonToDelete(model) | ||
| 34 | } | ||
| 30 | } | 35 | } |
| 31 | } | 36 | } |
| 32 | } | 37 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index e26c2e0ab..b4f4d950f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt | |||
| @@ -3,9 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.adapters | 4 | package org.yuzu.yuzu_emu.adapters |
| 5 | 5 | ||
| 6 | import android.content.Intent | ||
| 7 | import android.graphics.Bitmap | ||
| 8 | import android.graphics.drawable.LayerDrawable | ||
| 9 | import android.net.Uri | 6 | import android.net.Uri |
| 10 | import android.text.TextUtils | 7 | import android.text.TextUtils |
| 11 | import android.view.LayoutInflater | 8 | import android.view.LayoutInflater |
| @@ -15,10 +12,6 @@ import android.widget.Toast | |||
| 15 | import androidx.appcompat.app.AppCompatActivity | 12 | import androidx.appcompat.app.AppCompatActivity |
| 16 | import androidx.core.content.pm.ShortcutInfoCompat | 13 | import androidx.core.content.pm.ShortcutInfoCompat |
| 17 | import androidx.core.content.pm.ShortcutManagerCompat | 14 | import androidx.core.content.pm.ShortcutManagerCompat |
| 18 | import androidx.core.content.res.ResourcesCompat | ||
| 19 | import androidx.core.graphics.drawable.IconCompat | ||
| 20 | import androidx.core.graphics.drawable.toBitmap | ||
| 21 | import androidx.core.graphics.drawable.toDrawable | ||
| 22 | import androidx.documentfile.provider.DocumentFile | 15 | import androidx.documentfile.provider.DocumentFile |
| 23 | import androidx.lifecycle.ViewModelProvider | 16 | import androidx.lifecycle.ViewModelProvider |
| 24 | import androidx.lifecycle.lifecycleScope | 17 | import androidx.lifecycle.lifecycleScope |
| @@ -30,7 +23,6 @@ import kotlinx.coroutines.withContext | |||
| 30 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 23 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 31 | import org.yuzu.yuzu_emu.R | 24 | import org.yuzu.yuzu_emu.R |
| 32 | import org.yuzu.yuzu_emu.YuzuApplication | 25 | import org.yuzu.yuzu_emu.YuzuApplication |
| 33 | import org.yuzu.yuzu_emu.activities.EmulationActivity | ||
| 34 | import org.yuzu.yuzu_emu.databinding.CardGameBinding | 26 | import org.yuzu.yuzu_emu.databinding.CardGameBinding |
| 35 | import org.yuzu.yuzu_emu.model.Game | 27 | import org.yuzu.yuzu_emu.model.Game |
| 36 | import org.yuzu.yuzu_emu.model.GamesViewModel | 28 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| @@ -89,36 +81,13 @@ class GameAdapter(private val activity: AppCompatActivity) : | |||
| 89 | ) | 81 | ) |
| 90 | .apply() | 82 | .apply() |
| 91 | 83 | ||
| 92 | val openIntent = | ||
| 93 | Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply { | ||
| 94 | action = Intent.ACTION_VIEW | ||
| 95 | data = Uri.parse(game.path) | ||
| 96 | } | ||
| 97 | |||
| 98 | activity.lifecycleScope.launch { | 84 | activity.lifecycleScope.launch { |
| 99 | withContext(Dispatchers.IO) { | 85 | withContext(Dispatchers.IO) { |
| 100 | val layerDrawable = ResourcesCompat.getDrawable( | ||
| 101 | YuzuApplication.appContext.resources, | ||
| 102 | R.drawable.shortcut, | ||
| 103 | null | ||
| 104 | ) as LayerDrawable | ||
| 105 | layerDrawable.setDrawableByLayerId( | ||
| 106 | R.id.shortcut_foreground, | ||
| 107 | GameIconUtils.getGameIcon(activity, game) | ||
| 108 | .toDrawable(YuzuApplication.appContext.resources) | ||
| 109 | ) | ||
| 110 | val inset = YuzuApplication.appContext.resources | ||
| 111 | .getDimensionPixelSize(R.dimen.icon_inset) | ||
| 112 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) | ||
| 113 | val shortcut = | 86 | val shortcut = |
| 114 | ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) | 87 | ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) |
| 115 | .setShortLabel(game.title) | 88 | .setShortLabel(game.title) |
| 116 | .setIcon( | 89 | .setIcon(GameIconUtils.getShortcutIcon(activity, game)) |
| 117 | IconCompat.createWithAdaptiveBitmap( | 90 | .setIntent(game.launchIntent) |
| 118 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 119 | ) | ||
| 120 | ) | ||
| 121 | .setIntent(openIntent) | ||
| 122 | .build() | 91 | .build() |
| 123 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) | 92 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) |
| 124 | } | 93 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index 16fb87614..71be2d0b2 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt | |||
| @@ -23,7 +23,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { | |||
| 23 | THEME("theme"), | 23 | THEME("theme"), |
| 24 | THEME_MODE("theme_mode"), | 24 | THEME_MODE("theme_mode"), |
| 25 | OVERLAY_SCALE("control_scale"), | 25 | OVERLAY_SCALE("control_scale"), |
| 26 | OVERLAY_OPACITY("control_opacity"); | 26 | OVERLAY_OPACITY("control_opacity"), |
| 27 | LOCK_DRAWER("lock_drawer"); | ||
| 27 | 28 | ||
| 28 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) | 29 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) |
| 29 | 30 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt index 816336820..adb65812c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt | |||
| @@ -74,7 +74,7 @@ class AddonsFragment : Fragment() { | |||
| 74 | 74 | ||
| 75 | binding.listAddons.apply { | 75 | binding.listAddons.apply { |
| 76 | layoutManager = LinearLayoutManager(requireContext()) | 76 | layoutManager = LinearLayoutManager(requireContext()) |
| 77 | adapter = AddonAdapter() | 77 | adapter = AddonAdapter(addonViewModel) |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | viewLifecycleOwner.lifecycleScope.apply { | 80 | viewLifecycleOwner.lifecycleScope.apply { |
| @@ -110,6 +110,21 @@ class AddonsFragment : Fragment() { | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | launch { | ||
| 114 | repeatOnLifecycle(Lifecycle.State.STARTED) { | ||
| 115 | addonViewModel.addonToDelete.collect { | ||
| 116 | if (it != null) { | ||
| 117 | MessageDialogFragment.newInstance( | ||
| 118 | requireActivity(), | ||
| 119 | titleId = R.string.confirm_uninstall, | ||
| 120 | descriptionId = R.string.confirm_uninstall_description, | ||
| 121 | positiveAction = { addonViewModel.onDeleteAddon(it) } | ||
| 122 | ).show(parentFragmentManager, MessageDialogFragment.TAG) | ||
| 123 | addonViewModel.setAddonToDelete(null) | ||
| 124 | } | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 113 | } | 128 | } |
| 114 | 129 | ||
| 115 | binding.buttonInstall.setOnClickListener { | 130 | binding.buttonInstall.setOnClickListener { |
| @@ -156,22 +171,22 @@ class AddonsFragment : Fragment() { | |||
| 156 | descriptionId = R.string.invalid_directory_description | 171 | descriptionId = R.string.invalid_directory_description |
| 157 | ) | 172 | ) |
| 158 | if (isValid) { | 173 | if (isValid) { |
| 159 | IndeterminateProgressDialogFragment.newInstance( | 174 | ProgressDialogFragment.newInstance( |
| 160 | requireActivity(), | 175 | requireActivity(), |
| 161 | R.string.installing_game_content, | 176 | R.string.installing_game_content, |
| 162 | false | 177 | false |
| 163 | ) { | 178 | ) { progressCallback, _ -> |
| 164 | val parentDirectoryName = externalAddonDirectory.name | 179 | val parentDirectoryName = externalAddonDirectory.name |
| 165 | val internalAddonDirectory = | 180 | val internalAddonDirectory = |
| 166 | File(args.game.addonDir + parentDirectoryName) | 181 | File(args.game.addonDir + parentDirectoryName) |
| 167 | try { | 182 | try { |
| 168 | externalAddonDirectory.copyFilesTo(internalAddonDirectory) | 183 | externalAddonDirectory.copyFilesTo(internalAddonDirectory, progressCallback) |
| 169 | } catch (_: Exception) { | 184 | } catch (_: Exception) { |
| 170 | return@newInstance errorMessage | 185 | return@newInstance errorMessage |
| 171 | } | 186 | } |
| 172 | addonViewModel.refreshAddons() | 187 | addonViewModel.refreshAddons() |
| 173 | return@newInstance getString(R.string.addon_installed_successfully) | 188 | return@newInstance getString(R.string.addon_installed_successfully) |
| 174 | }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) | 189 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) |
| 175 | } else { | 190 | } else { |
| 176 | errorMessage.show(parentFragmentManager, MessageDialogFragment.TAG) | 191 | errorMessage.show(parentFragmentManager, MessageDialogFragment.TAG) |
| 177 | } | 192 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt index 9dabb9c41..bf017cd7c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt | |||
| @@ -75,7 +75,7 @@ class DriverManagerFragment : Fragment() { | |||
| 75 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) | 75 | driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) |
| 76 | binding.toolbarDrivers.setOnMenuItemClickListener { | 76 | binding.toolbarDrivers.setOnMenuItemClickListener { |
| 77 | when (it.itemId) { | 77 | when (it.itemId) { |
| 78 | R.id.menu_driver_clear -> { | 78 | R.id.menu_driver_use_global -> { |
| 79 | StringSetting.DRIVER_PATH.global = true | 79 | StringSetting.DRIVER_PATH.global = true |
| 80 | driverViewModel.updateDriverList() | 80 | driverViewModel.updateDriverList() |
| 81 | (binding.listDrivers.adapter as DriverAdapter) | 81 | (binding.listDrivers.adapter as DriverAdapter) |
| @@ -93,7 +93,7 @@ class DriverManagerFragment : Fragment() { | |||
| 93 | repeatOnLifecycle(Lifecycle.State.STARTED) { | 93 | repeatOnLifecycle(Lifecycle.State.STARTED) { |
| 94 | driverViewModel.showClearButton.collect { | 94 | driverViewModel.showClearButton.collect { |
| 95 | binding.toolbarDrivers.menu | 95 | binding.toolbarDrivers.menu |
| 96 | .findItem(R.id.menu_driver_clear).isVisible = it | 96 | .findItem(R.id.menu_driver_use_global).isVisible = it |
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| @@ -173,11 +173,11 @@ class DriverManagerFragment : Fragment() { | |||
| 173 | return@registerForActivityResult | 173 | return@registerForActivityResult |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | IndeterminateProgressDialogFragment.newInstance( | 176 | ProgressDialogFragment.newInstance( |
| 177 | requireActivity(), | 177 | requireActivity(), |
| 178 | R.string.installing_driver, | 178 | R.string.installing_driver, |
| 179 | false | 179 | false |
| 180 | ) { | 180 | ) { _, _ -> |
| 181 | val driverPath = | 181 | val driverPath = |
| 182 | "${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(result)}" | 182 | "${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(result)}" |
| 183 | val driverFile = File(driverPath) | 183 | val driverFile = File(driverPath) |
| @@ -213,6 +213,6 @@ class DriverManagerFragment : Fragment() { | |||
| 213 | } | 213 | } |
| 214 | } | 214 | } |
| 215 | return@newInstance Any() | 215 | return@newInstance Any() |
| 216 | }.show(childFragmentManager, IndeterminateProgressDialogFragment.TAG) | 216 | }.show(childFragmentManager, ProgressDialogFragment.TAG) |
| 217 | } | 217 | } |
| 218 | } | 218 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index 47767454a..2a97ae14d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt | |||
| @@ -182,11 +182,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | override fun onDrawerOpened(drawerView: View) { | 184 | override fun onDrawerOpened(drawerView: View) { |
| 185 | // No op | 185 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | override fun onDrawerClosed(drawerView: View) { | 188 | override fun onDrawerClosed(drawerView: View) { |
| 189 | // No op | 189 | binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt()) |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | override fun onDrawerStateChanged(newState: Int) { | 192 | override fun onDrawerStateChanged(newState: Int) { |
| @@ -196,6 +196,28 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 196 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) | 196 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) |
| 197 | binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text = | 197 | binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text = |
| 198 | game.title | 198 | game.title |
| 199 | |||
| 200 | binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply { | ||
| 201 | val lockMode = IntSetting.LOCK_DRAWER.getInt() | ||
| 202 | val titleId = if (lockMode == DrawerLayout.LOCK_MODE_LOCKED_CLOSED) { | ||
| 203 | R.string.unlock_drawer | ||
| 204 | } else { | ||
| 205 | R.string.lock_drawer | ||
| 206 | } | ||
| 207 | val iconId = if (lockMode == DrawerLayout.LOCK_MODE_UNLOCKED) { | ||
| 208 | R.drawable.ic_unlock | ||
| 209 | } else { | ||
| 210 | R.drawable.ic_lock | ||
| 211 | } | ||
| 212 | |||
| 213 | title = getString(titleId) | ||
| 214 | icon = ResourcesCompat.getDrawable( | ||
| 215 | resources, | ||
| 216 | iconId, | ||
| 217 | requireContext().theme | ||
| 218 | ) | ||
| 219 | } | ||
| 220 | |||
| 199 | binding.inGameMenu.setNavigationItemSelectedListener { | 221 | binding.inGameMenu.setNavigationItemSelectedListener { |
| 200 | when (it.itemId) { | 222 | when (it.itemId) { |
| 201 | R.id.menu_pause_emulation -> { | 223 | R.id.menu_pause_emulation -> { |
| @@ -242,6 +264,32 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 242 | true | 264 | true |
| 243 | } | 265 | } |
| 244 | 266 | ||
| 267 | R.id.menu_lock_drawer -> { | ||
| 268 | when (IntSetting.LOCK_DRAWER.getInt()) { | ||
| 269 | DrawerLayout.LOCK_MODE_UNLOCKED -> { | ||
| 270 | IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) | ||
| 271 | it.title = resources.getString(R.string.unlock_drawer) | ||
| 272 | it.icon = ResourcesCompat.getDrawable( | ||
| 273 | resources, | ||
| 274 | R.drawable.ic_lock, | ||
| 275 | requireContext().theme | ||
| 276 | ) | ||
| 277 | } | ||
| 278 | |||
| 279 | DrawerLayout.LOCK_MODE_LOCKED_CLOSED -> { | ||
| 280 | IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_UNLOCKED) | ||
| 281 | it.title = resources.getString(R.string.lock_drawer) | ||
| 282 | it.icon = ResourcesCompat.getDrawable( | ||
| 283 | resources, | ||
| 284 | R.drawable.ic_unlock, | ||
| 285 | requireContext().theme | ||
| 286 | ) | ||
| 287 | } | ||
| 288 | } | ||
| 289 | NativeConfig.saveGlobalConfig() | ||
| 290 | true | ||
| 291 | } | ||
| 292 | |||
| 245 | R.id.menu_exit -> { | 293 | R.id.menu_exit -> { |
| 246 | emulationState.stop() | 294 | emulationState.stop() |
| 247 | emulationViewModel.setIsEmulationStopping(true) | 295 | emulationViewModel.setIsEmulationStopping(true) |
| @@ -326,7 +374,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 326 | repeatOnLifecycle(Lifecycle.State.CREATED) { | 374 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| 327 | emulationViewModel.emulationStarted.collectLatest { | 375 | emulationViewModel.emulationStarted.collectLatest { |
| 328 | if (it) { | 376 | if (it) { |
| 329 | binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) | 377 | binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt()) |
| 330 | ViewUtils.showView(binding.surfaceInputOverlay) | 378 | ViewUtils.showView(binding.surfaceInputOverlay) |
| 331 | ViewUtils.hideView(binding.loadingIndicator) | 379 | ViewUtils.hideView(binding.loadingIndicator) |
| 332 | 380 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt index fa2a4c9f9..5aa3f453f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt | |||
| @@ -21,8 +21,10 @@ import androidx.fragment.app.activityViewModels | |||
| 21 | import androidx.navigation.findNavController | 21 | import androidx.navigation.findNavController |
| 22 | import androidx.navigation.fragment.navArgs | 22 | import androidx.navigation.fragment.navArgs |
| 23 | import com.google.android.material.transition.MaterialSharedAxis | 23 | import com.google.android.material.transition.MaterialSharedAxis |
| 24 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 24 | import org.yuzu.yuzu_emu.R | 25 | import org.yuzu.yuzu_emu.R |
| 25 | import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding | 26 | import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding |
| 27 | import org.yuzu.yuzu_emu.model.GameVerificationResult | ||
| 26 | import org.yuzu.yuzu_emu.model.HomeViewModel | 28 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 27 | import org.yuzu.yuzu_emu.utils.GameMetadata | 29 | import org.yuzu.yuzu_emu.utils.GameMetadata |
| 28 | 30 | ||
| @@ -101,6 +103,38 @@ class GameInfoFragment : Fragment() { | |||
| 101 | """.trimIndent() | 103 | """.trimIndent() |
| 102 | copyToClipboard(args.game.title, details) | 104 | copyToClipboard(args.game.title, details) |
| 103 | } | 105 | } |
| 106 | |||
| 107 | buttonVerifyIntegrity.setOnClickListener { | ||
| 108 | ProgressDialogFragment.newInstance( | ||
| 109 | requireActivity(), | ||
| 110 | R.string.verifying, | ||
| 111 | true | ||
| 112 | ) { progressCallback, _ -> | ||
| 113 | val result = GameVerificationResult.from( | ||
| 114 | NativeLibrary.verifyGameContents( | ||
| 115 | args.game.path, | ||
| 116 | progressCallback | ||
| 117 | ) | ||
| 118 | ) | ||
| 119 | return@newInstance when (result) { | ||
| 120 | GameVerificationResult.Success -> | ||
| 121 | MessageDialogFragment.newInstance( | ||
| 122 | titleId = R.string.verify_success, | ||
| 123 | descriptionId = R.string.operation_completed_successfully | ||
| 124 | ) | ||
| 125 | GameVerificationResult.Failed -> | ||
| 126 | MessageDialogFragment.newInstance( | ||
| 127 | titleId = R.string.verify_failure, | ||
| 128 | descriptionId = R.string.verify_failure_description | ||
| 129 | ) | ||
| 130 | GameVerificationResult.NotImplemented -> | ||
| 131 | MessageDialogFragment.newInstance( | ||
| 132 | titleId = R.string.verify_no_result, | ||
| 133 | descriptionId = R.string.verify_no_result_description | ||
| 134 | ) | ||
| 135 | } | ||
| 136 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) | ||
| 137 | } | ||
| 104 | } | 138 | } |
| 105 | 139 | ||
| 106 | setInsets() | 140 | setInsets() |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt index b04d1208f..582df0133 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | package org.yuzu.yuzu_emu.fragments | 4 | package org.yuzu.yuzu_emu.fragments |
| 5 | 5 | ||
| 6 | import android.annotation.SuppressLint | 6 | import android.annotation.SuppressLint |
| 7 | import android.content.pm.ShortcutInfo | ||
| 8 | import android.content.pm.ShortcutManager | ||
| 7 | import android.os.Bundle | 9 | import android.os.Bundle |
| 8 | import android.text.TextUtils | 10 | import android.text.TextUtils |
| 9 | import android.view.LayoutInflater | 11 | import android.view.LayoutInflater |
| @@ -44,7 +46,6 @@ import org.yuzu.yuzu_emu.utils.FileUtil | |||
| 44 | import org.yuzu.yuzu_emu.utils.GameIconUtils | 46 | import org.yuzu.yuzu_emu.utils.GameIconUtils |
| 45 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 47 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper |
| 46 | import org.yuzu.yuzu_emu.utils.MemoryUtil | 48 | import org.yuzu.yuzu_emu.utils.MemoryUtil |
| 47 | import java.io.BufferedInputStream | ||
| 48 | import java.io.BufferedOutputStream | 49 | import java.io.BufferedOutputStream |
| 49 | import java.io.File | 50 | import java.io.File |
| 50 | 51 | ||
| @@ -85,6 +86,24 @@ class GamePropertiesFragment : Fragment() { | |||
| 85 | view.findNavController().popBackStack() | 86 | view.findNavController().popBackStack() |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 89 | val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java) | ||
| 90 | binding.buttonShortcut.isEnabled = shortcutManager.isRequestPinShortcutSupported | ||
| 91 | binding.buttonShortcut.setOnClickListener { | ||
| 92 | viewLifecycleOwner.lifecycleScope.launch { | ||
| 93 | withContext(Dispatchers.IO) { | ||
| 94 | val shortcut = ShortcutInfo.Builder(requireContext(), args.game.title) | ||
| 95 | .setShortLabel(args.game.title) | ||
| 96 | .setIcon( | ||
| 97 | GameIconUtils.getShortcutIcon(requireActivity(), args.game) | ||
| 98 | .toIcon(requireContext()) | ||
| 99 | ) | ||
| 100 | .setIntent(args.game.launchIntent) | ||
| 101 | .build() | ||
| 102 | shortcutManager.requestPinShortcut(shortcut, null) | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 88 | GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen) | 107 | GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen) |
| 89 | binding.title.text = args.game.title | 108 | binding.title.text = args.game.title |
| 90 | binding.title.postDelayed( | 109 | binding.title.postDelayed( |
| @@ -357,27 +376,17 @@ class GamePropertiesFragment : Fragment() { | |||
| 357 | return@registerForActivityResult | 376 | return@registerForActivityResult |
| 358 | } | 377 | } |
| 359 | 378 | ||
| 360 | val inputZip = requireContext().contentResolver.openInputStream(result) | ||
| 361 | val savesFolder = File(args.game.saveDir) | 379 | val savesFolder = File(args.game.saveDir) |
| 362 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") | 380 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") |
| 363 | cacheSaveDir.mkdir() | 381 | cacheSaveDir.mkdir() |
| 364 | 382 | ||
| 365 | if (inputZip == null) { | 383 | ProgressDialogFragment.newInstance( |
| 366 | Toast.makeText( | ||
| 367 | YuzuApplication.appContext, | ||
| 368 | getString(R.string.fatal_error), | ||
| 369 | Toast.LENGTH_LONG | ||
| 370 | ).show() | ||
| 371 | return@registerForActivityResult | ||
| 372 | } | ||
| 373 | |||
| 374 | IndeterminateProgressDialogFragment.newInstance( | ||
| 375 | requireActivity(), | 384 | requireActivity(), |
| 376 | R.string.save_files_importing, | 385 | R.string.save_files_importing, |
| 377 | false | 386 | false |
| 378 | ) { | 387 | ) { _, _ -> |
| 379 | try { | 388 | try { |
| 380 | FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheSaveDir) | 389 | FileUtil.unzipToInternalStorage(result.toString(), cacheSaveDir) |
| 381 | val files = cacheSaveDir.listFiles() | 390 | val files = cacheSaveDir.listFiles() |
| 382 | var savesFolderFile: File? = null | 391 | var savesFolderFile: File? = null |
| 383 | if (files != null) { | 392 | if (files != null) { |
| @@ -422,7 +431,7 @@ class GamePropertiesFragment : Fragment() { | |||
| 422 | Toast.LENGTH_LONG | 431 | Toast.LENGTH_LONG |
| 423 | ).show() | 432 | ).show() |
| 424 | } | 433 | } |
| 425 | }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) | 434 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) |
| 426 | } | 435 | } |
| 427 | 436 | ||
| 428 | /** | 437 | /** |
| @@ -436,11 +445,11 @@ class GamePropertiesFragment : Fragment() { | |||
| 436 | return@registerForActivityResult | 445 | return@registerForActivityResult |
| 437 | } | 446 | } |
| 438 | 447 | ||
| 439 | IndeterminateProgressDialogFragment.newInstance( | 448 | ProgressDialogFragment.newInstance( |
| 440 | requireActivity(), | 449 | requireActivity(), |
| 441 | R.string.save_files_exporting, | 450 | R.string.save_files_exporting, |
| 442 | false | 451 | false |
| 443 | ) { | 452 | ) { _, _ -> |
| 444 | val saveLocation = args.game.saveDir | 453 | val saveLocation = args.game.saveDir |
| 445 | val zipResult = FileUtil.zipFromInternalStorage( | 454 | val zipResult = FileUtil.zipFromInternalStorage( |
| 446 | File(saveLocation), | 455 | File(saveLocation), |
| @@ -452,6 +461,6 @@ class GamePropertiesFragment : Fragment() { | |||
| 452 | TaskState.Completed -> getString(R.string.export_success) | 461 | TaskState.Completed -> getString(R.string.export_success) |
| 453 | TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) | 462 | TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) |
| 454 | } | 463 | } |
| 455 | }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) | 464 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) |
| 456 | } | 465 | } |
| 457 | } | 466 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt index 6ddd758e6..aefae2938 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt | |||
| @@ -32,6 +32,7 @@ import org.yuzu.yuzu_emu.BuildConfig | |||
| 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.NativeLibrary |
| 34 | import org.yuzu.yuzu_emu.R | 34 | import org.yuzu.yuzu_emu.R |
| 35 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 35 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter | 36 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter |
| 36 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding | 37 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding |
| 37 | import org.yuzu.yuzu_emu.features.DocumentProvider | 38 | import org.yuzu.yuzu_emu.features.DocumentProvider |
| @@ -142,6 +143,38 @@ class HomeSettingsFragment : Fragment() { | |||
| 142 | ) | 143 | ) |
| 143 | add( | 144 | add( |
| 144 | HomeSetting( | 145 | HomeSetting( |
| 146 | R.string.verify_installed_content, | ||
| 147 | R.string.verify_installed_content_description, | ||
| 148 | R.drawable.ic_check_circle, | ||
| 149 | { | ||
| 150 | ProgressDialogFragment.newInstance( | ||
| 151 | requireActivity(), | ||
| 152 | titleId = R.string.verifying, | ||
| 153 | cancellable = true | ||
| 154 | ) { progressCallback, _ -> | ||
| 155 | val result = NativeLibrary.verifyInstalledContents(progressCallback) | ||
| 156 | return@newInstance if (result.isEmpty()) { | ||
| 157 | MessageDialogFragment.newInstance( | ||
| 158 | titleId = R.string.verify_success, | ||
| 159 | descriptionId = R.string.operation_completed_successfully | ||
| 160 | ) | ||
| 161 | } else { | ||
| 162 | val failedNames = result.joinToString("\n") | ||
| 163 | val errorMessage = YuzuApplication.appContext.getString( | ||
| 164 | R.string.verification_failed_for, | ||
| 165 | failedNames | ||
| 166 | ) | ||
| 167 | MessageDialogFragment.newInstance( | ||
| 168 | titleId = R.string.verify_failure, | ||
| 169 | descriptionString = errorMessage | ||
| 170 | ) | ||
| 171 | } | ||
| 172 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) | ||
| 173 | } | ||
| 174 | ) | ||
| 175 | ) | ||
| 176 | add( | ||
| 177 | HomeSetting( | ||
| 145 | R.string.share_log, | 178 | R.string.share_log, |
| 146 | R.string.share_log_description, | 179 | R.string.share_log_description, |
| 147 | R.drawable.ic_log, | 180 | R.drawable.ic_log, |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt index 5b4bf2c9f..7df8e6bf4 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt | |||
| @@ -34,7 +34,6 @@ import org.yuzu.yuzu_emu.model.TaskState | |||
| 34 | import org.yuzu.yuzu_emu.ui.main.MainActivity | 34 | import org.yuzu.yuzu_emu.ui.main.MainActivity |
| 35 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | 35 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization |
| 36 | import org.yuzu.yuzu_emu.utils.FileUtil | 36 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 37 | import java.io.BufferedInputStream | ||
| 38 | import java.io.BufferedOutputStream | 37 | import java.io.BufferedOutputStream |
| 39 | import java.io.File | 38 | import java.io.File |
| 40 | import java.math.BigInteger | 39 | import java.math.BigInteger |
| @@ -195,26 +194,20 @@ class InstallableFragment : Fragment() { | |||
| 195 | return@registerForActivityResult | 194 | return@registerForActivityResult |
| 196 | } | 195 | } |
| 197 | 196 | ||
| 198 | val inputZip = requireContext().contentResolver.openInputStream(result) | ||
| 199 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") | 197 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") |
| 200 | cacheSaveDir.mkdir() | 198 | cacheSaveDir.mkdir() |
| 201 | 199 | ||
| 202 | if (inputZip == null) { | 200 | ProgressDialogFragment.newInstance( |
| 203 | Toast.makeText( | ||
| 204 | YuzuApplication.appContext, | ||
| 205 | getString(R.string.fatal_error), | ||
| 206 | Toast.LENGTH_LONG | ||
| 207 | ).show() | ||
| 208 | return@registerForActivityResult | ||
| 209 | } | ||
| 210 | |||
| 211 | IndeterminateProgressDialogFragment.newInstance( | ||
| 212 | requireActivity(), | 201 | requireActivity(), |
| 213 | R.string.save_files_importing, | 202 | R.string.save_files_importing, |
| 214 | false | 203 | false |
| 215 | ) { | 204 | ) { progressCallback, _ -> |
| 216 | try { | 205 | try { |
| 217 | FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheSaveDir) | 206 | FileUtil.unzipToInternalStorage( |
| 207 | result.toString(), | ||
| 208 | cacheSaveDir, | ||
| 209 | progressCallback | ||
| 210 | ) | ||
| 218 | val files = cacheSaveDir.listFiles() | 211 | val files = cacheSaveDir.listFiles() |
| 219 | var successfulImports = 0 | 212 | var successfulImports = 0 |
| 220 | var failedImports = 0 | 213 | var failedImports = 0 |
| @@ -287,7 +280,7 @@ class InstallableFragment : Fragment() { | |||
| 287 | Toast.LENGTH_LONG | 280 | Toast.LENGTH_LONG |
| 288 | ).show() | 281 | ).show() |
| 289 | } | 282 | } |
| 290 | }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) | 283 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) |
| 291 | } | 284 | } |
| 292 | 285 | ||
| 293 | private val exportSaves = registerForActivityResult( | 286 | private val exportSaves = registerForActivityResult( |
| @@ -297,11 +290,11 @@ class InstallableFragment : Fragment() { | |||
| 297 | return@registerForActivityResult | 290 | return@registerForActivityResult |
| 298 | } | 291 | } |
| 299 | 292 | ||
| 300 | IndeterminateProgressDialogFragment.newInstance( | 293 | ProgressDialogFragment.newInstance( |
| 301 | requireActivity(), | 294 | requireActivity(), |
| 302 | R.string.save_files_exporting, | 295 | R.string.save_files_exporting, |
| 303 | false | 296 | false |
| 304 | ) { | 297 | ) { _, _ -> |
| 305 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") | 298 | val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") |
| 306 | cacheSaveDir.mkdir() | 299 | cacheSaveDir.mkdir() |
| 307 | 300 | ||
| @@ -338,6 +331,6 @@ class InstallableFragment : Fragment() { | |||
| 338 | TaskState.Completed -> getString(R.string.export_success) | 331 | TaskState.Completed -> getString(R.string.export_success) |
| 339 | TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) | 332 | TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) |
| 340 | } | 333 | } |
| 341 | }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) | 334 | }.show(parentFragmentManager, ProgressDialogFragment.TAG) |
| 342 | } | 335 | } |
| 343 | } | 336 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt index 32062b6fe..620d8db7c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt | |||
| @@ -69,7 +69,7 @@ class MessageDialogFragment : DialogFragment() { | |||
| 69 | private const val HELP_LINK = "Link" | 69 | private const val HELP_LINK = "Link" |
| 70 | 70 | ||
| 71 | fun newInstance( | 71 | fun newInstance( |
| 72 | activity: FragmentActivity, | 72 | activity: FragmentActivity? = null, |
| 73 | titleId: Int = 0, | 73 | titleId: Int = 0, |
| 74 | titleString: String = "", | 74 | titleString: String = "", |
| 75 | descriptionId: Int = 0, | 75 | descriptionId: Int = 0, |
| @@ -86,9 +86,11 @@ class MessageDialogFragment : DialogFragment() { | |||
| 86 | putString(DESCRIPTION_STRING, descriptionString) | 86 | putString(DESCRIPTION_STRING, descriptionString) |
| 87 | putInt(HELP_LINK, helpLinkId) | 87 | putInt(HELP_LINK, helpLinkId) |
| 88 | } | 88 | } |
| 89 | ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply { | 89 | if (activity != null) { |
| 90 | clear() | 90 | ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply { |
| 91 | this.positiveAction = positiveAction | 91 | clear() |
| 92 | this.positiveAction = positiveAction | ||
| 93 | } | ||
| 92 | } | 94 | } |
| 93 | dialog.arguments = bundle | 95 | dialog.arguments = bundle |
| 94 | return dialog | 96 | return dialog |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProgressDialogFragment.kt index 8847e5531..d201cb80c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProgressDialogFragment.kt | |||
| @@ -23,11 +23,13 @@ import org.yuzu.yuzu_emu.R | |||
| 23 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding | 23 | import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding |
| 24 | import org.yuzu.yuzu_emu.model.TaskViewModel | 24 | import org.yuzu.yuzu_emu.model.TaskViewModel |
| 25 | 25 | ||
| 26 | class IndeterminateProgressDialogFragment : DialogFragment() { | 26 | class ProgressDialogFragment : DialogFragment() { |
| 27 | private val taskViewModel: TaskViewModel by activityViewModels() | 27 | private val taskViewModel: TaskViewModel by activityViewModels() |
| 28 | 28 | ||
| 29 | private lateinit var binding: DialogProgressBarBinding | 29 | private lateinit var binding: DialogProgressBarBinding |
| 30 | 30 | ||
| 31 | private val PROGRESS_BAR_RESOLUTION = 1000 | ||
| 32 | |||
| 31 | override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | 33 | override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { |
| 32 | val titleId = requireArguments().getInt(TITLE) | 34 | val titleId = requireArguments().getInt(TITLE) |
| 33 | val cancellable = requireArguments().getBoolean(CANCELLABLE) | 35 | val cancellable = requireArguments().getBoolean(CANCELLABLE) |
| @@ -61,6 +63,7 @@ class IndeterminateProgressDialogFragment : DialogFragment() { | |||
| 61 | 63 | ||
| 62 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | 64 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
| 63 | super.onViewCreated(view, savedInstanceState) | 65 | super.onViewCreated(view, savedInstanceState) |
| 66 | binding.message.isSelected = true | ||
| 64 | viewLifecycleOwner.lifecycleScope.apply { | 67 | viewLifecycleOwner.lifecycleScope.apply { |
| 65 | launch { | 68 | launch { |
| 66 | repeatOnLifecycle(Lifecycle.State.CREATED) { | 69 | repeatOnLifecycle(Lifecycle.State.CREATED) { |
| @@ -97,6 +100,35 @@ class IndeterminateProgressDialogFragment : DialogFragment() { | |||
| 97 | } | 100 | } |
| 98 | } | 101 | } |
| 99 | } | 102 | } |
| 103 | launch { | ||
| 104 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 105 | taskViewModel.progress.collect { | ||
| 106 | if (it != 0.0) { | ||
| 107 | binding.progressBar.apply { | ||
| 108 | isIndeterminate = false | ||
| 109 | progress = ( | ||
| 110 | (it / taskViewModel.maxProgress.value) * | ||
| 111 | PROGRESS_BAR_RESOLUTION | ||
| 112 | ).toInt() | ||
| 113 | min = 0 | ||
| 114 | max = PROGRESS_BAR_RESOLUTION | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | launch { | ||
| 121 | repeatOnLifecycle(Lifecycle.State.CREATED) { | ||
| 122 | taskViewModel.message.collect { | ||
| 123 | if (it.isEmpty()) { | ||
| 124 | binding.message.visibility = View.GONE | ||
| 125 | } else { | ||
| 126 | binding.message.visibility = View.VISIBLE | ||
| 127 | binding.message.text = it | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 100 | } | 132 | } |
| 101 | } | 133 | } |
| 102 | 134 | ||
| @@ -108,6 +140,7 @@ class IndeterminateProgressDialogFragment : DialogFragment() { | |||
| 108 | val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE) | 140 | val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE) |
| 109 | negativeButton.setOnClickListener { | 141 | negativeButton.setOnClickListener { |
| 110 | alertDialog.setTitle(getString(R.string.cancelling)) | 142 | alertDialog.setTitle(getString(R.string.cancelling)) |
| 143 | binding.progressBar.isIndeterminate = true | ||
| 111 | taskViewModel.setCancelled(true) | 144 | taskViewModel.setCancelled(true) |
| 112 | } | 145 | } |
| 113 | } | 146 | } |
| @@ -122,9 +155,12 @@ class IndeterminateProgressDialogFragment : DialogFragment() { | |||
| 122 | activity: FragmentActivity, | 155 | activity: FragmentActivity, |
| 123 | titleId: Int, | 156 | titleId: Int, |
| 124 | cancellable: Boolean = false, | 157 | cancellable: Boolean = false, |
| 125 | task: suspend () -> Any | 158 | task: suspend ( |
| 126 | ): IndeterminateProgressDialogFragment { | 159 | progressCallback: (max: Long, progress: Long) -> Boolean, |
| 127 | val dialog = IndeterminateProgressDialogFragment() | 160 | messageCallback: (message: String) -> Unit |
| 161 | ) -> Any | ||
| 162 | ): ProgressDialogFragment { | ||
| 163 | val dialog = ProgressDialogFragment() | ||
| 128 | val args = Bundle() | 164 | val args = Bundle() |
| 129 | ViewModelProvider(activity)[TaskViewModel::class.java].task = task | 165 | ViewModelProvider(activity)[TaskViewModel::class.java].task = task |
| 130 | args.putInt(TITLE, titleId) | 166 | args.putInt(TITLE, titleId) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt index 64b295fbd..20b10b1a0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt | |||
| @@ -136,14 +136,14 @@ class SearchFragment : Fragment() { | |||
| 136 | baseList.filter { | 136 | baseList.filter { |
| 137 | val lastPlayedTime = preferences.getLong(it.keyLastPlayedTime, 0L) | 137 | val lastPlayedTime = preferences.getLong(it.keyLastPlayedTime, 0L) |
| 138 | lastPlayedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) | 138 | lastPlayedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) |
| 139 | } | 139 | }.sortedByDescending { preferences.getLong(it.keyLastPlayedTime, 0L) } |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | R.id.chip_recently_added -> { | 142 | R.id.chip_recently_added -> { |
| 143 | baseList.filter { | 143 | baseList.filter { |
| 144 | val addedTime = preferences.getLong(it.keyAddedToLibraryTime, 0L) | 144 | val addedTime = preferences.getLong(it.keyAddedToLibraryTime, 0L) |
| 145 | addedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) | 145 | addedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) |
| 146 | } | 146 | }.sortedByDescending { preferences.getLong(it.keyAddedToLibraryTime, 0L) } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | R.id.chip_homebrew -> baseList.filter { it.isHomebrew } | 149 | R.id.chip_homebrew -> baseList.filter { it.isHomebrew } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt deleted file mode 100644 index ed79a8b02..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | data class Addon( | ||
| 7 | var enabled: Boolean, | ||
| 8 | val title: String, | ||
| 9 | val version: String | ||
| 10 | ) | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt index 075252f5b..b9c8e49ca 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt | |||
| @@ -15,8 +15,8 @@ import org.yuzu.yuzu_emu.utils.NativeConfig | |||
| 15 | import java.util.concurrent.atomic.AtomicBoolean | 15 | import java.util.concurrent.atomic.AtomicBoolean |
| 16 | 16 | ||
| 17 | class AddonViewModel : ViewModel() { | 17 | class AddonViewModel : ViewModel() { |
| 18 | private val _addonList = MutableStateFlow(mutableListOf<Addon>()) | 18 | private val _patchList = MutableStateFlow(mutableListOf<Patch>()) |
| 19 | val addonList get() = _addonList.asStateFlow() | 19 | val addonList get() = _patchList.asStateFlow() |
| 20 | 20 | ||
| 21 | private val _showModInstallPicker = MutableStateFlow(false) | 21 | private val _showModInstallPicker = MutableStateFlow(false) |
| 22 | val showModInstallPicker get() = _showModInstallPicker.asStateFlow() | 22 | val showModInstallPicker get() = _showModInstallPicker.asStateFlow() |
| @@ -24,6 +24,9 @@ class AddonViewModel : ViewModel() { | |||
| 24 | private val _showModNoticeDialog = MutableStateFlow(false) | 24 | private val _showModNoticeDialog = MutableStateFlow(false) |
| 25 | val showModNoticeDialog get() = _showModNoticeDialog.asStateFlow() | 25 | val showModNoticeDialog get() = _showModNoticeDialog.asStateFlow() |
| 26 | 26 | ||
| 27 | private val _addonToDelete = MutableStateFlow<Patch?>(null) | ||
| 28 | val addonToDelete = _addonToDelete.asStateFlow() | ||
| 29 | |||
| 27 | var game: Game? = null | 30 | var game: Game? = null |
| 28 | 31 | ||
| 29 | private val isRefreshing = AtomicBoolean(false) | 32 | private val isRefreshing = AtomicBoolean(false) |
| @@ -40,36 +43,47 @@ class AddonViewModel : ViewModel() { | |||
| 40 | isRefreshing.set(true) | 43 | isRefreshing.set(true) |
| 41 | viewModelScope.launch { | 44 | viewModelScope.launch { |
| 42 | withContext(Dispatchers.IO) { | 45 | withContext(Dispatchers.IO) { |
| 43 | val addonList = mutableListOf<Addon>() | 46 | val patchList = ( |
| 44 | val disabledAddons = NativeConfig.getDisabledAddons(game!!.programId) | 47 | NativeLibrary.getPatchesForFile(game!!.path, game!!.programId) |
| 45 | NativeLibrary.getAddonsForFile(game!!.path, game!!.programId)?.forEach { | 48 | ?: emptyArray() |
| 46 | val name = it.first.replace("[D] ", "") | 49 | ).toMutableList() |
| 47 | addonList.add(Addon(!disabledAddons.contains(name), name, it.second)) | 50 | patchList.sortBy { it.name } |
| 48 | } | 51 | _patchList.value = patchList |
| 49 | addonList.sortBy { it.title } | ||
| 50 | _addonList.value = addonList | ||
| 51 | isRefreshing.set(false) | 52 | isRefreshing.set(false) |
| 52 | } | 53 | } |
| 53 | } | 54 | } |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | fun setAddonToDelete(patch: Patch?) { | ||
| 58 | _addonToDelete.value = patch | ||
| 59 | } | ||
| 60 | |||
| 61 | fun onDeleteAddon(patch: Patch) { | ||
| 62 | when (PatchType.from(patch.type)) { | ||
| 63 | PatchType.Update -> NativeLibrary.removeUpdate(patch.programId) | ||
| 64 | PatchType.DLC -> NativeLibrary.removeDLC(patch.programId) | ||
| 65 | PatchType.Mod -> NativeLibrary.removeMod(patch.programId, patch.name) | ||
| 66 | } | ||
| 67 | refreshAddons() | ||
| 68 | } | ||
| 69 | |||
| 56 | fun onCloseAddons() { | 70 | fun onCloseAddons() { |
| 57 | if (_addonList.value.isEmpty()) { | 71 | if (_patchList.value.isEmpty()) { |
| 58 | return | 72 | return |
| 59 | } | 73 | } |
| 60 | 74 | ||
| 61 | NativeConfig.setDisabledAddons( | 75 | NativeConfig.setDisabledAddons( |
| 62 | game!!.programId, | 76 | game!!.programId, |
| 63 | _addonList.value.mapNotNull { | 77 | _patchList.value.mapNotNull { |
| 64 | if (it.enabled) { | 78 | if (it.enabled) { |
| 65 | null | 79 | null |
| 66 | } else { | 80 | } else { |
| 67 | it.title | 81 | it.name |
| 68 | } | 82 | } |
| 69 | }.toTypedArray() | 83 | }.toTypedArray() |
| 70 | ) | 84 | ) |
| 71 | NativeConfig.saveGlobalConfig() | 85 | NativeConfig.saveGlobalConfig() |
| 72 | _addonList.value.clear() | 86 | _patchList.value.clear() |
| 73 | game = null | 87 | game = null |
| 74 | } | 88 | } |
| 75 | 89 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt index f1ea1e20f..c8a4a2d17 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | package org.yuzu.yuzu_emu.model | 4 | package org.yuzu.yuzu_emu.model |
| 5 | 5 | ||
| 6 | import android.content.Intent | ||
| 6 | import android.net.Uri | 7 | import android.net.Uri |
| 7 | import android.os.Parcelable | 8 | import android.os.Parcelable |
| 8 | import java.util.HashSet | 9 | import java.util.HashSet |
| @@ -11,6 +12,7 @@ import kotlinx.serialization.Serializable | |||
| 11 | import org.yuzu.yuzu_emu.NativeLibrary | 12 | import org.yuzu.yuzu_emu.NativeLibrary |
| 12 | import org.yuzu.yuzu_emu.R | 13 | import org.yuzu.yuzu_emu.R |
| 13 | import org.yuzu.yuzu_emu.YuzuApplication | 14 | import org.yuzu.yuzu_emu.YuzuApplication |
| 15 | import org.yuzu.yuzu_emu.activities.EmulationActivity | ||
| 14 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | 16 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization |
| 15 | import org.yuzu.yuzu_emu.utils.FileUtil | 17 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 16 | import java.time.LocalDateTime | 18 | import java.time.LocalDateTime |
| @@ -61,6 +63,12 @@ class Game( | |||
| 61 | val addonDir: String | 63 | val addonDir: String |
| 62 | get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/" | 64 | get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/" |
| 63 | 65 | ||
| 66 | val launchIntent: Intent | ||
| 67 | get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply { | ||
| 68 | action = Intent.ACTION_VIEW | ||
| 69 | data = Uri.parse(path) | ||
| 70 | } | ||
| 71 | |||
| 64 | override fun equals(other: Any?): Boolean { | 72 | override fun equals(other: Any?): Boolean { |
| 65 | if (other !is Game) { | 73 | if (other !is Game) { |
| 66 | return false | 74 | return false |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt new file mode 100644 index 000000000..804637fb8 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | enum class GameVerificationResult(val int: Int) { | ||
| 7 | Success(0), | ||
| 8 | Failed(1), | ||
| 9 | NotImplemented(2); | ||
| 10 | |||
| 11 | companion object { | ||
| 12 | fun from(int: Int): GameVerificationResult = | ||
| 13 | entries.firstOrNull { it.int == int } ?: Success | ||
| 14 | } | ||
| 15 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt new file mode 100644 index 000000000..0c3cd0521 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | enum class InstallResult(val int: Int) { | ||
| 7 | Success(0), | ||
| 8 | Overwrite(1), | ||
| 9 | Failure(2), | ||
| 10 | BaseInstallAttempted(3); | ||
| 11 | |||
| 12 | companion object { | ||
| 13 | fun from(int: Int): InstallResult = entries.firstOrNull { it.int == int } ?: Success | ||
| 14 | } | ||
| 15 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt new file mode 100644 index 000000000..25cb9e365 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | import androidx.annotation.Keep | ||
| 7 | |||
| 8 | @Keep | ||
| 9 | data class Patch( | ||
| 10 | var enabled: Boolean, | ||
| 11 | val name: String, | ||
| 12 | val version: String, | ||
| 13 | val type: Int, | ||
| 14 | val programId: String, | ||
| 15 | val titleId: String | ||
| 16 | ) | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt new file mode 100644 index 000000000..e9a54162b --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | enum class PatchType(val int: Int) { | ||
| 7 | Update(0), | ||
| 8 | DLC(1), | ||
| 9 | Mod(2); | ||
| 10 | |||
| 11 | companion object { | ||
| 12 | fun from(int: Int): PatchType = entries.firstOrNull { it.int == int } ?: Update | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt index e59c95733..4361eb972 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt | |||
| @@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope | |||
| 8 | import kotlinx.coroutines.Dispatchers | 8 | import kotlinx.coroutines.Dispatchers |
| 9 | import kotlinx.coroutines.flow.MutableStateFlow | 9 | import kotlinx.coroutines.flow.MutableStateFlow |
| 10 | import kotlinx.coroutines.flow.StateFlow | 10 | import kotlinx.coroutines.flow.StateFlow |
| 11 | import kotlinx.coroutines.flow.asStateFlow | ||
| 11 | import kotlinx.coroutines.launch | 12 | import kotlinx.coroutines.launch |
| 12 | 13 | ||
| 13 | class TaskViewModel : ViewModel() { | 14 | class TaskViewModel : ViewModel() { |
| @@ -23,13 +24,28 @@ class TaskViewModel : ViewModel() { | |||
| 23 | val cancelled: StateFlow<Boolean> get() = _cancelled | 24 | val cancelled: StateFlow<Boolean> get() = _cancelled |
| 24 | private val _cancelled = MutableStateFlow(false) | 25 | private val _cancelled = MutableStateFlow(false) |
| 25 | 26 | ||
| 26 | lateinit var task: suspend () -> Any | 27 | private val _progress = MutableStateFlow(0.0) |
| 28 | val progress = _progress.asStateFlow() | ||
| 29 | |||
| 30 | private val _maxProgress = MutableStateFlow(0.0) | ||
| 31 | val maxProgress = _maxProgress.asStateFlow() | ||
| 32 | |||
| 33 | private val _message = MutableStateFlow("") | ||
| 34 | val message = _message.asStateFlow() | ||
| 35 | |||
| 36 | lateinit var task: suspend ( | ||
| 37 | progressCallback: (max: Long, progress: Long) -> Boolean, | ||
| 38 | messageCallback: (message: String) -> Unit | ||
| 39 | ) -> Any | ||
| 27 | 40 | ||
| 28 | fun clear() { | 41 | fun clear() { |
| 29 | _result.value = Any() | 42 | _result.value = Any() |
| 30 | _isComplete.value = false | 43 | _isComplete.value = false |
| 31 | _isRunning.value = false | 44 | _isRunning.value = false |
| 32 | _cancelled.value = false | 45 | _cancelled.value = false |
| 46 | _progress.value = 0.0 | ||
| 47 | _maxProgress.value = 0.0 | ||
| 48 | _message.value = "" | ||
| 33 | } | 49 | } |
| 34 | 50 | ||
| 35 | fun setCancelled(value: Boolean) { | 51 | fun setCancelled(value: Boolean) { |
| @@ -43,7 +59,16 @@ class TaskViewModel : ViewModel() { | |||
| 43 | _isRunning.value = true | 59 | _isRunning.value = true |
| 44 | 60 | ||
| 45 | viewModelScope.launch(Dispatchers.IO) { | 61 | viewModelScope.launch(Dispatchers.IO) { |
| 46 | val res = task() | 62 | val res = task( |
| 63 | { max, progress -> | ||
| 64 | _maxProgress.value = max.toDouble() | ||
| 65 | _progress.value = progress.toDouble() | ||
| 66 | return@task cancelled.value | ||
| 67 | }, | ||
| 68 | { message -> | ||
| 69 | _message.value = message | ||
| 70 | } | ||
| 71 | ) | ||
| 47 | _result.value = res | 72 | _result.value = res |
| 48 | _isComplete.value = true | 73 | _isComplete.value = true |
| 49 | _isRunning.value = false | 74 | _isRunning.value = false |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index 644289e25..c2cc29961 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt | |||
| @@ -38,12 +38,13 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity | |||
| 38 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding | 38 | import org.yuzu.yuzu_emu.databinding.ActivityMainBinding |
| 39 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 39 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 40 | import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment | 40 | import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment |
| 41 | import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment | 41 | import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment |
| 42 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment | 42 | import org.yuzu.yuzu_emu.fragments.MessageDialogFragment |
| 43 | import org.yuzu.yuzu_emu.model.AddonViewModel | 43 | import org.yuzu.yuzu_emu.model.AddonViewModel |
| 44 | import org.yuzu.yuzu_emu.model.DriverViewModel | 44 | import org.yuzu.yuzu_emu.model.DriverViewModel |
| 45 | import org.yuzu.yuzu_emu.model.GamesViewModel | 45 | import org.yuzu.yuzu_emu.model.GamesViewModel |
| 46 | import org.yuzu.yuzu_emu.model.HomeViewModel | 46 | import org.yuzu.yuzu_emu.model.HomeViewModel |
| 47 | import org.yuzu.yuzu_emu.model.InstallResult | ||
| 47 | import org.yuzu.yuzu_emu.model.TaskState | 48 | import org.yuzu.yuzu_emu.model.TaskState |
| 48 | import org.yuzu.yuzu_emu.model.TaskViewModel | 49 | import org.yuzu.yuzu_emu.model.TaskViewModel |
| 49 | import org.yuzu.yuzu_emu.utils.* | 50 | import org.yuzu.yuzu_emu.utils.* |
| @@ -369,26 +370,23 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 369 | return@registerForActivityResult | 370 | return@registerForActivityResult |
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | val inputZip = contentResolver.openInputStream(result) | ||
| 373 | if (inputZip == null) { | ||
| 374 | Toast.makeText( | ||
| 375 | applicationContext, | ||
| 376 | getString(R.string.fatal_error), | ||
| 377 | Toast.LENGTH_LONG | ||
| 378 | ).show() | ||
| 379 | return@registerForActivityResult | ||
| 380 | } | ||
| 381 | |||
| 382 | val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") } | 373 | val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") } |
| 383 | 374 | ||
| 384 | val firmwarePath = | 375 | val firmwarePath = |
| 385 | File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/") | 376 | File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/") |
| 386 | val cacheFirmwareDir = File("${cacheDir.path}/registered/") | 377 | val cacheFirmwareDir = File("${cacheDir.path}/registered/") |
| 387 | 378 | ||
| 388 | val task: () -> Any = { | 379 | ProgressDialogFragment.newInstance( |
| 380 | this, | ||
| 381 | R.string.firmware_installing | ||
| 382 | ) { progressCallback, _ -> | ||
| 389 | var messageToShow: Any | 383 | var messageToShow: Any |
| 390 | try { | 384 | try { |
| 391 | FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheFirmwareDir) | 385 | FileUtil.unzipToInternalStorage( |
| 386 | result.toString(), | ||
| 387 | cacheFirmwareDir, | ||
| 388 | progressCallback | ||
| 389 | ) | ||
| 392 | val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1 | 390 | val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1 |
| 393 | val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2 | 391 | val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2 |
| 394 | messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) { | 392 | messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) { |
| @@ -404,18 +402,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 404 | getString(R.string.save_file_imported_success) | 402 | getString(R.string.save_file_imported_success) |
| 405 | } | 403 | } |
| 406 | } catch (e: Exception) { | 404 | } catch (e: Exception) { |
| 405 | Log.error("[MainActivity] Firmware install failed - ${e.message}") | ||
| 407 | messageToShow = getString(R.string.fatal_error) | 406 | messageToShow = getString(R.string.fatal_error) |
| 408 | } finally { | 407 | } finally { |
| 409 | cacheFirmwareDir.deleteRecursively() | 408 | cacheFirmwareDir.deleteRecursively() |
| 410 | } | 409 | } |
| 411 | messageToShow | 410 | messageToShow |
| 412 | } | 411 | }.show(supportFragmentManager, ProgressDialogFragment.TAG) |
| 413 | |||
| 414 | IndeterminateProgressDialogFragment.newInstance( | ||
| 415 | this, | ||
| 416 | R.string.firmware_installing, | ||
| 417 | task = task | ||
| 418 | ).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | ||
| 419 | } | 412 | } |
| 420 | 413 | ||
| 421 | val getAmiiboKey = | 414 | val getAmiiboKey = |
| @@ -474,11 +467,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 474 | return@registerForActivityResult | 467 | return@registerForActivityResult |
| 475 | } | 468 | } |
| 476 | 469 | ||
| 477 | IndeterminateProgressDialogFragment.newInstance( | 470 | ProgressDialogFragment.newInstance( |
| 478 | this@MainActivity, | 471 | this@MainActivity, |
| 479 | R.string.verifying_content, | 472 | R.string.verifying_content, |
| 480 | false | 473 | false |
| 481 | ) { | 474 | ) { _, _ -> |
| 482 | var updatesMatchProgram = true | 475 | var updatesMatchProgram = true |
| 483 | for (document in documents) { | 476 | for (document in documents) { |
| 484 | val valid = NativeLibrary.doesUpdateMatchProgram( | 477 | val valid = NativeLibrary.doesUpdateMatchProgram( |
| @@ -501,44 +494,42 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 501 | positiveAction = { homeViewModel.setContentToInstall(documents) } | 494 | positiveAction = { homeViewModel.setContentToInstall(documents) } |
| 502 | ) | 495 | ) |
| 503 | } | 496 | } |
| 504 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | 497 | }.show(supportFragmentManager, ProgressDialogFragment.TAG) |
| 505 | } | 498 | } |
| 506 | 499 | ||
| 507 | private fun installContent(documents: List<Uri>) { | 500 | private fun installContent(documents: List<Uri>) { |
| 508 | IndeterminateProgressDialogFragment.newInstance( | 501 | ProgressDialogFragment.newInstance( |
| 509 | this@MainActivity, | 502 | this@MainActivity, |
| 510 | R.string.installing_game_content | 503 | R.string.installing_game_content |
| 511 | ) { | 504 | ) { progressCallback, messageCallback -> |
| 512 | var installSuccess = 0 | 505 | var installSuccess = 0 |
| 513 | var installOverwrite = 0 | 506 | var installOverwrite = 0 |
| 514 | var errorBaseGame = 0 | 507 | var errorBaseGame = 0 |
| 515 | var errorExtension = 0 | 508 | var error = 0 |
| 516 | var errorOther = 0 | ||
| 517 | documents.forEach { | 509 | documents.forEach { |
| 510 | messageCallback.invoke(FileUtil.getFilename(it)) | ||
| 518 | when ( | 511 | when ( |
| 519 | NativeLibrary.installFileToNand( | 512 | InstallResult.from( |
| 520 | it.toString(), | 513 | NativeLibrary.installFileToNand( |
| 521 | FileUtil.getExtension(it) | 514 | it.toString(), |
| 515 | progressCallback | ||
| 516 | ) | ||
| 522 | ) | 517 | ) |
| 523 | ) { | 518 | ) { |
| 524 | NativeLibrary.InstallFileToNandResult.Success -> { | 519 | InstallResult.Success -> { |
| 525 | installSuccess += 1 | 520 | installSuccess += 1 |
| 526 | } | 521 | } |
| 527 | 522 | ||
| 528 | NativeLibrary.InstallFileToNandResult.SuccessFileOverwritten -> { | 523 | InstallResult.Overwrite -> { |
| 529 | installOverwrite += 1 | 524 | installOverwrite += 1 |
| 530 | } | 525 | } |
| 531 | 526 | ||
| 532 | NativeLibrary.InstallFileToNandResult.ErrorBaseGame -> { | 527 | InstallResult.BaseInstallAttempted -> { |
| 533 | errorBaseGame += 1 | 528 | errorBaseGame += 1 |
| 534 | } | 529 | } |
| 535 | 530 | ||
| 536 | NativeLibrary.InstallFileToNandResult.ErrorFilenameExtension -> { | 531 | InstallResult.Failure -> { |
| 537 | errorExtension += 1 | 532 | error += 1 |
| 538 | } | ||
| 539 | |||
| 540 | else -> { | ||
| 541 | errorOther += 1 | ||
| 542 | } | 533 | } |
| 543 | } | 534 | } |
| 544 | } | 535 | } |
| @@ -565,7 +556,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 565 | ) | 556 | ) |
| 566 | installResult.append(separator) | 557 | installResult.append(separator) |
| 567 | } | 558 | } |
| 568 | val errorTotal: Int = errorBaseGame + errorExtension + errorOther | 559 | val errorTotal: Int = errorBaseGame + error |
| 569 | if (errorTotal > 0) { | 560 | if (errorTotal > 0) { |
| 570 | installResult.append(separator) | 561 | installResult.append(separator) |
| 571 | installResult.append( | 562 | installResult.append( |
| @@ -582,14 +573,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 582 | ) | 573 | ) |
| 583 | installResult.append(separator) | 574 | installResult.append(separator) |
| 584 | } | 575 | } |
| 585 | if (errorExtension > 0) { | 576 | if (error > 0) { |
| 586 | installResult.append(separator) | ||
| 587 | installResult.append( | ||
| 588 | getString(R.string.install_game_content_failure_file_extension) | ||
| 589 | ) | ||
| 590 | installResult.append(separator) | ||
| 591 | } | ||
| 592 | if (errorOther > 0) { | ||
| 593 | installResult.append( | 577 | installResult.append( |
| 594 | getString(R.string.install_game_content_failure_description) | 578 | getString(R.string.install_game_content_failure_description) |
| 595 | ) | 579 | ) |
| @@ -608,7 +592,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 608 | descriptionString = installResult.toString().trim() | 592 | descriptionString = installResult.toString().trim() |
| 609 | ) | 593 | ) |
| 610 | } | 594 | } |
| 611 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | 595 | }.show(supportFragmentManager, ProgressDialogFragment.TAG) |
| 612 | } | 596 | } |
| 613 | 597 | ||
| 614 | val exportUserData = registerForActivityResult( | 598 | val exportUserData = registerForActivityResult( |
| @@ -618,16 +602,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 618 | return@registerForActivityResult | 602 | return@registerForActivityResult |
| 619 | } | 603 | } |
| 620 | 604 | ||
| 621 | IndeterminateProgressDialogFragment.newInstance( | 605 | ProgressDialogFragment.newInstance( |
| 622 | this, | 606 | this, |
| 623 | R.string.exporting_user_data, | 607 | R.string.exporting_user_data, |
| 624 | true | 608 | true |
| 625 | ) { | 609 | ) { progressCallback, _ -> |
| 626 | val zipResult = FileUtil.zipFromInternalStorage( | 610 | val zipResult = FileUtil.zipFromInternalStorage( |
| 627 | File(DirectoryInitialization.userDirectory!!), | 611 | File(DirectoryInitialization.userDirectory!!), |
| 628 | DirectoryInitialization.userDirectory!!, | 612 | DirectoryInitialization.userDirectory!!, |
| 629 | BufferedOutputStream(contentResolver.openOutputStream(result)), | 613 | BufferedOutputStream(contentResolver.openOutputStream(result)), |
| 630 | taskViewModel.cancelled, | 614 | progressCallback, |
| 631 | compression = false | 615 | compression = false |
| 632 | ) | 616 | ) |
| 633 | return@newInstance when (zipResult) { | 617 | return@newInstance when (zipResult) { |
| @@ -635,7 +619,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 635 | TaskState.Failed -> R.string.export_failed | 619 | TaskState.Failed -> R.string.export_failed |
| 636 | TaskState.Cancelled -> R.string.user_data_export_cancelled | 620 | TaskState.Cancelled -> R.string.user_data_export_cancelled |
| 637 | } | 621 | } |
| 638 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | 622 | }.show(supportFragmentManager, ProgressDialogFragment.TAG) |
| 639 | } | 623 | } |
| 640 | 624 | ||
| 641 | val importUserData = | 625 | val importUserData = |
| @@ -644,10 +628,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 644 | return@registerForActivityResult | 628 | return@registerForActivityResult |
| 645 | } | 629 | } |
| 646 | 630 | ||
| 647 | IndeterminateProgressDialogFragment.newInstance( | 631 | ProgressDialogFragment.newInstance( |
| 648 | this, | 632 | this, |
| 649 | R.string.importing_user_data | 633 | R.string.importing_user_data |
| 650 | ) { | 634 | ) { progressCallback, _ -> |
| 651 | val checkStream = | 635 | val checkStream = |
| 652 | ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result))) | 636 | ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result))) |
| 653 | var isYuzuBackup = false | 637 | var isYuzuBackup = false |
| @@ -676,8 +660,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 676 | // Copy archive to internal storage | 660 | // Copy archive to internal storage |
| 677 | try { | 661 | try { |
| 678 | FileUtil.unzipToInternalStorage( | 662 | FileUtil.unzipToInternalStorage( |
| 679 | BufferedInputStream(contentResolver.openInputStream(result)), | 663 | result.toString(), |
| 680 | File(DirectoryInitialization.userDirectory!!) | 664 | File(DirectoryInitialization.userDirectory!!), |
| 665 | progressCallback | ||
| 681 | ) | 666 | ) |
| 682 | } catch (e: Exception) { | 667 | } catch (e: Exception) { |
| 683 | return@newInstance MessageDialogFragment.newInstance( | 668 | return@newInstance MessageDialogFragment.newInstance( |
| @@ -694,6 +679,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider { | |||
| 694 | driverViewModel.reloadDriverData() | 679 | driverViewModel.reloadDriverData() |
| 695 | 680 | ||
| 696 | return@newInstance getString(R.string.user_data_import_success) | 681 | return@newInstance getString(R.string.user_data_import_success) |
| 697 | }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) | 682 | }.show(supportFragmentManager, ProgressDialogFragment.TAG) |
| 698 | } | 683 | } |
| 699 | } | 684 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt index b54a19c65..fc2339f5a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt | |||
| @@ -7,7 +7,6 @@ import android.database.Cursor | |||
| 7 | import android.net.Uri | 7 | import android.net.Uri |
| 8 | import android.provider.DocumentsContract | 8 | import android.provider.DocumentsContract |
| 9 | import androidx.documentfile.provider.DocumentFile | 9 | import androidx.documentfile.provider.DocumentFile |
| 10 | import kotlinx.coroutines.flow.StateFlow | ||
| 11 | import java.io.BufferedInputStream | 10 | import java.io.BufferedInputStream |
| 12 | import java.io.File | 11 | import java.io.File |
| 13 | import java.io.IOException | 12 | import java.io.IOException |
| @@ -19,6 +18,7 @@ import org.yuzu.yuzu_emu.YuzuApplication | |||
| 19 | import org.yuzu.yuzu_emu.model.MinimalDocumentFile | 18 | import org.yuzu.yuzu_emu.model.MinimalDocumentFile |
| 20 | import org.yuzu.yuzu_emu.model.TaskState | 19 | import org.yuzu.yuzu_emu.model.TaskState |
| 21 | import java.io.BufferedOutputStream | 20 | import java.io.BufferedOutputStream |
| 21 | import java.io.OutputStream | ||
| 22 | import java.lang.NullPointerException | 22 | import java.lang.NullPointerException |
| 23 | import java.nio.charset.StandardCharsets | 23 | import java.nio.charset.StandardCharsets |
| 24 | import java.util.zip.Deflater | 24 | import java.util.zip.Deflater |
| @@ -283,12 +283,34 @@ object FileUtil { | |||
| 283 | 283 | ||
| 284 | /** | 284 | /** |
| 285 | * Extracts the given zip file into the given directory. | 285 | * Extracts the given zip file into the given directory. |
| 286 | * @param path String representation of a [Uri] or a typical path delimited by '/' | ||
| 287 | * @param destDir Location to unzip the contents of [path] into | ||
| 288 | * @param progressCallback Lambda that is called with the total number of files and the current | ||
| 289 | * progress through the process. Stops execution as soon as possible if this returns true. | ||
| 286 | */ | 290 | */ |
| 287 | @Throws(SecurityException::class) | 291 | @Throws(SecurityException::class) |
| 288 | fun unzipToInternalStorage(zipStream: BufferedInputStream, destDir: File) { | 292 | fun unzipToInternalStorage( |
| 289 | ZipInputStream(zipStream).use { zis -> | 293 | path: String, |
| 294 | destDir: File, | ||
| 295 | progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false } | ||
| 296 | ) { | ||
| 297 | var totalEntries = 0L | ||
| 298 | ZipInputStream(getInputStream(path)).use { zis -> | ||
| 299 | var tempEntry = zis.nextEntry | ||
| 300 | while (tempEntry != null) { | ||
| 301 | tempEntry = zis.nextEntry | ||
| 302 | totalEntries++ | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | var progress = 0L | ||
| 307 | ZipInputStream(getInputStream(path)).use { zis -> | ||
| 290 | var entry: ZipEntry? = zis.nextEntry | 308 | var entry: ZipEntry? = zis.nextEntry |
| 291 | while (entry != null) { | 309 | while (entry != null) { |
| 310 | if (progressCallback.invoke(totalEntries, progress)) { | ||
| 311 | return@use | ||
| 312 | } | ||
| 313 | |||
| 292 | val newFile = File(destDir, entry.name) | 314 | val newFile = File(destDir, entry.name) |
| 293 | val destinationDirectory = if (entry.isDirectory) newFile else newFile.parentFile | 315 | val destinationDirectory = if (entry.isDirectory) newFile else newFile.parentFile |
| 294 | 316 | ||
| @@ -304,6 +326,7 @@ object FileUtil { | |||
| 304 | newFile.outputStream().use { fos -> zis.copyTo(fos) } | 326 | newFile.outputStream().use { fos -> zis.copyTo(fos) } |
| 305 | } | 327 | } |
| 306 | entry = zis.nextEntry | 328 | entry = zis.nextEntry |
| 329 | progress++ | ||
| 307 | } | 330 | } |
| 308 | } | 331 | } |
| 309 | } | 332 | } |
| @@ -313,14 +336,15 @@ object FileUtil { | |||
| 313 | * @param inputFile File representation of the item that will be zipped | 336 | * @param inputFile File representation of the item that will be zipped |
| 314 | * @param rootDir Directory containing the inputFile | 337 | * @param rootDir Directory containing the inputFile |
| 315 | * @param outputStream Stream where the zip file will be output | 338 | * @param outputStream Stream where the zip file will be output |
| 316 | * @param cancelled [StateFlow] that reports whether this process has been cancelled | 339 | * @param progressCallback Lambda that is called with the total number of files and the current |
| 340 | * progress through the process. Stops execution as soon as possible if this returns true. | ||
| 317 | * @param compression Disables compression if true | 341 | * @param compression Disables compression if true |
| 318 | */ | 342 | */ |
| 319 | fun zipFromInternalStorage( | 343 | fun zipFromInternalStorage( |
| 320 | inputFile: File, | 344 | inputFile: File, |
| 321 | rootDir: String, | 345 | rootDir: String, |
| 322 | outputStream: BufferedOutputStream, | 346 | outputStream: BufferedOutputStream, |
| 323 | cancelled: StateFlow<Boolean>? = null, | 347 | progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false }, |
| 324 | compression: Boolean = true | 348 | compression: Boolean = true |
| 325 | ): TaskState { | 349 | ): TaskState { |
| 326 | try { | 350 | try { |
| @@ -330,8 +354,10 @@ object FileUtil { | |||
| 330 | zos.setLevel(Deflater.NO_COMPRESSION) | 354 | zos.setLevel(Deflater.NO_COMPRESSION) |
| 331 | } | 355 | } |
| 332 | 356 | ||
| 357 | var count = 0L | ||
| 358 | val totalFiles = inputFile.walkTopDown().count().toLong() | ||
| 333 | inputFile.walkTopDown().forEach { file -> | 359 | inputFile.walkTopDown().forEach { file -> |
| 334 | if (cancelled?.value == true) { | 360 | if (progressCallback.invoke(totalFiles, count)) { |
| 335 | return TaskState.Cancelled | 361 | return TaskState.Cancelled |
| 336 | } | 362 | } |
| 337 | 363 | ||
| @@ -343,6 +369,7 @@ object FileUtil { | |||
| 343 | if (file.isFile) { | 369 | if (file.isFile) { |
| 344 | file.inputStream().use { fis -> fis.copyTo(zos) } | 370 | file.inputStream().use { fis -> fis.copyTo(zos) } |
| 345 | } | 371 | } |
| 372 | count++ | ||
| 346 | } | 373 | } |
| 347 | } | 374 | } |
| 348 | } | 375 | } |
| @@ -356,9 +383,14 @@ object FileUtil { | |||
| 356 | /** | 383 | /** |
| 357 | * Helper function that copies the contents of a DocumentFile folder into a [File] | 384 | * Helper function that copies the contents of a DocumentFile folder into a [File] |
| 358 | * @param file [File] representation of the folder to copy into | 385 | * @param file [File] representation of the folder to copy into |
| 386 | * @param progressCallback Lambda that is called with the total number of files and the current | ||
| 387 | * progress through the process. Stops execution as soon as possible if this returns true. | ||
| 359 | * @throws IllegalStateException Fails when trying to copy a folder into a file and vice versa | 388 | * @throws IllegalStateException Fails when trying to copy a folder into a file and vice versa |
| 360 | */ | 389 | */ |
| 361 | fun DocumentFile.copyFilesTo(file: File) { | 390 | fun DocumentFile.copyFilesTo( |
| 391 | file: File, | ||
| 392 | progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false } | ||
| 393 | ) { | ||
| 362 | file.mkdirs() | 394 | file.mkdirs() |
| 363 | if (!this.isDirectory || !file.isDirectory) { | 395 | if (!this.isDirectory || !file.isDirectory) { |
| 364 | throw IllegalStateException( | 396 | throw IllegalStateException( |
| @@ -366,7 +398,13 @@ object FileUtil { | |||
| 366 | ) | 398 | ) |
| 367 | } | 399 | } |
| 368 | 400 | ||
| 401 | var count = 0L | ||
| 402 | val totalFiles = this.listFiles().size.toLong() | ||
| 369 | this.listFiles().forEach { | 403 | this.listFiles().forEach { |
| 404 | if (progressCallback.invoke(totalFiles, count)) { | ||
| 405 | return | ||
| 406 | } | ||
| 407 | |||
| 370 | val newFile = File(file, it.name!!) | 408 | val newFile = File(file, it.name!!) |
| 371 | if (it.isDirectory) { | 409 | if (it.isDirectory) { |
| 372 | newFile.mkdirs() | 410 | newFile.mkdirs() |
| @@ -381,6 +419,7 @@ object FileUtil { | |||
| 381 | newFile.outputStream().use { os -> bos.copyTo(os) } | 419 | newFile.outputStream().use { os -> bos.copyTo(os) } |
| 382 | } | 420 | } |
| 383 | } | 421 | } |
| 422 | count++ | ||
| 384 | } | 423 | } |
| 385 | } | 424 | } |
| 386 | 425 | ||
| @@ -427,6 +466,18 @@ object FileUtil { | |||
| 427 | } | 466 | } |
| 428 | } | 467 | } |
| 429 | 468 | ||
| 469 | fun getInputStream(path: String) = if (path.contains("content://")) { | ||
| 470 | Uri.parse(path).inputStream() | ||
| 471 | } else { | ||
| 472 | File(path).inputStream() | ||
| 473 | } | ||
| 474 | |||
| 475 | fun getOutputStream(path: String) = if (path.contains("content://")) { | ||
| 476 | Uri.parse(path).outputStream() | ||
| 477 | } else { | ||
| 478 | File(path).outputStream() | ||
| 479 | } | ||
| 480 | |||
| 430 | @Throws(IOException::class) | 481 | @Throws(IOException::class) |
| 431 | fun getStringFromFile(file: File): String = | 482 | fun getStringFromFile(file: File): String = |
| 432 | String(file.readBytes(), StandardCharsets.UTF_8) | 483 | String(file.readBytes(), StandardCharsets.UTF_8) |
| @@ -434,4 +485,19 @@ object FileUtil { | |||
| 434 | @Throws(IOException::class) | 485 | @Throws(IOException::class) |
| 435 | fun getStringFromInputStream(stream: InputStream): String = | 486 | fun getStringFromInputStream(stream: InputStream): String = |
| 436 | String(stream.readBytes(), StandardCharsets.UTF_8) | 487 | String(stream.readBytes(), StandardCharsets.UTF_8) |
| 488 | |||
| 489 | fun DocumentFile.inputStream(): InputStream = | ||
| 490 | YuzuApplication.appContext.contentResolver.openInputStream(uri)!! | ||
| 491 | |||
| 492 | fun DocumentFile.outputStream(): OutputStream = | ||
| 493 | YuzuApplication.appContext.contentResolver.openOutputStream(uri)!! | ||
| 494 | |||
| 495 | fun Uri.inputStream(): InputStream = | ||
| 496 | YuzuApplication.appContext.contentResolver.openInputStream(this)!! | ||
| 497 | |||
| 498 | fun Uri.outputStream(): OutputStream = | ||
| 499 | YuzuApplication.appContext.contentResolver.openOutputStream(this)!! | ||
| 500 | |||
| 501 | fun Uri.asDocumentFile(): DocumentFile? = | ||
| 502 | DocumentFile.fromSingleUri(YuzuApplication.appContext, this) | ||
| 437 | } | 503 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt index 2e9b0beb8..d05020560 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt | |||
| @@ -5,7 +5,10 @@ package org.yuzu.yuzu_emu.utils | |||
| 5 | 5 | ||
| 6 | import android.graphics.Bitmap | 6 | import android.graphics.Bitmap |
| 7 | import android.graphics.BitmapFactory | 7 | import android.graphics.BitmapFactory |
| 8 | import android.graphics.drawable.LayerDrawable | ||
| 8 | import android.widget.ImageView | 9 | import android.widget.ImageView |
| 10 | import androidx.core.content.res.ResourcesCompat | ||
| 11 | import androidx.core.graphics.drawable.IconCompat | ||
| 9 | import androidx.core.graphics.drawable.toBitmap | 12 | import androidx.core.graphics.drawable.toBitmap |
| 10 | import androidx.core.graphics.drawable.toDrawable | 13 | import androidx.core.graphics.drawable.toDrawable |
| 11 | import androidx.lifecycle.LifecycleOwner | 14 | import androidx.lifecycle.LifecycleOwner |
| @@ -85,4 +88,22 @@ object GameIconUtils { | |||
| 85 | return imageLoader.execute(request) | 88 | return imageLoader.execute(request) |
| 86 | .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) | 89 | .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) |
| 87 | } | 90 | } |
| 91 | |||
| 92 | suspend fun getShortcutIcon(lifecycleOwner: LifecycleOwner, game: Game): IconCompat { | ||
| 93 | val layerDrawable = ResourcesCompat.getDrawable( | ||
| 94 | YuzuApplication.appContext.resources, | ||
| 95 | R.drawable.shortcut, | ||
| 96 | null | ||
| 97 | ) as LayerDrawable | ||
| 98 | layerDrawable.setDrawableByLayerId( | ||
| 99 | R.id.shortcut_foreground, | ||
| 100 | getGameIcon(lifecycleOwner, game).toDrawable(YuzuApplication.appContext.resources) | ||
| 101 | ) | ||
| 102 | val inset = YuzuApplication.appContext.resources | ||
| 103 | .getDimensionPixelSize(R.dimen.icon_inset) | ||
| 104 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) | ||
| 105 | return IconCompat.createWithAdaptiveBitmap( | ||
| 106 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 107 | ) | ||
| 108 | } | ||
| 88 | } | 109 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt index a8f9dcc34..81212cbee 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt | |||
| @@ -5,7 +5,6 @@ package org.yuzu.yuzu_emu.utils | |||
| 5 | 5 | ||
| 6 | import android.net.Uri | 6 | import android.net.Uri |
| 7 | import android.os.Build | 7 | import android.os.Build |
| 8 | import java.io.BufferedInputStream | ||
| 9 | import java.io.File | 8 | import java.io.File |
| 10 | import java.io.IOException | 9 | import java.io.IOException |
| 11 | import org.yuzu.yuzu_emu.NativeLibrary | 10 | import org.yuzu.yuzu_emu.NativeLibrary |
| @@ -123,7 +122,7 @@ object GpuDriverHelper { | |||
| 123 | // Unzip the driver. | 122 | // Unzip the driver. |
| 124 | try { | 123 | try { |
| 125 | FileUtil.unzipToInternalStorage( | 124 | FileUtil.unzipToInternalStorage( |
| 126 | BufferedInputStream(copiedFile.inputStream()), | 125 | copiedFile.path, |
| 127 | File(driverInstallationPath!!) | 126 | File(driverInstallationPath!!) |
| 128 | ) | 127 | ) |
| 129 | } catch (e: SecurityException) { | 128 | } catch (e: SecurityException) { |
| @@ -156,7 +155,7 @@ object GpuDriverHelper { | |||
| 156 | // Unzip the driver to the private installation directory | 155 | // Unzip the driver to the private installation directory |
| 157 | try { | 156 | try { |
| 158 | FileUtil.unzipToInternalStorage( | 157 | FileUtil.unzipToInternalStorage( |
| 159 | BufferedInputStream(driver.inputStream()), | 158 | driver.path, |
| 160 | File(driverInstallationPath!!) | 159 | File(driverInstallationPath!!) |
| 161 | ) | 160 | ) |
| 162 | } catch (e: SecurityException) { | 161 | } catch (e: SecurityException) { |
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp index 1e884ffdd..7018a52af 100644 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ b/src/android/app/src/main/jni/android_common/android_common.cpp | |||
| @@ -42,3 +42,19 @@ double GetJDouble(JNIEnv* env, jobject jdouble) { | |||
| 42 | jobject ToJDouble(JNIEnv* env, double value) { | 42 | jobject ToJDouble(JNIEnv* env, double value) { |
| 43 | return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); | 43 | return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); |
| 44 | } | 44 | } |
| 45 | |||
| 46 | s32 GetJInteger(JNIEnv* env, jobject jinteger) { | ||
| 47 | return env->GetIntField(jinteger, IDCache::GetIntegerValueField()); | ||
| 48 | } | ||
| 49 | |||
| 50 | jobject ToJInteger(JNIEnv* env, s32 value) { | ||
| 51 | return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value); | ||
| 52 | } | ||
| 53 | |||
| 54 | bool GetJBoolean(JNIEnv* env, jobject jboolean) { | ||
| 55 | return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField()); | ||
| 56 | } | ||
| 57 | |||
| 58 | jobject ToJBoolean(JNIEnv* env, bool value) { | ||
| 59 | return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value); | ||
| 60 | } | ||
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h index 8eb803e1b..29a338c0a 100644 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ b/src/android/app/src/main/jni/android_common/android_common.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <string> | 6 | #include <string> |
| 7 | 7 | ||
| 8 | #include <jni.h> | 8 | #include <jni.h> |
| 9 | #include "common/common_types.h" | ||
| 9 | 10 | ||
| 10 | std::string GetJString(JNIEnv* env, jstring jstr); | 11 | std::string GetJString(JNIEnv* env, jstring jstr); |
| 11 | jstring ToJString(JNIEnv* env, std::string_view str); | 12 | jstring ToJString(JNIEnv* env, std::string_view str); |
| @@ -13,3 +14,9 @@ jstring ToJString(JNIEnv* env, std::u16string_view str); | |||
| 13 | 14 | ||
| 14 | double GetJDouble(JNIEnv* env, jobject jdouble); | 15 | double GetJDouble(JNIEnv* env, jobject jdouble); |
| 15 | jobject ToJDouble(JNIEnv* env, double value); | 16 | jobject ToJDouble(JNIEnv* env, double value); |
| 17 | |||
| 18 | s32 GetJInteger(JNIEnv* env, jobject jinteger); | ||
| 19 | jobject ToJInteger(JNIEnv* env, s32 value); | ||
| 20 | |||
| 21 | bool GetJBoolean(JNIEnv* env, jobject jboolean); | ||
| 22 | jobject ToJBoolean(JNIEnv* env, bool value); | ||
diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index 559ae83eb..cf93304da 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h | |||
| @@ -63,6 +63,7 @@ struct Values { | |||
| 63 | Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay", | 63 | Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay", |
| 64 | Settings::Category::Overlay}; | 64 | Settings::Category::Overlay}; |
| 65 | Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; | 65 | Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; |
| 66 | Settings::Setting<s32> lock_drawer{linkage, false, "lock_drawer", Settings::Category::Overlay}; | ||
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | extern Values values; | 69 | extern Values values; |
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp index c79ad7d76..96f2ad3d4 100644 --- a/src/android/app/src/main/jni/id_cache.cpp +++ b/src/android/app/src/main/jni/id_cache.cpp | |||
| @@ -43,10 +43,27 @@ static jfieldID s_overlay_control_data_landscape_position_field; | |||
| 43 | static jfieldID s_overlay_control_data_portrait_position_field; | 43 | static jfieldID s_overlay_control_data_portrait_position_field; |
| 44 | static jfieldID s_overlay_control_data_foldable_position_field; | 44 | static jfieldID s_overlay_control_data_foldable_position_field; |
| 45 | 45 | ||
| 46 | static jclass s_patch_class; | ||
| 47 | static jmethodID s_patch_constructor; | ||
| 48 | static jfieldID s_patch_enabled_field; | ||
| 49 | static jfieldID s_patch_name_field; | ||
| 50 | static jfieldID s_patch_version_field; | ||
| 51 | static jfieldID s_patch_type_field; | ||
| 52 | static jfieldID s_patch_program_id_field; | ||
| 53 | static jfieldID s_patch_title_id_field; | ||
| 54 | |||
| 46 | static jclass s_double_class; | 55 | static jclass s_double_class; |
| 47 | static jmethodID s_double_constructor; | 56 | static jmethodID s_double_constructor; |
| 48 | static jfieldID s_double_value_field; | 57 | static jfieldID s_double_value_field; |
| 49 | 58 | ||
| 59 | static jclass s_integer_class; | ||
| 60 | static jmethodID s_integer_constructor; | ||
| 61 | static jfieldID s_integer_value_field; | ||
| 62 | |||
| 63 | static jclass s_boolean_class; | ||
| 64 | static jmethodID s_boolean_constructor; | ||
| 65 | static jfieldID s_boolean_value_field; | ||
| 66 | |||
| 50 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; | 67 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; |
| 51 | 68 | ||
| 52 | namespace IDCache { | 69 | namespace IDCache { |
| @@ -186,6 +203,38 @@ jfieldID GetOverlayControlDataFoldablePositionField() { | |||
| 186 | return s_overlay_control_data_foldable_position_field; | 203 | return s_overlay_control_data_foldable_position_field; |
| 187 | } | 204 | } |
| 188 | 205 | ||
| 206 | jclass GetPatchClass() { | ||
| 207 | return s_patch_class; | ||
| 208 | } | ||
| 209 | |||
| 210 | jmethodID GetPatchConstructor() { | ||
| 211 | return s_patch_constructor; | ||
| 212 | } | ||
| 213 | |||
| 214 | jfieldID GetPatchEnabledField() { | ||
| 215 | return s_patch_enabled_field; | ||
| 216 | } | ||
| 217 | |||
| 218 | jfieldID GetPatchNameField() { | ||
| 219 | return s_patch_name_field; | ||
| 220 | } | ||
| 221 | |||
| 222 | jfieldID GetPatchVersionField() { | ||
| 223 | return s_patch_version_field; | ||
| 224 | } | ||
| 225 | |||
| 226 | jfieldID GetPatchTypeField() { | ||
| 227 | return s_patch_type_field; | ||
| 228 | } | ||
| 229 | |||
| 230 | jfieldID GetPatchProgramIdField() { | ||
| 231 | return s_patch_program_id_field; | ||
| 232 | } | ||
| 233 | |||
| 234 | jfieldID GetPatchTitleIdField() { | ||
| 235 | return s_patch_title_id_field; | ||
| 236 | } | ||
| 237 | |||
| 189 | jclass GetDoubleClass() { | 238 | jclass GetDoubleClass() { |
| 190 | return s_double_class; | 239 | return s_double_class; |
| 191 | } | 240 | } |
| @@ -198,6 +247,30 @@ jfieldID GetDoubleValueField() { | |||
| 198 | return s_double_value_field; | 247 | return s_double_value_field; |
| 199 | } | 248 | } |
| 200 | 249 | ||
| 250 | jclass GetIntegerClass() { | ||
| 251 | return s_integer_class; | ||
| 252 | } | ||
| 253 | |||
| 254 | jmethodID GetIntegerConstructor() { | ||
| 255 | return s_integer_constructor; | ||
| 256 | } | ||
| 257 | |||
| 258 | jfieldID GetIntegerValueField() { | ||
| 259 | return s_integer_value_field; | ||
| 260 | } | ||
| 261 | |||
| 262 | jclass GetBooleanClass() { | ||
| 263 | return s_boolean_class; | ||
| 264 | } | ||
| 265 | |||
| 266 | jmethodID GetBooleanConstructor() { | ||
| 267 | return s_boolean_constructor; | ||
| 268 | } | ||
| 269 | |||
| 270 | jfieldID GetBooleanValueField() { | ||
| 271 | return s_boolean_value_field; | ||
| 272 | } | ||
| 273 | |||
| 201 | } // namespace IDCache | 274 | } // namespace IDCache |
| 202 | 275 | ||
| 203 | #ifdef __cplusplus | 276 | #ifdef __cplusplus |
| @@ -278,12 +351,37 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | |||
| 278 | env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); | 351 | env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); |
| 279 | env->DeleteLocalRef(overlay_control_data_class); | 352 | env->DeleteLocalRef(overlay_control_data_class); |
| 280 | 353 | ||
| 354 | const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch"); | ||
| 355 | s_patch_class = reinterpret_cast<jclass>(env->NewGlobalRef(patch_class)); | ||
| 356 | s_patch_constructor = env->GetMethodID( | ||
| 357 | patch_class, "<init>", | ||
| 358 | "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V"); | ||
| 359 | s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z"); | ||
| 360 | s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;"); | ||
| 361 | s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;"); | ||
| 362 | s_patch_type_field = env->GetFieldID(patch_class, "type", "I"); | ||
| 363 | s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;"); | ||
| 364 | s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;"); | ||
| 365 | env->DeleteLocalRef(patch_class); | ||
| 366 | |||
| 281 | const jclass double_class = env->FindClass("java/lang/Double"); | 367 | const jclass double_class = env->FindClass("java/lang/Double"); |
| 282 | s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class)); | 368 | s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class)); |
| 283 | s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V"); | 369 | s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V"); |
| 284 | s_double_value_field = env->GetFieldID(double_class, "value", "D"); | 370 | s_double_value_field = env->GetFieldID(double_class, "value", "D"); |
| 285 | env->DeleteLocalRef(double_class); | 371 | env->DeleteLocalRef(double_class); |
| 286 | 372 | ||
| 373 | const jclass int_class = env->FindClass("java/lang/Integer"); | ||
| 374 | s_integer_class = reinterpret_cast<jclass>(env->NewGlobalRef(int_class)); | ||
| 375 | s_integer_constructor = env->GetMethodID(int_class, "<init>", "(I)V"); | ||
| 376 | s_integer_value_field = env->GetFieldID(int_class, "value", "I"); | ||
| 377 | env->DeleteLocalRef(int_class); | ||
| 378 | |||
| 379 | const jclass boolean_class = env->FindClass("java/lang/Boolean"); | ||
| 380 | s_boolean_class = reinterpret_cast<jclass>(env->NewGlobalRef(boolean_class)); | ||
| 381 | s_boolean_constructor = env->GetMethodID(boolean_class, "<init>", "(Z)V"); | ||
| 382 | s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z"); | ||
| 383 | env->DeleteLocalRef(boolean_class); | ||
| 384 | |||
| 287 | // Initialize Android Storage | 385 | // Initialize Android Storage |
| 288 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); | 386 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); |
| 289 | 387 | ||
| @@ -309,7 +407,10 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { | |||
| 309 | env->DeleteGlobalRef(s_string_class); | 407 | env->DeleteGlobalRef(s_string_class); |
| 310 | env->DeleteGlobalRef(s_pair_class); | 408 | env->DeleteGlobalRef(s_pair_class); |
| 311 | env->DeleteGlobalRef(s_overlay_control_data_class); | 409 | env->DeleteGlobalRef(s_overlay_control_data_class); |
| 410 | env->DeleteGlobalRef(s_patch_class); | ||
| 312 | env->DeleteGlobalRef(s_double_class); | 411 | env->DeleteGlobalRef(s_double_class); |
| 412 | env->DeleteGlobalRef(s_integer_class); | ||
| 413 | env->DeleteGlobalRef(s_boolean_class); | ||
| 313 | 414 | ||
| 314 | // UnInitialize applets | 415 | // UnInitialize applets |
| 315 | SoftwareKeyboard::CleanupJNI(env); | 416 | SoftwareKeyboard::CleanupJNI(env); |
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h index 784d1412f..a002e705d 100644 --- a/src/android/app/src/main/jni/id_cache.h +++ b/src/android/app/src/main/jni/id_cache.h | |||
| @@ -43,8 +43,25 @@ jfieldID GetOverlayControlDataLandscapePositionField(); | |||
| 43 | jfieldID GetOverlayControlDataPortraitPositionField(); | 43 | jfieldID GetOverlayControlDataPortraitPositionField(); |
| 44 | jfieldID GetOverlayControlDataFoldablePositionField(); | 44 | jfieldID GetOverlayControlDataFoldablePositionField(); |
| 45 | 45 | ||
| 46 | jclass GetPatchClass(); | ||
| 47 | jmethodID GetPatchConstructor(); | ||
| 48 | jfieldID GetPatchEnabledField(); | ||
| 49 | jfieldID GetPatchNameField(); | ||
| 50 | jfieldID GetPatchVersionField(); | ||
| 51 | jfieldID GetPatchTypeField(); | ||
| 52 | jfieldID GetPatchProgramIdField(); | ||
| 53 | jfieldID GetPatchTitleIdField(); | ||
| 54 | |||
| 46 | jclass GetDoubleClass(); | 55 | jclass GetDoubleClass(); |
| 47 | jmethodID GetDoubleConstructor(); | 56 | jmethodID GetDoubleConstructor(); |
| 48 | jfieldID GetDoubleValueField(); | 57 | jfieldID GetDoubleValueField(); |
| 49 | 58 | ||
| 59 | jclass GetIntegerClass(); | ||
| 60 | jmethodID GetIntegerConstructor(); | ||
| 61 | jfieldID GetIntegerValueField(); | ||
| 62 | |||
| 63 | jclass GetBooleanClass(); | ||
| 64 | jmethodID GetBooleanConstructor(); | ||
| 65 | jfieldID GetBooleanValueField(); | ||
| 66 | |||
| 50 | } // namespace IDCache | 67 | } // namespace IDCache |
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index ed3b1353a..963f57380 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <core/file_sys/patch_manager.h> | 17 | #include <core/file_sys/patch_manager.h> |
| 18 | #include <core/file_sys/savedata_factory.h> | 18 | #include <core/file_sys/savedata_factory.h> |
| 19 | #include <core/loader/nro.h> | 19 | #include <core/loader/nro.h> |
| 20 | #include <frontend_common/content_manager.h> | ||
| 20 | #include <jni.h> | 21 | #include <jni.h> |
| 21 | 22 | ||
| 22 | #include "common/detached_tasks.h" | 23 | #include "common/detached_tasks.h" |
| @@ -100,67 +101,6 @@ void EmulationSession::SetNativeWindow(ANativeWindow* native_window) { | |||
| 100 | m_native_window = native_window; | 101 | m_native_window = native_window; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) { | ||
| 104 | jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 105 | std::size_t block_size) { | ||
| 106 | if (src == nullptr || dest == nullptr) { | ||
| 107 | return false; | ||
| 108 | } | ||
| 109 | if (!dest->Resize(src->GetSize())) { | ||
| 110 | return false; | ||
| 111 | } | ||
| 112 | |||
| 113 | using namespace Common::Literals; | ||
| 114 | [[maybe_unused]] std::vector<u8> buffer(1_MiB); | ||
| 115 | |||
| 116 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 117 | jconst read = src->Read(buffer.data(), buffer.size(), i); | ||
| 118 | dest->Write(buffer.data(), read, i); | ||
| 119 | } | ||
| 120 | return true; | ||
| 121 | }; | ||
| 122 | |||
| 123 | enum InstallResult { | ||
| 124 | Success = 0, | ||
| 125 | SuccessFileOverwritten = 1, | ||
| 126 | InstallError = 2, | ||
| 127 | ErrorBaseGame = 3, | ||
| 128 | ErrorFilenameExtension = 4, | ||
| 129 | }; | ||
| 130 | |||
| 131 | [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp; | ||
| 132 | if (file_extension == "nsp") { | ||
| 133 | nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read)); | ||
| 134 | if (nsp->IsExtractedType()) { | ||
| 135 | return InstallError; | ||
| 136 | } | ||
| 137 | } else { | ||
| 138 | return ErrorFilenameExtension; | ||
| 139 | } | ||
| 140 | |||
| 141 | if (!nsp) { | ||
| 142 | return InstallError; | ||
| 143 | } | ||
| 144 | |||
| 145 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 146 | return InstallError; | ||
| 147 | } | ||
| 148 | |||
| 149 | jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true, | ||
| 150 | copy_func); | ||
| 151 | |||
| 152 | switch (res) { | ||
| 153 | case FileSys::InstallResult::Success: | ||
| 154 | return Success; | ||
| 155 | case FileSys::InstallResult::OverwriteExisting: | ||
| 156 | return SuccessFileOverwritten; | ||
| 157 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 158 | return ErrorBaseGame; | ||
| 159 | default: | ||
| 160 | return InstallError; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, | 104 | void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, |
| 165 | const std::string& custom_driver_dir, | 105 | const std::string& custom_driver_dir, |
| 166 | const std::string& custom_driver_name, | 106 | const std::string& custom_driver_name, |
| @@ -512,10 +452,20 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject | |||
| 512 | } | 452 | } |
| 513 | 453 | ||
| 514 | int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, | 454 | int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, |
| 515 | jstring j_file, | 455 | jstring j_file, jobject jcallback) { |
| 516 | jstring j_file_extension) { | 456 | auto jlambdaClass = env->GetObjectClass(jcallback); |
| 517 | return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file), | 457 | auto jlambdaInvokeMethod = env->GetMethodID( |
| 518 | GetJString(env, j_file_extension)); | 458 | jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); |
| 459 | const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||
| 460 | auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||
| 461 | ToJDouble(env, max), ToJDouble(env, progress)); | ||
| 462 | return GetJBoolean(env, jwasCancelled); | ||
| 463 | }; | ||
| 464 | |||
| 465 | return static_cast<int>( | ||
| 466 | ContentManager::InstallNSP(&EmulationSession::GetInstance().System(), | ||
| 467 | EmulationSession::GetInstance().System().GetFilesystem().get(), | ||
| 468 | GetJString(env, j_file), callback)); | ||
| 519 | } | 469 | } |
| 520 | 470 | ||
| 521 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, | 471 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, |
| @@ -824,9 +774,9 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, | |||
| 824 | return true; | 774 | return true; |
| 825 | } | 775 | } |
| 826 | 776 | ||
| 827 | jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getAddonsForFile(JNIEnv* env, jobject jobj, | 777 | jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj, |
| 828 | jstring jpath, | 778 | jstring jpath, |
| 829 | jstring jprogramId) { | 779 | jstring jprogramId) { |
| 830 | const auto path = GetJString(env, jpath); | 780 | const auto path = GetJString(env, jpath); |
| 831 | const auto vFile = | 781 | const auto vFile = |
| 832 | Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); | 782 | Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); |
| @@ -843,20 +793,77 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getAddonsForFile(JNIEnv* env, | |||
| 843 | FileSys::VirtualFile update_raw; | 793 | FileSys::VirtualFile update_raw; |
| 844 | loader->ReadUpdateRaw(update_raw); | 794 | loader->ReadUpdateRaw(update_raw); |
| 845 | 795 | ||
| 846 | auto addons = pm.GetPatchVersionNames(update_raw); | 796 | auto patches = pm.GetPatches(update_raw); |
| 847 | auto jemptyString = ToJString(env, ""); | 797 | jobjectArray jpatchArray = |
| 848 | auto jemptyStringPair = env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | 798 | env->NewObjectArray(patches.size(), IDCache::GetPatchClass(), nullptr); |
| 849 | jemptyString, jemptyString); | ||
| 850 | jobjectArray jaddonsArray = | ||
| 851 | env->NewObjectArray(addons.size(), IDCache::GetPairClass(), jemptyStringPair); | ||
| 852 | int i = 0; | 799 | int i = 0; |
| 853 | for (const auto& addon : addons) { | 800 | for (const auto& patch : patches) { |
| 854 | jobject jaddon = env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | 801 | jobject jpatch = env->NewObject( |
| 855 | ToJString(env, addon.first), ToJString(env, addon.second)); | 802 | IDCache::GetPatchClass(), IDCache::GetPatchConstructor(), patch.enabled, |
| 856 | env->SetObjectArrayElement(jaddonsArray, i, jaddon); | 803 | ToJString(env, patch.name), ToJString(env, patch.version), |
| 804 | static_cast<jint>(patch.type), ToJString(env, std::to_string(patch.program_id)), | ||
| 805 | ToJString(env, std::to_string(patch.title_id))); | ||
| 806 | env->SetObjectArrayElement(jpatchArray, i, jpatch); | ||
| 857 | ++i; | 807 | ++i; |
| 858 | } | 808 | } |
| 859 | return jaddonsArray; | 809 | return jpatchArray; |
| 810 | } | ||
| 811 | |||
| 812 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject jobj, | ||
| 813 | jstring jprogramId) { | ||
| 814 | auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||
| 815 | ContentManager::RemoveUpdate(EmulationSession::GetInstance().System().GetFileSystemController(), | ||
| 816 | program_id); | ||
| 817 | } | ||
| 818 | |||
| 819 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj, | ||
| 820 | jstring jprogramId) { | ||
| 821 | auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||
| 822 | ContentManager::RemoveAllDLC(&EmulationSession::GetInstance().System(), program_id); | ||
| 823 | } | ||
| 824 | |||
| 825 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId, | ||
| 826 | jstring jname) { | ||
| 827 | auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||
| 828 | ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(), | ||
| 829 | program_id, GetJString(env, jname)); | ||
| 830 | } | ||
| 831 | |||
| 832 | jobject Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env, jobject jobj, | ||
| 833 | jobject jcallback) { | ||
| 834 | auto jlambdaClass = env->GetObjectClass(jcallback); | ||
| 835 | auto jlambdaInvokeMethod = env->GetMethodID( | ||
| 836 | jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | ||
| 837 | const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||
| 838 | auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||
| 839 | ToJDouble(env, max), ToJDouble(env, progress)); | ||
| 840 | return GetJBoolean(env, jwasCancelled); | ||
| 841 | }; | ||
| 842 | |||
| 843 | auto& session = EmulationSession::GetInstance(); | ||
| 844 | std::vector<std::string> result = ContentManager::VerifyInstalledContents( | ||
| 845 | &session.System(), session.GetContentProvider(), callback); | ||
| 846 | jobjectArray jresult = | ||
| 847 | env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, "")); | ||
| 848 | for (size_t i = 0; i < result.size(); ++i) { | ||
| 849 | env->SetObjectArrayElement(jresult, i, ToJString(env, result[i])); | ||
| 850 | } | ||
| 851 | return jresult; | ||
| 852 | } | ||
| 853 | |||
| 854 | jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobject jobj, | ||
| 855 | jstring jpath, jobject jcallback) { | ||
| 856 | auto jlambdaClass = env->GetObjectClass(jcallback); | ||
| 857 | auto jlambdaInvokeMethod = env->GetMethodID( | ||
| 858 | jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | ||
| 859 | const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||
| 860 | auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||
| 861 | ToJDouble(env, max), ToJDouble(env, progress)); | ||
| 862 | return GetJBoolean(env, jwasCancelled); | ||
| 863 | }; | ||
| 864 | auto& session = EmulationSession::GetInstance(); | ||
| 865 | return static_cast<jint>( | ||
| 866 | ContentManager::VerifyGameContents(&session.System(), GetJString(env, jpath), callback)); | ||
| 860 | } | 867 | } |
| 861 | 868 | ||
| 862 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, | 869 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, |
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 4a8049578..dadb138ad 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/file_sys/registered_cache.h" | 7 | #include "core/file_sys/registered_cache.h" |
| 8 | #include "core/hle/service/acc/profile_manager.h" | 8 | #include "core/hle/service/acc/profile_manager.h" |
| 9 | #include "core/perf_stats.h" | 9 | #include "core/perf_stats.h" |
| 10 | #include "frontend_common/content_manager.h" | ||
| 10 | #include "jni/applets/software_keyboard.h" | 11 | #include "jni/applets/software_keyboard.h" |
| 11 | #include "jni/emu_window/emu_window.h" | 12 | #include "jni/emu_window/emu_window.h" |
| 12 | #include "video_core/rasterizer_interface.h" | 13 | #include "video_core/rasterizer_interface.h" |
| @@ -29,7 +30,6 @@ public: | |||
| 29 | void SetNativeWindow(ANativeWindow* native_window); | 30 | void SetNativeWindow(ANativeWindow* native_window); |
| 30 | void SurfaceChanged(); | 31 | void SurfaceChanged(); |
| 31 | 32 | ||
| 32 | int InstallFileToNand(std::string filename, std::string file_extension); | ||
| 33 | void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, | 33 | void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, |
| 34 | const std::string& custom_driver_name, | 34 | const std::string& custom_driver_name, |
| 35 | const std::string& file_redirect_dir); | 35 | const std::string& file_redirect_dir); |
diff --git a/src/android/app/src/main/res/drawable/ic_lock.xml b/src/android/app/src/main/res/drawable/ic_lock.xml new file mode 100644 index 000000000..ef97b1936 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_lock.xml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | android:height="24dp" | ||
| 3 | android:viewportHeight="24" | ||
| 4 | android:viewportWidth="24" | ||
| 5 | android:width="24dp"> | ||
| 6 | <path | ||
| 7 | android:fillColor="?attr/colorControlNormal" | ||
| 8 | android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" /> | ||
| 9 | </vector> | ||
diff --git a/src/android/app/src/main/res/drawable/ic_shortcut.xml b/src/android/app/src/main/res/drawable/ic_shortcut.xml new file mode 100644 index 000000000..06e1983b2 --- /dev/null +++ b/src/android/app/src/main/res/drawable/ic_shortcut.xml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 2 | android:width="24dp" | ||
| 3 | android:height="24dp" | ||
| 4 | android:viewportWidth="960" | ||
| 5 | android:viewportHeight="960"> | ||
| 6 | <path | ||
| 7 | android:fillColor="?attr/colorControlNormal" | ||
| 8 | android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v160h-80v-40L280,240v480h400v-40h80v160q0,33 -23.5,56.5T680,920L280,920ZM686,520L480,520v120h-80v-120q0,-33 23.5,-56.5T480,440h206l-62,-64 56,-56 160,160 -160,160 -56,-56 62,-64Z" /> | ||
| 9 | </vector> | ||
diff --git a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml index 0b9633855..551f255c0 100644 --- a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml +++ b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml | |||
| @@ -43,16 +43,35 @@ | |||
| 43 | app:layout_constraintStart_toStartOf="parent" | 43 | app:layout_constraintStart_toStartOf="parent" |
| 44 | app:layout_constraintTop_toTopOf="parent"> | 44 | app:layout_constraintTop_toTopOf="parent"> |
| 45 | 45 | ||
| 46 | <Button | 46 | <androidx.constraintlayout.widget.ConstraintLayout |
| 47 | android:id="@+id/button_back" | 47 | android:layout_width="match_parent" |
| 48 | style="?attr/materialIconButtonStyle" | ||
| 49 | android:layout_width="wrap_content" | ||
| 50 | android:layout_height="wrap_content" | 48 | android:layout_height="wrap_content" |
| 51 | android:layout_gravity="start" | ||
| 52 | android:layout_margin="8dp" | 49 | android:layout_margin="8dp" |
| 53 | app:icon="@drawable/ic_back" | 50 | android:orientation="horizontal"> |
| 54 | app:iconSize="24dp" | 51 | |
| 55 | app:iconTint="?attr/colorOnSurface" /> | 52 | <Button |
| 53 | android:id="@+id/button_back" | ||
| 54 | style="?attr/materialIconButtonStyle" | ||
| 55 | android:layout_width="wrap_content" | ||
| 56 | android:layout_height="wrap_content" | ||
| 57 | app:icon="@drawable/ic_back" | ||
| 58 | app:iconSize="24dp" | ||
| 59 | app:iconTint="?attr/colorOnSurface" | ||
| 60 | app:layout_constraintStart_toStartOf="parent" | ||
| 61 | app:layout_constraintTop_toTopOf="parent" /> | ||
| 62 | |||
| 63 | <Button | ||
| 64 | android:id="@+id/button_shortcut" | ||
| 65 | style="?attr/materialIconButtonStyle" | ||
| 66 | android:layout_width="wrap_content" | ||
| 67 | android:layout_height="wrap_content" | ||
| 68 | app:icon="@drawable/ic_shortcut" | ||
| 69 | app:iconSize="24dp" | ||
| 70 | app:iconTint="?attr/colorOnSurface" | ||
| 71 | app:layout_constraintTop_toTopOf="parent" | ||
| 72 | app:layout_constraintEnd_toEndOf="parent" /> | ||
| 73 | |||
| 74 | </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 56 | 75 | ||
| 57 | <com.google.android.material.card.MaterialCardView | 76 | <com.google.android.material.card.MaterialCardView |
| 58 | style="?attr/materialCardViewElevatedStyle" | 77 | style="?attr/materialCardViewElevatedStyle" |
diff --git a/src/android/app/src/main/res/layout/card_home_option.xml b/src/android/app/src/main/res/layout/card_home_option.xml index cb667c928..224ec4d89 100644 --- a/src/android/app/src/main/res/layout/card_home_option.xml +++ b/src/android/app/src/main/res/layout/card_home_option.xml | |||
| @@ -2,16 +2,16 @@ | |||
| 2 | <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto" | 3 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 4 | xmlns:tools="http://schemas.android.com/tools" | 4 | xmlns:tools="http://schemas.android.com/tools" |
| 5 | style="?attr/materialCardViewFilledStyle" | 5 | style="?attr/materialCardViewElevatedStyle" |
| 6 | android:id="@+id/option_card" | 6 | android:id="@+id/option_card" |
| 7 | android:layout_width="match_parent" | 7 | android:layout_width="match_parent" |
| 8 | android:layout_height="wrap_content" | 8 | android:layout_height="wrap_content" |
| 9 | android:layout_marginBottom="24dp" | 9 | android:layout_marginBottom="24dp" |
| 10 | android:layout_marginHorizontal="12dp" | 10 | android:layout_marginHorizontal="12dp" |
| 11 | android:background="?attr/selectableItemBackground" | 11 | android:background="?attr/selectableItemBackground" |
| 12 | android:backgroundTint="?attr/colorSurfaceVariant" | ||
| 13 | android:clickable="true" | 12 | android:clickable="true" |
| 14 | android:focusable="true"> | 13 | android:focusable="true" |
| 14 | app:cardElevation="4dp"> | ||
| 15 | 15 | ||
| 16 | <LinearLayout | 16 | <LinearLayout |
| 17 | android:id="@+id/option_layout" | 17 | android:id="@+id/option_layout" |
diff --git a/src/android/app/src/main/res/layout/dialog_progress_bar.xml b/src/android/app/src/main/res/layout/dialog_progress_bar.xml index 0209ea082..e61aa5294 100644 --- a/src/android/app/src/main/res/layout/dialog_progress_bar.xml +++ b/src/android/app/src/main/res/layout/dialog_progress_bar.xml | |||
| @@ -1,8 +1,30 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <com.google.android.material.progressindicator.LinearProgressIndicator xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto" | 3 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 4 | android:id="@+id/progress_bar" | ||
| 5 | android:layout_width="match_parent" | 4 | android:layout_width="match_parent" |
| 6 | android:layout_height="wrap_content" | 5 | android:layout_height="wrap_content" |
| 7 | android:padding="24dp" | 6 | android:orientation="vertical"> |
| 8 | app:trackCornerRadius="4dp" /> | 7 | |
| 8 | <com.google.android.material.textview.MaterialTextView | ||
| 9 | android:id="@+id/message" | ||
| 10 | style="@style/TextAppearance.Material3.BodyMedium" | ||
| 11 | android:layout_width="match_parent" | ||
| 12 | android:layout_height="wrap_content" | ||
| 13 | android:layout_marginHorizontal="24dp" | ||
| 14 | android:layout_marginTop="12dp" | ||
| 15 | android:layout_marginBottom="6dp" | ||
| 16 | android:ellipsize="marquee" | ||
| 17 | android:marqueeRepeatLimit="marquee_forever" | ||
| 18 | android:requiresFadingEdge="horizontal" | ||
| 19 | android:singleLine="true" | ||
| 20 | android:textAlignment="viewStart" | ||
| 21 | android:visibility="gone" /> | ||
| 22 | |||
| 23 | <com.google.android.material.progressindicator.LinearProgressIndicator | ||
| 24 | android:id="@+id/progress_bar" | ||
| 25 | android:layout_width="match_parent" | ||
| 26 | android:layout_height="wrap_content" | ||
| 27 | android:padding="24dp" | ||
| 28 | app:trackCornerRadius="4dp" /> | ||
| 29 | |||
| 30 | </LinearLayout> | ||
diff --git a/src/android/app/src/main/res/layout/fragment_game_info.xml b/src/android/app/src/main/res/layout/fragment_game_info.xml index 80ede8a8c..53af15787 100644 --- a/src/android/app/src/main/res/layout/fragment_game_info.xml +++ b/src/android/app/src/main/res/layout/fragment_game_info.xml | |||
| @@ -118,6 +118,14 @@ | |||
| 118 | android:layout_marginTop="16dp" | 118 | android:layout_marginTop="16dp" |
| 119 | android:text="@string/copy_details" /> | 119 | android:text="@string/copy_details" /> |
| 120 | 120 | ||
| 121 | <com.google.android.material.button.MaterialButton | ||
| 122 | android:id="@+id/button_verify_integrity" | ||
| 123 | style="@style/Widget.Material3.Button" | ||
| 124 | android:layout_width="wrap_content" | ||
| 125 | android:layout_height="wrap_content" | ||
| 126 | android:layout_marginTop="10dp" | ||
| 127 | android:text="@string/verify_integrity" /> | ||
| 128 | |||
| 121 | </LinearLayout> | 129 | </LinearLayout> |
| 122 | 130 | ||
| 123 | </androidx.core.widget.NestedScrollView> | 131 | </androidx.core.widget.NestedScrollView> |
diff --git a/src/android/app/src/main/res/layout/fragment_game_properties.xml b/src/android/app/src/main/res/layout/fragment_game_properties.xml index 72ecbde30..cadd0bc4a 100644 --- a/src/android/app/src/main/res/layout/fragment_game_properties.xml +++ b/src/android/app/src/main/res/layout/fragment_game_properties.xml | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <androidx.constraintlayout.widget.ConstraintLayout | 2 | <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 3 | xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 4 | xmlns:app="http://schemas.android.com/apk/res-auto" | 3 | xmlns:app="http://schemas.android.com/apk/res-auto" |
| 5 | xmlns:tools="http://schemas.android.com/tools" | 4 | xmlns:tools="http://schemas.android.com/tools" |
| 6 | android:layout_width="match_parent" | 5 | android:layout_width="match_parent" |
| @@ -22,16 +21,35 @@ | |||
| 22 | android:orientation="vertical" | 21 | android:orientation="vertical" |
| 23 | android:gravity="center_horizontal"> | 22 | android:gravity="center_horizontal"> |
| 24 | 23 | ||
| 25 | <Button | 24 | <androidx.constraintlayout.widget.ConstraintLayout |
| 26 | android:id="@+id/button_back" | 25 | android:layout_width="match_parent" |
| 27 | style="?attr/materialIconButtonStyle" | ||
| 28 | android:layout_width="wrap_content" | ||
| 29 | android:layout_height="wrap_content" | 26 | android:layout_height="wrap_content" |
| 30 | android:layout_margin="8dp" | 27 | android:layout_margin="8dp" |
| 31 | android:layout_gravity="start" | 28 | android:orientation="horizontal"> |
| 32 | app:icon="@drawable/ic_back" | 29 | |
| 33 | app:iconSize="24dp" | 30 | <Button |
| 34 | app:iconTint="?attr/colorOnSurface" /> | 31 | android:id="@+id/button_back" |
| 32 | style="?attr/materialIconButtonStyle" | ||
| 33 | android:layout_width="wrap_content" | ||
| 34 | android:layout_height="wrap_content" | ||
| 35 | app:icon="@drawable/ic_back" | ||
| 36 | app:iconSize="24dp" | ||
| 37 | app:iconTint="?attr/colorOnSurface" | ||
| 38 | app:layout_constraintStart_toStartOf="parent" | ||
| 39 | app:layout_constraintTop_toTopOf="parent" /> | ||
| 40 | |||
| 41 | <Button | ||
| 42 | android:id="@+id/button_shortcut" | ||
| 43 | style="?attr/materialIconButtonStyle" | ||
| 44 | android:layout_width="wrap_content" | ||
| 45 | android:layout_height="wrap_content" | ||
| 46 | app:icon="@drawable/ic_shortcut" | ||
| 47 | app:iconSize="24dp" | ||
| 48 | app:iconTint="?attr/colorOnSurface" | ||
| 49 | app:layout_constraintEnd_toEndOf="parent" | ||
| 50 | app:layout_constraintTop_toTopOf="parent" /> | ||
| 51 | |||
| 52 | </androidx.constraintlayout.widget.ConstraintLayout> | ||
| 35 | 53 | ||
| 36 | <com.google.android.material.card.MaterialCardView | 54 | <com.google.android.material.card.MaterialCardView |
| 37 | style="?attr/materialCardViewElevatedStyle" | 55 | style="?attr/materialCardViewElevatedStyle" |
| @@ -45,7 +63,7 @@ | |||
| 45 | android:id="@+id/image_game_screen" | 63 | android:id="@+id/image_game_screen" |
| 46 | android:layout_width="175dp" | 64 | android:layout_width="175dp" |
| 47 | android:layout_height="175dp" | 65 | android:layout_height="175dp" |
| 48 | tools:src="@drawable/default_icon"/> | 66 | tools:src="@drawable/default_icon" /> |
| 49 | 67 | ||
| 50 | </com.google.android.material.card.MaterialCardView> | 68 | </com.google.android.material.card.MaterialCardView> |
| 51 | 69 | ||
diff --git a/src/android/app/src/main/res/layout/list_item_addon.xml b/src/android/app/src/main/res/layout/list_item_addon.xml index 74ca04ef1..3a1382fe2 100644 --- a/src/android/app/src/main/res/layout/list_item_addon.xml +++ b/src/android/app/src/main/res/layout/list_item_addon.xml | |||
| @@ -14,12 +14,11 @@ | |||
| 14 | android:id="@+id/text_container" | 14 | android:id="@+id/text_container" |
| 15 | android:layout_width="0dp" | 15 | android:layout_width="0dp" |
| 16 | android:layout_height="wrap_content" | 16 | android:layout_height="wrap_content" |
| 17 | android:layout_marginEnd="16dp" | ||
| 18 | android:orientation="vertical" | 17 | android:orientation="vertical" |
| 19 | app:layout_constraintBottom_toBottomOf="@+id/addon_switch" | 18 | android:layout_marginEnd="16dp" |
| 20 | app:layout_constraintEnd_toStartOf="@+id/addon_switch" | 19 | app:layout_constraintEnd_toStartOf="@+id/addon_checkbox" |
| 21 | app:layout_constraintStart_toStartOf="parent" | 20 | app:layout_constraintStart_toStartOf="parent" |
| 22 | app:layout_constraintTop_toTopOf="@+id/addon_switch"> | 21 | app:layout_constraintTop_toTopOf="parent"> |
| 23 | 22 | ||
| 24 | <com.google.android.material.textview.MaterialTextView | 23 | <com.google.android.material.textview.MaterialTextView |
| 25 | android:id="@+id/title" | 24 | android:id="@+id/title" |
| @@ -42,16 +41,29 @@ | |||
| 42 | 41 | ||
| 43 | </LinearLayout> | 42 | </LinearLayout> |
| 44 | 43 | ||
| 45 | <com.google.android.material.materialswitch.MaterialSwitch | 44 | <com.google.android.material.checkbox.MaterialCheckBox |
| 46 | android:id="@+id/addon_switch" | 45 | android:id="@+id/addon_checkbox" |
| 47 | android:layout_width="wrap_content" | 46 | android:layout_width="wrap_content" |
| 48 | android:layout_height="wrap_content" | 47 | android:layout_height="wrap_content" |
| 49 | android:focusable="true" | 48 | android:focusable="true" |
| 50 | android:gravity="center" | 49 | android:gravity="center" |
| 51 | android:nextFocusLeft="@id/addon_container" | 50 | android:layout_marginEnd="8dp" |
| 52 | app:layout_constraintBottom_toBottomOf="parent" | 51 | app:layout_constraintTop_toTopOf="@+id/text_container" |
| 52 | app:layout_constraintBottom_toBottomOf="@+id/text_container" | ||
| 53 | app:layout_constraintEnd_toStartOf="@+id/button_delete" /> | ||
| 54 | |||
| 55 | <Button | ||
| 56 | android:id="@+id/button_delete" | ||
| 57 | style="@style/Widget.Material3.Button.IconButton" | ||
| 58 | android:layout_width="wrap_content" | ||
| 59 | android:layout_height="wrap_content" | ||
| 60 | android:layout_gravity="center_vertical" | ||
| 61 | android:contentDescription="@string/delete" | ||
| 62 | android:tooltipText="@string/delete" | ||
| 63 | app:icon="@drawable/ic_delete" | ||
| 64 | app:iconTint="?attr/colorControlNormal" | ||
| 53 | app:layout_constraintEnd_toEndOf="parent" | 65 | app:layout_constraintEnd_toEndOf="parent" |
| 54 | app:layout_constraintStart_toEndOf="@id/text_container" | 66 | app:layout_constraintTop_toTopOf="@+id/addon_checkbox" |
| 55 | app:layout_constraintTop_toTopOf="parent" /> | 67 | app:layout_constraintBottom_toBottomOf="@+id/addon_checkbox" /> |
| 56 | 68 | ||
| 57 | </androidx.constraintlayout.widget.ConstraintLayout> | 69 | </androidx.constraintlayout.widget.ConstraintLayout> |
diff --git a/src/android/app/src/main/res/layout/list_item_setting.xml b/src/android/app/src/main/res/layout/list_item_setting.xml index 1f80682f1..e13431497 100644 --- a/src/android/app/src/main/res/layout/list_item_setting.xml +++ b/src/android/app/src/main/res/layout/list_item_setting.xml | |||
| @@ -69,7 +69,7 @@ | |||
| 69 | android:layout_height="wrap_content" | 69 | android:layout_height="wrap_content" |
| 70 | android:layout_marginTop="16dp" | 70 | android:layout_marginTop="16dp" |
| 71 | android:visibility="gone" | 71 | android:visibility="gone" |
| 72 | android:text="@string/clear" | 72 | android:text="@string/use_global_setting" |
| 73 | tools:visibility="visible" /> | 73 | tools:visibility="visible" /> |
| 74 | 74 | ||
| 75 | </LinearLayout> | 75 | </LinearLayout> |
diff --git a/src/android/app/src/main/res/layout/list_item_setting_switch.xml b/src/android/app/src/main/res/layout/list_item_setting_switch.xml index 1c08e2e1b..e23337058 100644 --- a/src/android/app/src/main/res/layout/list_item_setting_switch.xml +++ b/src/android/app/src/main/res/layout/list_item_setting_switch.xml | |||
| @@ -63,7 +63,7 @@ | |||
| 63 | android:layout_width="wrap_content" | 63 | android:layout_width="wrap_content" |
| 64 | android:layout_height="wrap_content" | 64 | android:layout_height="wrap_content" |
| 65 | android:layout_marginTop="16dp" | 65 | android:layout_marginTop="16dp" |
| 66 | android:text="@string/clear" | 66 | android:text="@string/use_global_setting" |
| 67 | android:visibility="gone" | 67 | android:visibility="gone" |
| 68 | tools:visibility="visible" /> | 68 | tools:visibility="visible" /> |
| 69 | 69 | ||
diff --git a/src/android/app/src/main/res/menu/menu_driver_manager.xml b/src/android/app/src/main/res/menu/menu_driver_manager.xml index dee5d57b6..0876c2194 100644 --- a/src/android/app/src/main/res/menu/menu_driver_manager.xml +++ b/src/android/app/src/main/res/menu/menu_driver_manager.xml | |||
| @@ -1,11 +1,8 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <menu xmlns:android="http://schemas.android.com/apk/res/android" | 2 | <menu xmlns:android="http://schemas.android.com/apk/res/android"> |
| 3 | xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
| 4 | 3 | ||
| 5 | <item | 4 | <item |
| 6 | android:id="@+id/menu_driver_clear" | 5 | android:id="@+id/menu_driver_use_global" |
| 7 | android:icon="@drawable/ic_clear" | 6 | android:title="@string/use_global_setting" /> |
| 8 | android:title="@string/clear" | ||
| 9 | app:showAsAction="always" /> | ||
| 10 | 7 | ||
| 11 | </menu> | 8 | </menu> |
diff --git a/src/android/app/src/main/res/menu/menu_in_game.xml b/src/android/app/src/main/res/menu/menu_in_game.xml index ac6ab06ff..eecb0563b 100644 --- a/src/android/app/src/main/res/menu/menu_in_game.xml +++ b/src/android/app/src/main/res/menu/menu_in_game.xml | |||
| @@ -22,6 +22,11 @@ | |||
| 22 | android:title="@string/emulation_input_overlay" /> | 22 | android:title="@string/emulation_input_overlay" /> |
| 23 | 23 | ||
| 24 | <item | 24 | <item |
| 25 | android:id="@+id/menu_lock_drawer" | ||
| 26 | android:icon="@drawable/ic_unlock" | ||
| 27 | android:title="@string/emulation_input_overlay" /> | ||
| 28 | |||
| 29 | <item | ||
| 25 | android:id="@+id/menu_exit" | 30 | android:id="@+id/menu_exit" |
| 26 | android:icon="@drawable/ic_exit" | 31 | android:icon="@drawable/ic_exit" |
| 27 | android:title="@string/emulation_exit" /> | 32 | android:title="@string/emulation_exit" /> |
diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml index 07dffffe8..53678f465 100644 --- a/src/android/app/src/main/res/values-ar/strings.xml +++ b/src/android/app/src/main/res/values-ar/strings.xml | |||
| @@ -3,38 +3,39 @@ | |||
| 3 | 3 | ||
| 4 | <string name="emulation_notification_channel_name">Ø§Ù„Ù…ØØ§ÙƒÙŠ Ù†Ø´Ø·</string> | 4 | <string name="emulation_notification_channel_name">Ø§Ù„Ù…ØØ§ÙƒÙŠ Ù†Ø´Ø·</string> |
| 5 | <string name="emulation_notification_channel_description">اظهار اشعار دائم عندما يكون Ø§Ù„Ù…ØØ§ÙƒÙŠ Ù†Ø´Ø·Ø§Ù‹</string> | 5 | <string name="emulation_notification_channel_description">اظهار اشعار دائم عندما يكون Ø§Ù„Ù…ØØ§ÙƒÙŠ Ù†Ø´Ø·Ø§Ù‹</string> |
| 6 | <string name="emulation_notification_running">يوزو يعمل</string> | 6 | <string name="emulation_notification_running">يوزو قيد التشغيل</string> |
| 7 | <string name="notice_notification_channel_name">الإشعارات والأخطاء</string> | 7 | <string name="notice_notification_channel_name">الإشعارات والأخطاء</string> |
| 8 | <string name="notice_notification_channel_description">اظهار اشعار عند ØØµÙˆÙ„ اي مشكلة.</string> | 8 | <string name="notice_notification_channel_description">اظهار اشعار عند ØØµÙˆÙ„ اي مشكلة.</string> |
| 9 | <string name="notification_permission_not_granted">لم يتم Ù…Ù†Ø Ø¥Ø°Ù† الإشعار</string> | 9 | <string name="notification_permission_not_granted">لم يتم Ù…Ù†Ø Ø¥Ø°Ù† الإشعار</string> |
| 10 | 10 | ||
| 11 | <!-- Setup strings --> | 11 | <!-- Setup strings --> |
| 12 | <string name="welcome">Ù…Ø±ØØ¨Ù‹Ø§</string> | 12 | <string name="welcome">Ù…Ø±ØØ¨Ø§</string> |
| 13 | <string name="welcome_description">والانتقال إلى Ø§Ù„Ù…ØØ§ÙƒØ§Ø© <b>يوزو</b> تعر٠على كيÙية إعداد.</string> | 13 | <string name="welcome_description">تعر٠على كيÙية إعداد <b>يوزو</b> والانتقال إلى Ø§Ù„Ù…ØØ§ÙƒØ§Ø©</string> |
| 14 | <string name="get_started">لنبدأ</string> | 14 | <string name="get_started">لنبدأ</string> |
| 15 | <string name="keys">Ø§Ù„Ù…ÙØ§ØªÙŠØ</string> | 15 | <string name="keys">Ø§Ù„Ù…ÙØ§ØªÙŠØ</string> |
| 16 | <string name="keys_description">اختر مل٠<b>prod.keys</b> من الزر ادناه</string> | 16 | <string name="keys_description">اختر مل٠<b>prod.keys</b> من الزر ادناه</string> |
| 17 | <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ</string> | 17 | <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ</string> |
| 18 | <string name="games">الألعاب</string> | 18 | <string name="games">الألعاب</string> |
| 19 | <string name="games_description">اختر مجلد <b>العابك</b> من الزر ادناه.</string> | 19 | <string name="games_description">ØØ¯Ø¯ مجلد <b>العابك</b> من الزر ادناه.</string> |
| 20 | <string name="done">إنهاء</string> | 20 | <string name="done">إنهاء</string> |
| 21 | <string name="done_description">كل شيء جاهز./n استمتع بألعابك!</string> | 21 | <string name="done_description">أنت جاهز تمامًا. استمتع بألعابك!</string> |
| 22 | <string name="text_continue">استمر</string> | 22 | <string name="text_continue">استمر</string> |
| 23 | <string name="next">التالي</string> | 23 | <string name="next">التالي</string> |
| 24 | <string name="back">عودة</string> | 24 | <string name="back">عودة</string> |
| 25 | <string name="add_games">Ø¥Ø¶Ø§ÙØ© ألعاب</string> | 25 | <string name="add_games">Ø¥Ø¶Ø§ÙØ© ألعاب</string> |
| 26 | <string name="add_games_description">إختار مجلد ألعابك</string> | 26 | <string name="add_games_description">ØØ¯Ø¯ مجلد الألعاب الخاص بك</string> |
| 27 | <string name="step_complete">مكتمل</string> | 27 | <string name="step_complete">مكتمل</string> |
| 28 | 28 | ||
| 29 | <!-- Home strings --> | 29 | <!-- Home strings --> |
| 30 | <string name="home_games">الألعاب</string> | 30 | <string name="home_games">الألعاب</string> |
| 31 | <string name="home_search">Ø§Ù„Ø¨ØØ«</string> | 31 | <string name="home_search">Ø§Ù„Ø¨ØØ«</string> |
| 32 | <string name="home_settings">الإعدادات</string> | 32 | <string name="home_settings">الإعدادات</string> |
| 33 | <string name="empty_gamelist">لم يتم العثور على Ù…Ù„ÙØ§Øª او لم يتم ØªØØ¯ÙŠØ¯ مسار العاب.</string> | 33 | <string name="empty_gamelist">لم يتم العثور على Ù…Ù„ÙØ§Øª أو لم يتم ØªØØ¯ÙŠØ¯ مجلد الألعاب ØØªÙ‰ الآن.</string> |
| 34 | <string name="search_and_filter_games">Ø¨ØØ« وتصÙية الألعاب</string> | 34 | <string name="search_and_filter_games">Ø§Ù„Ø¨ØØ« وتصÙية الألعاب</string> |
| 35 | <string name="select_games_folder">ØªØØ¯ÙŠØ¯ مجلد الألعاب</string> | 35 | <string name="select_games_folder">ØØ¯Ø¯ مجلد الألعاب</string> |
| 36 | <string name="manage_game_folders">إدارة مجلدات اللعبة</string> | ||
| 36 | <string name="select_games_folder_description">ÙŠØ³Ù…Ø Ù„Ù€ يوزو بملء قائمة الألعاب</string> | 37 | <string name="select_games_folder_description">ÙŠØ³Ù…Ø Ù„Ù€ يوزو بملء قائمة الألعاب</string> |
| 37 | <string name="add_games_warning">تخط٠اختيار مجلد الالعاب؟</string> | 38 | <string name="add_games_warning">تخطي ØªØØ¯ÙŠØ¯ مجلد الألعاب؟</string> |
| 38 | <string name="add_games_warning_description">لن يتم عرض الألعاب ÙÙŠ قائمة الألعاب إذا لم يتم ØªØØ¯ÙŠØ¯ مجلد</string> | 39 | <string name="add_games_warning_description">لن يتم عرض الألعاب ÙÙŠ قائمة الألعاب إذا لم يتم ØªØØ¯ÙŠØ¯ مجلد</string> |
| 39 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| 40 | <string name="home_search_games">Ø§Ù„Ø¨ØØ« عن ألعاب</string> | 41 | <string name="home_search_games">Ø§Ù„Ø¨ØØ« عن ألعاب</string> |
| @@ -45,7 +46,7 @@ | |||
| 45 | <string name="install_prod_keys_warning">تخطي Ø¥Ø¶Ø§ÙØ© Ø§Ù„Ù…ÙØ§ØªÙŠØØŸ</string> | 46 | <string name="install_prod_keys_warning">تخطي Ø¥Ø¶Ø§ÙØ© Ø§Ù„Ù…ÙØ§ØªÙŠØØŸ</string> |
| 46 | <string name="install_prod_keys_warning_description">مطلوب Ù…ÙØ§ØªÙŠØ ØµØ§Ù„ØØ© Ù„Ù…ØØ§ÙƒØ§Ø© ألعاب البيع بالتجزئة. ستعمل تطبيقات البيرة المنزلية Ùقط إذا تابعت</string> | 47 | <string name="install_prod_keys_warning_description">مطلوب Ù…ÙØ§ØªÙŠØ ØµØ§Ù„ØØ© Ù„Ù…ØØ§ÙƒØ§Ø© ألعاب البيع بالتجزئة. ستعمل تطبيقات البيرة المنزلية Ùقط إذا تابعت</string> |
| 47 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> | 48 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> |
| 48 | <string name="notifications">التنبيهات</string> | 49 | <string name="notifications">الإشعارات</string> |
| 49 | <string name="notifications_description">Ø§Ù…Ù†Ø Ø¥Ø°Ù† الإشعار باستخدام الزر أدناه</string> | 50 | <string name="notifications_description">Ø§Ù…Ù†Ø Ø¥Ø°Ù† الإشعار باستخدام الزر أدناه</string> |
| 50 | <string name="give_permission">Ù…Ù†Ø Ø§Ù„Ø¥Ø°Ù†</string> | 51 | <string name="give_permission">Ù…Ù†Ø Ø§Ù„Ø¥Ø°Ù†</string> |
| 51 | <string name="notification_warning">تخطي Ù…Ù†Ø Ø¥Ø°Ù† الإشعارات؟</string> | 52 | <string name="notification_warning">تخطي Ù…Ù†Ø Ø¥Ø°Ù† الإشعارات؟</string> |
| @@ -62,9 +63,12 @@ | |||
| 62 | <string name="invalid_keys_file">تم ØªØØ¯ÙŠØ¯ Ù…Ù„Ù Ù…ÙØ§ØªÙŠØ غير صالØ</string> | 63 | <string name="invalid_keys_file">تم ØªØØ¯ÙŠØ¯ Ù…Ù„Ù Ù…ÙØ§ØªÙŠØ غير صالØ</string> |
| 63 | <string name="install_keys_success">تم تثبيت Ø§Ù„Ù…ÙØ§ØªÙŠØ بنجاØ</string> | 64 | <string name="install_keys_success">تم تثبيت Ø§Ù„Ù…ÙØ§ØªÙŠØ بنجاØ</string> |
| 64 | <string name="reading_keys_failure">خطأ ÙÙŠ قراءة Ù…ÙØ§ØªÙŠØ التشÙير</string> | 65 | <string name="reading_keys_failure">خطأ ÙÙŠ قراءة Ù…ÙØ§ØªÙŠØ التشÙير</string> |
| 66 | <string name="install_prod_keys_failure_extension_description">ÙˆØØ§ÙˆÙ„ مرة أخر keys تØÙ‚Ù‚ من أن Ù…Ù„Ù Ø§Ù„Ù…ÙØ§ØªÙŠØ له امتداد</string> | ||
| 67 | <string name="install_amiibo_keys_failure_extension_description">ÙˆØØ§ÙˆÙ„ مرة أخر bin تØÙ‚Ù‚ من أن Ù…Ù„Ù Ø§Ù„Ù…ÙØ§ØªÙŠØ له امتداد</string> | ||
| 65 | <string name="invalid_keys_error">Ù…ÙØ§ØªÙŠØ التشÙير غير ØµØ§Ù„ØØ©</string> | 68 | <string name="invalid_keys_error">Ù…ÙØ§ØªÙŠØ التشÙير غير ØµØ§Ù„ØØ©</string> |
| 66 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 67 | <string name="install_keys_failure_description">Ø§Ù„Ù…Ù„Ù Ø§Ù„Ù…ØØ¯Ø¯ غير صØÙŠØ أو تالÙ. يرجى إعادة Ø§Ù„Ù…ÙØ§ØªÙŠØ الخاصة بك</string> | 70 | <string name="install_keys_failure_description">Ø§Ù„Ù…Ù„Ù Ø§Ù„Ù…ØØ¯Ø¯ غير صØÙŠØ أو تالÙ. يرجى إعادة Ø§Ù„Ù…ÙØ§ØªÙŠØ الخاصة بك</string> |
| 71 | <string name="gpu_driver_manager">GPU مدير برنامج تشغيل</string> | ||
| 68 | <string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string> | 72 | <string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string> |
| 69 | <string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة Ù„Ù„ØØµÙˆÙ„ على أداء أو دقة Ø£ÙØ¶Ù„</string> | 73 | <string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة Ù„Ù„ØØµÙˆÙ„ على أداء أو دقة Ø£ÙØ¶Ù„</string> |
| 70 | <string name="advanced_settings">إعدادات متقدمة</string> | 74 | <string name="advanced_settings">إعدادات متقدمة</string> |
| @@ -82,22 +86,27 @@ | |||
| 82 | <string name="notification_no_directory_link_description">الرجاء ØªØØ¯ÙŠØ¯ موقع مجلد المستخدم باستخدام Ø§Ù„Ù„ÙˆØØ© الجانبية لمدير Ø§Ù„Ù…Ù„ÙØ§Øª يدويًا</string> | 86 | <string name="notification_no_directory_link_description">الرجاء ØªØØ¯ÙŠØ¯ موقع مجلد المستخدم باستخدام Ø§Ù„Ù„ÙˆØØ© الجانبية لمدير Ø§Ù„Ù…Ù„ÙØ§Øª يدويًا</string> |
| 83 | <string name="manage_save_data">إدارة ØÙظ البيانات</string> | 87 | <string name="manage_save_data">إدارة ØÙظ البيانات</string> |
| 84 | <string name="manage_save_data_description">ØÙظ البيانات التي تم العثور عليها. يرجى اختيار Ø£ØØ¯ الخيارات التالية</string> | 88 | <string name="manage_save_data_description">ØÙظ البيانات التي تم العثور عليها. يرجى اختيار Ø£ØØ¯ الخيارات التالية</string> |
| 89 | <string name="import_save_warning">استيراد ØÙظ البيانات</string> | ||
| 90 | <string name="import_save_warning_description">سيؤدي هذا إلى استبدال جميع بيانات الØÙظ الموجودة بالمل٠المقدم. هل أنت متأكد أنك تريد الاستمرار؟</string> | ||
| 85 | <string name="import_export_saves_description">استيراد أو تصدير Ù…Ù„ÙØ§Øª الØÙظ</string> | 91 | <string name="import_export_saves_description">استيراد أو تصدير Ù…Ù„ÙØ§Øª الØÙظ</string> |
| 92 | <string name="save_files_importing">جاري استيراد Ù…Ù„ÙØ§Øª الØÙظ</string> | ||
| 93 | <string name="save_files_exporting">جاري تصدير Ù…Ù„ÙØ§Øª الØÙظ</string> | ||
| 86 | <string name="save_file_imported_success">تم الاستيراد بنجاØ</string> | 94 | <string name="save_file_imported_success">تم الاستيراد بنجاØ</string> |
| 87 | <string name="save_file_invalid_zip_structure">بنية مجلد الØÙظ غير ØµØ§Ù„ØØ©</string> | 95 | <string name="save_file_invalid_zip_structure">بنية مجلد الØÙظ غير ØµØ§Ù„ØØ©</string> |
| 88 | <string name="save_file_invalid_zip_structure_description">يجب أن يكون اسم المجلد Ø§Ù„ÙØ±Ø¹ÙŠ Ø§Ù„Ø£ÙˆÙ„ هو معر٠عنوان اللعبة.</string> | 96 | <string name="save_file_invalid_zip_structure_description">يجب أن يكون اسم المجلد Ø§Ù„ÙØ±Ø¹ÙŠ Ø§Ù„Ø£ÙˆÙ„ هو معر٠عنوان اللعبة.</string> |
| 89 | <string name="import_saves">استيراد</string> | 97 | <string name="import_saves">استيراد</string> |
| 90 | <string name="export_saves">تصدير</string> | 98 | <string name="export_saves">تصدير</string> |
| 91 | <string name="install_firmware">تثبيت البرامج الثابتة</string> | 99 | <string name="install_firmware">تثبيت Ùيرموير</string> |
| 92 | <string name="firmware_installing">تثبيت البرامج الثابتة</string> | 100 | <string name="install_firmware_description">يجب أن يكون Ùيرموير ÙÙŠ أرشي٠مضغوط وهو ضروري لتشغيل بعض الألعاب</string> |
| 93 | <string name="firmware_installed_success">تم تثبيت البرامج الثابتة بنجاØ</string> | 101 | <string name="firmware_installing">تثبيت Ùيرموير</string> |
| 94 | <string name="firmware_installed_failure">ÙØ´Ù„ تثبيت البرامج الثابتة</string> | 102 | <string name="firmware_installed_success">تم تثبيت Ùيرموير بنجاØ</string> |
| 103 | <string name="firmware_installed_failure">ÙØ´Ù„ تثبيت Ùيرموير</string> | ||
| 95 | <string name="share_log">مشاركة سجلات التصØÙŠØ</string> | 104 | <string name="share_log">مشاركة سجلات التصØÙŠØ</string> |
| 96 | <string name="share_log_description">مشاركة مل٠سجل يوزو لتصØÙŠØ المشكلات</string> | 105 | <string name="share_log_description">مشاركة مل٠سجل يوزو لتصØÙŠØ المشكلات</string> |
| 97 | <string name="share_log_missing">لم يتم العثور على مل٠السجل</string> | 106 | <string name="share_log_missing">لم يتم العثور على مل٠السجل</string> |
| 98 | <string name="install_game_content">تثبيت Ù…ØØªÙˆÙ‰ اللعبة</string> | 107 | <string name="install_game_content">تثبيت Ù…ØØªÙˆÙ‰ اللعبة</string> |
| 99 | <string name="install_game_content_description">DLC قم بتثبيت ØªØØ¯ÙŠØ«Ø§Øª اللعبة أو</string> | 108 | <string name="install_game_content_description">DLC قم بتثبيت ØªØØ¯ÙŠØ«Ø§Øª اللعبة أو</string> |
| 100 | <string name="installing_game_content">جار٠تثبيت Ø§Ù„Ù…ØØªÙˆÙ‰</string> | 109 | <string name="installing_game_content">جاري تثبيت Ø§Ù„Ù…ØØªÙˆÙ‰</string> |
| 101 | <string name="install_game_content_failure_base">لا ÙŠÙØ³Ù…Ø Ø¨ØªØ«Ø¨ÙŠØª الألعاب الأساسية لتجنب التعارضات Ø§Ù„Ù…ØØªÙ…لة.</string> | 110 | <string name="install_game_content_failure_base">لا ÙŠÙØ³Ù…Ø Ø¨ØªØ«Ø¨ÙŠØª الألعاب الأساسية لتجنب التعارضات Ø§Ù„Ù…ØØªÙ…لة.</string> |
| 102 | <string name="install_game_content_success_install">%1$d تم التثبيت بنجاØ</string> | 111 | <string name="install_game_content_success_install">%1$d تم التثبيت بنجاØ</string> |
| 103 | <string name="install_game_content_success_overwrite">%1$d تمت الكتابة Ùوقه بنجاØ</string> | 112 | <string name="install_game_content_success_overwrite">%1$d تمت الكتابة Ùوقه بنجاØ</string> |
| @@ -105,19 +114,39 @@ | |||
| 105 | <string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string> | 114 | <string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string> |
| 106 | <string name="custom_driver_not_supported_description">تØÙ…يل برنامج التشغيل المخصص غير معتمد ØØ§Ù„يًا لهذا الجهاز.\nØØ¯Ø¯ هذا الخيار مرة أخرى ÙÙŠ المستقبل Ù„Ù…Ø¹Ø±ÙØ© ما إذا تمت Ø¥Ø¶Ø§ÙØ© الدعم!</string> | 115 | <string name="custom_driver_not_supported_description">تØÙ…يل برنامج التشغيل المخصص غير معتمد ØØ§Ù„يًا لهذا الجهاز.\nØØ¯Ø¯ هذا الخيار مرة أخرى ÙÙŠ المستقبل Ù„Ù…Ø¹Ø±ÙØ© ما إذا تمت Ø¥Ø¶Ø§ÙØ© الدعم!</string> |
| 107 | <string name="manage_yuzu_data">إدارة بيانات يوزو</string> | 116 | <string name="manage_yuzu_data">إدارة بيانات يوزو</string> |
| 108 | <string name="manage_yuzu_data_description">استيراد/تصدير البرامج الثابتة ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ وبيانات المستخدم والمزيد!</string> | 117 | <string name="manage_yuzu_data_description">استيراد/تصدير Ùيرموير ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ وبيانات المستخدم والمزيد</string> |
| 109 | <string name="share_save_file">مشاركة مل٠الØÙظ</string> | 118 | <string name="share_save_file">مشاركة مل٠الØÙظ</string> |
| 110 | <string name="export_save_failed">ÙØ´Ù„ تصدير الØÙظ</string> | 119 | <string name="export_save_failed">ÙØ´Ù„ تصدير الØÙظ</string> |
| 111 | 120 | <string name="game_folders">مجلدات اللعبة</string> | |
| 121 | <string name="deep_scan">ÙØØµ عميق</string> | ||
| 122 | <string name="add_game_folder">Ø¥Ø¶Ø§ÙØ© مجلد اللعبة</string> | ||
| 123 | <string name="folder_already_added">تمت Ø¥Ø¶Ø§ÙØ© هذا المجلد Ø¨Ø§Ù„ÙØ¹Ù„</string> | ||
| 124 | <string name="game_folder_properties">خصائص مجلد اللعبة</string> | ||
| 125 | <string name="no_save_data_found">لم يتم العثور على بيانات الØÙظ</string> | ||
| 126 | |||
| 127 | <!-- Applet launcher strings --> | ||
| 128 | <string name="applets">قائمة التطبيقات المصغرة</string> | ||
| 129 | <string name="applets_description">قم بتشغيل تطبيقات النظام باستخدام Ùيرموير المثبت</string> | ||
| 130 | <string name="applets_error_firmware">Ùيرموير غير مثبت</string> | ||
| 131 | <string name="applets_error_applet">التطبيق المصغر غير Ù…ØªÙˆÙØ±</string> | ||
| 132 | <string name="album_applet">الألبوم</string> | ||
| 133 | <string name="album_applet_description">شاهد الصور المخزنة ÙÙŠ مجلد لقطات شاشة المستخدم باستخدام عارض صور النظام</string> | ||
| 134 | <string name="mii_edit_applet">ØªØØ±ÙŠØ± Mii</string> | ||
| 135 | <string name="mii_edit_applet_description">باستخدام Ù…ØØ±Ø± النظام Miis عرض ÙˆØªØØ±ÙŠØ±</string> | ||
| 136 | <string name="cabinet_applet_description">ØªØØ±ÙŠØ± ÙˆØØ°Ù البيانات المخزنة على أميبو</string> | ||
| 137 | <string name="cabinet_nickname_and_owner">إعدادات الاسم المستعار والمالك</string> | ||
| 138 | <string name="cabinet_game_data_eraser">Ù…Ù…ØØ§Ø© بيانات اللعبة</string> | ||
| 112 | <string name="copied_to_clipboard">نسخ إلى Ø§Ù„ØØ§Ùظة</string> | 139 | <string name="copied_to_clipboard">نسخ إلى Ø§Ù„ØØ§Ùظة</string> |
| 113 | <string name="about_app_description">Ù…ØØ§ÙƒÙŠ Ø³ÙˆÙŠØªØ´ Ù…ÙØªÙˆØ المصدر</string> | 140 | <string name="about_app_description">Ù…ØØ§ÙƒÙŠ Ø³ÙˆÙŠØªØ´ Ù…ÙØªÙˆØ المصدر</string> |
| 114 | <string name="contributors">المساهمين</string> | 141 | <string name="contributors">المساهمين</string> |
| 142 | <string name="contributors_description">مصنوع من ÙØ±ÙŠÙ‚ يوزو</string> | ||
| 115 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | 143 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> |
| 116 | <string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string> | 144 | <string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string> |
| 117 | <string name="build">البناء</string> | 145 | <string name="build">البناء</string> |
| 118 | <string name="user_data">بيانات المستخدم</string> | 146 | <string name="user_data">بيانات المستخدم</string> |
| 119 | <string name="exporting_user_data">جار٠تصدير بيانات المستخدم</string> | 147 | <string name="user_data_description">استيراد/تصدير جميع بيانات التطبيق. عند استيراد بيانات المستخدم، سيتم ØØ°Ù جميع بيانات المستخدم Ø§Ù„ØØ§Ù„ية!</string> |
| 120 | <string name="importing_user_data">جار٠استيراد بيانات المستخدم</string> | 148 | <string name="exporting_user_data">جاري تصدير بيانات المستخدم</string> |
| 149 | <string name="importing_user_data">جاري استيراد بيانات المستخدم</string> | ||
| 121 | <string name="import_user_data">استيراد بيانات المستخدم</string> | 150 | <string name="import_user_data">استيراد بيانات المستخدم</string> |
| 122 | <string name="invalid_yuzu_backup">نسخة Ø§ØØªÙŠØ§Ø·ÙŠØ© يوزو غير ØµØ§Ù„ØØ©</string> | 151 | <string name="invalid_yuzu_backup">نسخة Ø§ØØªÙŠØ§Ø·ÙŠØ© يوزو غير ØµØ§Ù„ØØ©</string> |
| 123 | <string name="user_data_export_success">تم تصدير بيانات المستخدم بنجاØ</string> | 152 | <string name="user_data_export_success">تم تصدير بيانات المستخدم بنجاØ</string> |
| @@ -153,7 +182,7 @@ | |||
| 153 | <string name="use_docked_mode">وضع الإرساء</string> | 182 | <string name="use_docked_mode">وضع الإرساء</string> |
| 154 | <string name="use_docked_mode_description">زيادة الدقة، ÙˆØ§Ù†Ø®ÙØ§Ø¶ الأداء. يتم استخدام الوضع المØÙ…ول عند تعطيله، مما يؤدي إلى Ø®ÙØ¶ الدقة وزيادة الأداء.</string> | 183 | <string name="use_docked_mode_description">زيادة الدقة، ÙˆØ§Ù†Ø®ÙØ§Ø¶ الأداء. يتم استخدام الوضع المØÙ…ول عند تعطيله، مما يؤدي إلى Ø®ÙØ¶ الدقة وزيادة الأداء.</string> |
| 155 | <string name="emulated_region">المنطقة التي تمت Ù…ØØ§ÙƒØ§ØªÙ‡Ø§</string> | 184 | <string name="emulated_region">المنطقة التي تمت Ù…ØØ§ÙƒØ§ØªÙ‡Ø§</string> |
| 156 | <string name="emulated_language">لغة Ø§Ù„Ù…ØØ§ÙƒØ§Ù‡</string> | 185 | <string name="emulated_language">لغة Ø§Ù„Ù…ØØ§ÙƒØ§Ø©</string> |
| 157 | <string name="select_rtc_date">ØØ¯Ø¯ التاريخ Ùˆ الساعة ÙÙŠ الوقت الØÙ‚يقي</string> | 186 | <string name="select_rtc_date">ØØ¯Ø¯ التاريخ Ùˆ الساعة ÙÙŠ الوقت الØÙ‚يقي</string> |
| 158 | <string name="select_rtc_time">ØØ¯Ø¯ وقت الساعة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ</string> | 187 | <string name="select_rtc_time">ØØ¯Ø¯ وقت الساعة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ</string> |
| 159 | <string name="use_custom_rtc">ساعة مخصصة ÙÙŠ الوقت الØÙ‚يقي</string> | 188 | <string name="use_custom_rtc">ساعة مخصصة ÙÙŠ الوقت الØÙ‚يقي</string> |
| @@ -164,7 +193,7 @@ | |||
| 164 | <string name="renderer_accuracy">مستوى الدقة</string> | 193 | <string name="renderer_accuracy">مستوى الدقة</string> |
| 165 | <string name="renderer_resolution">(Handheld/Docked) الدقة</string> | 194 | <string name="renderer_resolution">(Handheld/Docked) الدقة</string> |
| 166 | <string name="renderer_vsync">VSync وضع</string> | 195 | <string name="renderer_vsync">VSync وضع</string> |
| 167 | <string name="renderer_screen_layout">الاتجاه</string> | 196 | <string name="renderer_screen_layout">اتجاه العرض</string> |
| 168 | <string name="renderer_aspect_ratio">تناسب الابعاد</string> | 197 | <string name="renderer_aspect_ratio">تناسب الابعاد</string> |
| 169 | <string name="renderer_anti_aliasing">طريقة Ù…ÙƒØ§ÙØØ© التعرج</string> | 198 | <string name="renderer_anti_aliasing">طريقة Ù…ÙƒØ§ÙØØ© التعرج</string> |
| 170 | <string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string> | 199 | <string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string> |
| @@ -172,31 +201,32 @@ | |||
| 172 | <string name="renderer_reactive_flushing">استخدم Ø§Ù„ØªÙ†Ø¸ÙŠÙ Ø§Ù„ØªÙØ§Ø¹Ù„ÙŠ</string> | 201 | <string name="renderer_reactive_flushing">استخدم Ø§Ù„ØªÙ†Ø¸ÙŠÙ Ø§Ù„ØªÙØ§Ø¹Ù„ÙŠ</string> |
| 173 | <string name="renderer_reactive_flushing_description">ØªØØ³ÙŠÙ† دقة العرض ÙÙŠ بعض الألعاب على ØØ³Ø§Ø¨ الأداء</string> | 202 | <string name="renderer_reactive_flushing_description">ØªØØ³ÙŠÙ† دقة العرض ÙÙŠ بعض الألعاب على ØØ³Ø§Ø¨ الأداء</string> |
| 174 | <string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتØÙ…يل التظليلات التي تم إنشاؤها Ù…ØÙ„يًا.</string> | 203 | <string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتØÙ…يل التظليلات التي تم إنشاؤها Ù…ØÙ„يًا.</string> |
| 175 | |||
| 176 | <!-- Debug settings strings --> | 204 | <!-- Debug settings strings --> |
| 177 | <string name="cpu">ÙˆØØ¯Ø© المعالج المركزية</string> | 205 | <string name="cpu">ÙˆØØ¯Ø© المعالج المركزية</string> |
| 178 | <string name="cpu_debug_mode">تصØÙŠØ أخطاء ÙˆØØ¯Ø© المعالجة المركزية</string> | 206 | <string name="cpu_debug_mode">تصØÙŠØ أخطاء ÙˆØØ¯Ø© المعالجة المركزية</string> |
| 179 | <string name="cpu_debug_mode_description">يضع ÙˆØØ¯Ø© المعالجة المركزية ÙÙŠ وضع التصØÙŠØ البطيء.</string> | 207 | <string name="cpu_debug_mode_description">يضع ÙˆØØ¯Ø© المعالجة المركزية ÙÙŠ وضع التصØÙŠØ البطيء.</string> |
| 180 | <string name="gpu">GPU</string> | 208 | <string name="gpu">ÙˆØØ¯Ø© معالجة الرسومات</string> |
| 181 | <string name="renderer_api">API</string> | 209 | <string name="renderer_api">واجهة برمجة التطبيقات</string> |
| 182 | <string name="renderer_debug">تصØÙŠØ الأخطاء الرسومية</string> | 210 | <string name="renderer_debug">تصØÙŠØ الأخطاء الرسومية</string> |
| 183 | <string name="renderer_debug_description">يضبط واجهة برمجة تطبيقات الرسومات على وضع تصØÙŠØ الأخطاء البطيء.</string> | 211 | <string name="renderer_debug_description">يضبط واجهة برمجة تطبيقات الرسومات على وضع تصØÙŠØ الأخطاء البطيء.</string> |
| 184 | <string name="fastmem">Fastmem</string> | 212 | <string name="fastmem">Fastmem</string> |
| 185 | 213 | ||
| 186 | <!-- Audio settings strings --> | 214 | <!-- Audio settings strings --> |
| 187 | <string name="audio_output_engine">Ù…ØØ±Ùƒ الإخراج</string> | 215 | <string name="audio_output_engine">Ù…ØØ±Ùƒ الإخراج</string> |
| 188 | <string name="audio_volume">ØØ¬Ù…</string> | 216 | <string name="audio_volume">مستوى الصوت</string> |
| 189 | <string name="audio_volume_description">ÙŠØØ¯Ø¯ ØØ¬Ù… إخراج الصوت</string> | 217 | <string name="audio_volume_description">ÙŠØØ¯Ø¯ مستوى إخراج الصوت</string> |
| 190 | 218 | ||
| 191 | <!-- Miscellaneous --> | 219 | <!-- Miscellaneous --> |
| 192 | <string name="slider_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 220 | <string name="slider_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> |
| 193 | <string name="ini_saved">الإعدادات المØÙوظة</string> | 221 | <string name="ini_saved">الإعدادات المØÙوظة</string> |
| 194 | <string name="gameid_saved">الإعدادات المØÙوظة لـ %1$s</string> | 222 | <string name="gameid_saved">الإعدادات المØÙوظة لـ %1$s</string> |
| 223 | <string name="error_saving">خطأ ÙÙŠ ØÙظ %1$s.ini: %2$s</string> | ||
| 195 | <string name="unimplemented_menu">القائمة غير Ø§Ù„Ù…Ù†ÙØ°Ø©</string> | 224 | <string name="unimplemented_menu">القائمة غير Ø§Ù„Ù…Ù†ÙØ°Ø©</string> |
| 196 | <string name="loading">جاري تØÙ…يل</string> | 225 | <string name="loading">جاري التØÙ…يل</string> |
| 197 | <string name="shutting_down">إيقا٠تشغيل</string> | 226 | <string name="shutting_down">إيقا٠التشغيل</string> |
| 198 | <string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد مرة أخرى إلى قيمته Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©ØŸ</string> | 227 | <string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد مرة أخرى إلى قيمته Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©ØŸ</string> |
| 199 | <string name="reset_to_default">إعادة تعيين إلى Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 228 | <string name="reset_to_default">إعادة التعيين إلى الوضع Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> |
| 229 | <string name="reset_to_default_description">إعادة تعيين جميع الإعدادات المتقدمة</string> | ||
| 200 | <string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string> | 230 | <string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string> |
| 201 | <string name="reset_all_settings_description">سيتم إعادة تعيين ÙƒØ§ÙØ© الإعدادات المتقدمة إلى تكوينها Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ. هذا لا يمكن التراجع عنها.</string> | 231 | <string name="reset_all_settings_description">سيتم إعادة تعيين ÙƒØ§ÙØ© الإعدادات المتقدمة إلى تكوينها Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ. هذا لا يمكن التراجع عنها.</string> |
| 202 | <string name="settings_reset">إعادة تعيين الأعدادات</string> | 232 | <string name="settings_reset">إعادة تعيين الأعدادات</string> |
| @@ -204,32 +234,77 @@ | |||
| 204 | <string name="learn_more">Ù…Ø¹Ø±ÙØ© المزيد</string> | 234 | <string name="learn_more">Ù…Ø¹Ø±ÙØ© المزيد</string> |
| 205 | <string name="auto">تلقائي</string> | 235 | <string name="auto">تلقائي</string> |
| 206 | <string name="submit">إرسال</string> | 236 | <string name="submit">إرسال</string> |
| 207 | <string name="string_null">قيمه خاليه</string> | 237 | <string name="string_null">لا شيء</string> |
| 208 | <string name="string_import">استيراد</string> | 238 | <string name="string_import">استيراد</string> |
| 209 | <string name="export">تصدير</string> | 239 | <string name="export">تصدير</string> |
| 210 | <string name="export_failed">ÙØ´Ù„ التصدير</string> | 240 | <string name="export_failed">ÙØ´Ù„ التصدير</string> |
| 211 | <string name="import_failed">ÙØ´Ù„ الاستيراد</string> | 241 | <string name="import_failed">ÙØ´Ù„ الاستيراد</string> |
| 212 | <string name="cancelling">إلغاء</string> | 242 | <string name="cancelling">إلغاء</string> |
| 213 | 243 | <string name="install">تثبيت</string> | |
| 244 | <string name="delete">ØØ°Ù</string> | ||
| 245 | <string name="edit">ØØ±Ø±</string> | ||
| 246 | <string name="export_success">تم التصدير بنجاØ</string> | ||
| 247 | <string name="start">Start</string> | ||
| 248 | <string name="clear">مسØ</string> | ||
| 249 | <string name="global">عالمي</string> | ||
| 250 | <string name="custom">مخصص</string> | ||
| 251 | <string name="notice">إشعار</string> | ||
| 252 | <string name="import_complete">اكتمل الاستيراد</string> | ||
| 214 | <!-- GPU driver installation --> | 253 | <!-- GPU driver installation --> |
| 215 | <string name="select_gpu_driver">GPU ØØ¯Ø¯ برنامج تشغيل</string> | 254 | <string name="select_gpu_driver">GPU ØØ¯Ø¯ برنامج تشغيل</string> |
| 216 | <string name="select_gpu_driver_title">Ø§Ù„ØØ§Ù„ÙŠ الخاص بك؟ GPU هل ترغب ÙÙŠ استبدال برنامج تشغيل</string> | 255 | <string name="select_gpu_driver_title">Ø§Ù„ØØ§Ù„ÙŠ الخاص بك؟ GPU هل ترغب ÙÙŠ استبدال برنامج تشغيل</string> |
| 217 | <string name="select_gpu_driver_install">تثبيت</string> | 256 | <string name="select_gpu_driver_install">تثبيت</string> |
| 218 | <string name="select_gpu_driver_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 257 | <string name="select_gpu_driver_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> |
| 219 | <string name="select_gpu_driver_use_default">يستخدم تعري٠معالج الرسوميات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 258 | <string name="select_gpu_driver_use_default">يستخدم تعري٠معالج الرسومات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> |
| 220 | <string name="select_gpu_driver_error">تم ØªØØ¯ÙŠØ¯ برنامج تشغيل غير ØµØ§Ù„Ø ØŒ باستخدام النظام Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 259 | <string name="select_gpu_driver_error">تم ØªØØ¯ÙŠØ¯ برنامج تشغيل غير صالØ</string> |
| 221 | <string name="system_gpu_driver">تعري٠معالج الرسوميات الخاص بالنظام</string> | 260 | <string name="driver_already_installed">برنامج التشغيل مثبت Ø¨Ø§Ù„ÙØ¹Ù„</string> |
| 222 | <string name="installing_driver">جار٠تثبيت برنامج التشغيل…</string> | 261 | <string name="system_gpu_driver">تعري٠معالج الرسومات الخاص بالنظام</string> |
| 262 | <string name="installing_driver">جاري تثبيت برنامج التشغيل…</string> | ||
| 223 | 263 | ||
| 224 | <!-- Preferences Screen --> | 264 | <!-- Preferences Screen --> |
| 225 | <string name="preferences_settings">إعدادات</string> | 265 | <string name="preferences_settings">إعدادات</string> |
| 226 | <string name="preferences_general">عام</string> | 266 | <string name="preferences_general">عام</string> |
| 227 | <string name="preferences_system">النظام</string> | 267 | <string name="preferences_system">النظام</string> |
| 228 | <string name="preferences_graphics">الرسوميات</string> | 268 | <string name="preferences_system_description">وضع الإرساء ،المنطقة ،اللغة</string> |
| 269 | <string name="preferences_graphics">الرسومات</string> | ||
| 270 | <string name="preferences_graphics_description">مستوى الدقة ،الدقة ،ذاكرة التخزين المؤقت للتظليل</string> | ||
| 229 | <string name="preferences_audio">الصوت</string> | 271 | <string name="preferences_audio">الصوت</string> |
| 272 | <string name="preferences_audio_description">Ù…ØØ±Ùƒ الإخراج ØŒ ØØ¬Ù… الصوت</string> | ||
| 230 | <string name="preferences_theme">السمة واللون</string> | 273 | <string name="preferences_theme">السمة واللون</string> |
| 231 | <string name="preferences_debug">تصØÙŠØ الأخطاء</string> | 274 | <string name="preferences_debug">تصØÙŠØ الأخطاء</string> |
| 232 | 275 | <!-- Game properties --> | |
| 276 | <string name="info">معلومات</string> | ||
| 277 | <string name="info_description">معر٠البرنامج، المطور، الإصدار</string> | ||
| 278 | <string name="per_game_settings">إعدادات كل لعبة</string> | ||
| 279 | <string name="per_game_settings_description">ØªØØ±ÙŠØ± الإعدادات الخاصة بهذه اللعبة</string> | ||
| 280 | <string name="launch_options">تشغيل الإعدادات</string> | ||
| 281 | <string name="path">المسار</string> | ||
| 282 | <string name="program_id">معر٠البرنامج</string> | ||
| 283 | <string name="developer">المطور</string> | ||
| 284 | <string name="version">إصدار</string> | ||
| 285 | <string name="copy_details">نسخ Ø§Ù„ØªÙØ§ØµÙŠÙ„</string> | ||
| 286 | <string name="add_ons">Ø§Ù„Ø¥Ø¶Ø§ÙØ§Øª</string> | ||
| 287 | <string name="add_ons_description">DLCالتعديلات ÙˆØ§Ù„ØªØØ¯ÙŠØ«Ø§Øª Ùˆ</string> | ||
| 288 | <string name="clear_shader_cache">Ù…Ø³Ø Ø°Ø§ÙƒØ±Ø© التخزين المؤقت للتظليل</string> | ||
| 289 | <string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string> | ||
| 290 | <string name="clear_shader_cache_warning_description">سو٠تواجه المزيد من التأتأة مع تجديد ذاكرة التخزين المؤقت للتظليل</string> | ||
| 291 | <string name="cleared_shaders_successfully">تم Ù…Ø³Ø Ø§Ù„ØªØ¸Ù„ÙŠÙ„ بنجاØ</string> | ||
| 292 | <string name="addons_game">Ø¥Ø¶Ø§ÙØ§Øª: %1$s</string> | ||
| 293 | <string name="save_data">ØÙظ البيانات</string> | ||
| 294 | <string name="save_data_description">إدارة ØÙظ البيانات الخاصة بهذه اللعبة</string> | ||
| 295 | <string name="delete_save_data">ØØ°Ù ØÙظ البيانات</string> | ||
| 296 | <string name="delete_save_data_description">يزيل ÙƒØ§ÙØ© البيانات المØÙوظة الخاصة بهذه اللعبة</string> | ||
| 297 | <string name="delete_save_data_warning_description">يؤدي هذا إلى إزالة ÙƒØ§ÙØ© البيانات المØÙوظة لهذه اللعبة بشكل لا يمكن استرداده. هل أنت متأكد أنك تريد الاستمرار؟</string> | ||
| 298 | <string name="save_data_deleted_successfully">ØÙظ البيانات تم ØØ°Ùها بنجاØ</string> | ||
| 299 | <string name="select_content_type">نوع Ø§Ù„Ù…ØØªÙˆÙ‰</string> | ||
| 300 | <string name="updates_and_dlc">DLC Ø§Ù„ØªØØ¯ÙŠØ«Ø§Øª ÙˆØ§Ù„Ù…ØØªÙˆÙ‰ القابل للتنزيل </string> | ||
| 301 | <string name="mods_and_cheats">تعديل وغش</string> | ||
| 302 | <string name="addon_notice">إشعار إضاÙÙŠ مهم</string> | ||
| 303 | <string name="invalid_directory">مجلد غير صالØ</string> | ||
| 304 | <string name="addon_installed_successfully">تم تثبيت الملØÙ‚ بنجاØ</string> | ||
| 305 | <string name="verifying_content">جاري التØÙ‚Ù‚ من Ø§Ù„Ù…ØØªÙˆÙ‰</string> | ||
| 306 | <string name="content_install_notice">إشعار تثبيت Ø§Ù„Ù…ØØªÙˆÙ‰</string> | ||
| 307 | <string name="content_install_notice_description">Ø§Ù„Ù…ØØªÙˆÙ‰ الذي ØØ¯Ø¯ØªÙ‡ لا يتطابق مع هذه اللعبة.هل تريد التثبيت على أية ØØ§Ù„ØŸ</string> | ||
| 233 | <!-- ROM loading errors --> | 308 | <!-- ROM loading errors --> |
| 234 | <string name="loader_error_encrypted">الخاص بك ROM تم تشÙير</string> | 309 | <string name="loader_error_encrypted">الخاص بك ROM تم تشÙير</string> |
| 235 | <string name="loader_error_video_core">ØØ¯Ø« خطأ أثناء تهيئة مركز الÙيديو</string> | 310 | <string name="loader_error_video_core">ØØ¯Ø« خطأ أثناء تهيئة مركز الÙيديو</string> |
| @@ -238,24 +313,25 @@ | |||
| 238 | 313 | ||
| 239 | <!-- Emulation Menu --> | 314 | <!-- Emulation Menu --> |
| 240 | <string name="emulation_exit">الخروج من Ø§Ù„Ù…ØØ§ÙƒØ§Ø©</string> | 315 | <string name="emulation_exit">الخروج من Ø§Ù„Ù…ØØ§ÙƒØ§Ø©</string> |
| 241 | <string name="emulation_done">منجز</string> | 316 | <string name="emulation_done">إنهاء</string> |
| 242 | <string name="emulation_fps_counter">عداد إطار/ثانية</string> | 317 | <string name="emulation_fps_counter">عداد إطار/ثانية</string> |
| 243 | <string name="emulation_toggle_controls">تبديل عناصر التØÙƒÙ…</string> | 318 | <string name="emulation_toggle_controls">عناصر التØÙƒÙ…</string> |
| 244 | <string name="emulation_rel_stick_center">مركز العصا النسبي</string> | 319 | <string name="emulation_rel_stick_center">مركز العصا النسبي</string> |
| 245 | <string name="emulation_dpad_slide">مزلاق أزرار الاتجاهات</string> | 320 | <string name="emulation_dpad_slide">مزلاق الأسهم</string> |
| 246 | <string name="emulation_haptics">الاهتزازات الديناميكية</string> | 321 | <string name="emulation_haptics">الاهتزازات الديناميكية</string> |
| 247 | <string name="emulation_show_overlay">عرض التراكب</string> | 322 | <string name="emulation_show_overlay">عرض التراكب</string> |
| 248 | <string name="emulation_toggle_all">تبديل الكل</string> | 323 | <string name="emulation_toggle_all">الكل</string> |
| 249 | <string name="emulation_control_adjust">ضبط التراكب</string> | 324 | <string name="emulation_control_adjust">ضبط التراكب</string> |
| 250 | <string name="emulation_control_scale">ØØ¬Ù…</string> | 325 | <string name="emulation_control_scale">Ø§Ù„ØØ¬Ù…</string> |
| 251 | <string name="emulation_control_opacity">العتامه</string> | 326 | <string name="emulation_control_opacity">Ø§Ù„Ø´ÙØ§Ùية</string> |
| 252 | <string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string> | 327 | <string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string> |
| 253 | <string name="emulation_touch_overlay_edit">ØªØØ±ÙŠØ± التراكب</string> | 328 | <string name="emulation_touch_overlay_edit">ØªØØ±ÙŠØ± التراكب</string> |
| 254 | <string name="emulation_pause">Ø¥ÙŠÙ‚Ø§Ù Ø§Ù„Ù…ØØ§ÙƒØ§Ø© مؤقتًا</string> | 329 | <string name="emulation_pause">Ø¥ÙŠÙ‚Ø§Ù Ø§Ù„Ù…ØØ§ÙƒØ§Ø© مؤقتًا</string> |
| 255 | <string name="emulation_unpause">إلغاء الإيقا٠المؤقت للمضاهاة</string> | 330 | <string name="emulation_unpause">إلغاء الإيقا٠المؤقت Ù„Ù„Ù…ØØ§ÙƒØ§Ø©</string> |
| 256 | <string name="emulation_input_overlay">خيارات التراكب</string> | 331 | <string name="emulation_input_overlay">خيارات التراكب</string> |
| 332 | <string name="touchscreen">شاشة اللمس</string> | ||
| 257 | 333 | ||
| 258 | <string name="load_settings">جار٠تØÙ…يل الإعدادات</string> | 334 | <string name="load_settings">جاري تØÙ…يل الإعدادات</string> |
| 259 | 335 | ||
| 260 | <!-- Software keyboard --> | 336 | <!-- Software keyboard --> |
| 261 | <string name="software_keyboard">Ù„ÙˆØØ© Ø§Ù„Ù…ÙØ§ØªÙŠØ البرمجية</string> | 337 | <string name="software_keyboard">Ù„ÙˆØØ© Ø§Ù„Ù…ÙØ§ØªÙŠØ البرمجية</string> |
| @@ -282,6 +358,7 @@ | |||
| 282 | 358 | ||
| 283 | <!-- Memory Sizes --> | 359 | <!-- Memory Sizes --> |
| 284 | <string name="memory_byte">Byte</string> | 360 | <string name="memory_byte">Byte</string> |
| 361 | <string name="memory_byte_shorthand">B</string> | ||
| 285 | <string name="memory_kilobyte">KB</string> | 362 | <string name="memory_kilobyte">KB</string> |
| 286 | <string name="memory_megabyte">MB</string> | 363 | <string name="memory_megabyte">MB</string> |
| 287 | <string name="memory_gigabyte">GB</string> | 364 | <string name="memory_gigabyte">GB</string> |
| @@ -326,10 +403,9 @@ | |||
| 326 | <string name="anti_aliasing_smaa">SMAA</string> | 403 | <string name="anti_aliasing_smaa">SMAA</string> |
| 327 | 404 | ||
| 328 | <!-- Screen Layouts --> | 405 | <!-- Screen Layouts --> |
| 329 | <string name="screen_layout_landscape">اÙقي</string> | ||
| 330 | <string name="screen_layout_portrait">عمودي</string> | ||
| 331 | <string name="screen_layout_auto">تلقائي</string> | 406 | <string name="screen_layout_auto">تلقائي</string> |
| 332 | 407 | <string name="screen_layout_landscape">Ø£Ùقي</string> | |
| 408 | <string name="screen_layout_portrait">عمودي</string> | ||
| 333 | <!-- Aspect Ratios --> | 409 | <!-- Aspect Ratios --> |
| 334 | <string name="ratio_default">(16:9) Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> | 410 | <string name="ratio_default">(16:9) Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> |
| 335 | <string name="ratio_force_four_three">4:3 ÙØ±Ø¶</string> | 411 | <string name="ratio_force_four_three">4:3 ÙØ±Ø¶</string> |
| @@ -337,16 +413,20 @@ | |||
| 337 | <string name="ratio_force_sixteen_ten">16:10 ÙØ±Ø¶</string> | 413 | <string name="ratio_force_sixteen_ten">16:10 ÙØ±Ø¶</string> |
| 338 | <string name="ratio_stretch">تمتد إلى Ø§Ù„Ù†Ø§ÙØ°Ø©</string> | 414 | <string name="ratio_stretch">تمتد إلى Ø§Ù„Ù†Ø§ÙØ°Ø©</string> |
| 339 | 415 | ||
| 416 | <!-- CPU Backend --> | ||
| 417 | <string name="cpu_backend_dynarmic">Dynarmic (بطيء)</string> | ||
| 418 | <string name="cpu_backend_nce">تنÙيذ التعليمات البرمجية الأصلية (NCE)</string> | ||
| 419 | |||
| 340 | <!-- CPU Accuracy --> | 420 | <!-- CPU Accuracy --> |
| 341 | <string name="cpu_accuracy_accurate">دقه</string> | 421 | <string name="cpu_accuracy_accurate">دقه</string> |
| 342 | <string name="cpu_accuracy_unsafe">غير آمن</string> | 422 | <string name="cpu_accuracy_unsafe">غير آمن</string> |
| 343 | <string name="cpu_accuracy_paranoid">Paranoid (Slow)</string> | 423 | <string name="cpu_accuracy_paranoid">Paranoid (بطيء)</string> |
| 344 | 424 | ||
| 345 | <!-- Gamepad Buttons --> | 425 | <!-- Gamepad Buttons --> |
| 346 | <string name="gamepad_d_pad">أزرار الاتجاهات</string> | 426 | <string name="gamepad_d_pad">الأسهم</string> |
| 347 | <string name="gamepad_left_stick">العصا اليسرى</string> | 427 | <string name="gamepad_left_stick">العصا اليسرى</string> |
| 348 | <string name="gamepad_right_stick">العصا اليمنى</string> | 428 | <string name="gamepad_right_stick">العصا اليمنى</string> |
| 349 | <string name="gamepad_home">شاشة الإستقبال</string> | 429 | <string name="gamepad_home">شاشة الرئيسية</string> |
| 350 | <string name="gamepad_screenshot">لقطة شاشة</string> | 430 | <string name="gamepad_screenshot">لقطة شاشة</string> |
| 351 | 431 | ||
| 352 | <!-- Disk shader cache --> | 432 | <!-- Disk shader cache --> |
| @@ -362,11 +442,16 @@ | |||
| 362 | <string name="change_theme_mode">تغيير وضع السمة</string> | 442 | <string name="change_theme_mode">تغيير وضع السمة</string> |
| 363 | <string name="theme_mode_follow_system">اتبع النظام</string> | 443 | <string name="theme_mode_follow_system">اتبع النظام</string> |
| 364 | <string name="theme_mode_light">ÙØ§ØªØ</string> | 444 | <string name="theme_mode_light">ÙØ§ØªØ</string> |
| 365 | <string name="theme_mode_dark">غامق</string> | 445 | <string name="theme_mode_dark">داكن</string> |
| 366 | 446 | ||
| 367 | <!-- Audio output engines --> | ||
| 368 | <string name="cubeb">cubeb</string> | 447 | <string name="cubeb">cubeb</string> |
| 369 | 448 | ||
| 449 | <!-- Anisotropic filtering options --> | ||
| 450 | <string name="multiplier_two">2x</string> | ||
| 451 | <string name="multiplier_four">4x</string> | ||
| 452 | <string name="multiplier_eight">8x</string> | ||
| 453 | <string name="multiplier_sixteen">16x</string> | ||
| 454 | |||
| 370 | <!-- Black backgrounds theme --> | 455 | <!-- Black backgrounds theme --> |
| 371 | <string name="use_black_backgrounds">خلÙيات سوداء</string> | 456 | <string name="use_black_backgrounds">خلÙيات سوداء</string> |
| 372 | <string name="use_black_backgrounds_description">عند استخدام المظهر الداكن، قم بتطبيق خلÙيات سوداء.</string> | 457 | <string name="use_black_backgrounds_description">عند استخدام المظهر الداكن، قم بتطبيق خلÙيات سوداء.</string> |
diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml index d2e5fee19..7e1eb2b8d 100644 --- a/src/android/app/src/main/res/values-ckb/strings.xml +++ b/src/android/app/src/main/res/values-ckb/strings.xml | |||
| @@ -157,7 +157,6 @@ | |||
| 157 | <string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string> | 157 | <string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string> |
| 158 | <string name="use_disk_shader_cache">بیرگەخێرای سێبەری دیسک</string> | 158 | <string name="use_disk_shader_cache">بیرگەخێرای سێبەری دیسک</string> |
| 159 | <string name="use_disk_shader_cache_description">پچڕپچڕی کەمدەکاتەوە بە هەڵگرتن و بارکردنی سێبەری دروستکراو لە ناوخۆدا.</string> | 159 | <string name="use_disk_shader_cache_description">پچڕپچڕی کەمدەکاتەوە بە هەڵگرتن و بارکردنی سێبەری دروستکراو لە ناوخۆدا.</string> |
| 160 | |||
| 161 | <!-- Debug settings strings --> | 160 | <!-- Debug settings strings --> |
| 162 | <string name="cpu">CPU</string> | 161 | <string name="cpu">CPU</string> |
| 163 | <string name="renderer_api">API گراÙیک</string> | 162 | <string name="renderer_api">API گراÙیک</string> |
| @@ -183,13 +182,15 @@ | |||
| 183 | <string name="submit">پێشکەشکردن</string> | 182 | <string name="submit">پێشکەشکردن</string> |
| 184 | <string name="string_import">هاوردەکردن</string> | 183 | <string name="string_import">هاوردەکردن</string> |
| 185 | <string name="export">هەناردەکردن</string> | 184 | <string name="export">هەناردەکردن</string> |
| 185 | <string name="install">دامەزراندن</string> | ||
| 186 | <string name="delete">سڕینەوە</string> | ||
| 187 | <string name="clear">سڕینەوە</string> | ||
| 186 | <!-- GPU driver installation --> | 188 | <!-- GPU driver installation --> |
| 187 | <string name="select_gpu_driver">هەڵبژاردنی وەگەڕخەری GPU</string> | 189 | <string name="select_gpu_driver">هەڵبژاردنی وەگەڕخەری GPU</string> |
| 188 | <string name="select_gpu_driver_title">ØÛ•ز دەکەیت وەگەڕخەری GPU ÛŒ ئێستات بگۆڕیت؟</string> | 190 | <string name="select_gpu_driver_title">ØÛ•ز دەکەیت وەگەڕخەری GPU ÛŒ ئێستات بگۆڕیت؟</string> |
| 189 | <string name="select_gpu_driver_install">دامەزراندن</string> | 191 | <string name="select_gpu_driver_install">دامەزراندن</string> |
| 190 | <string name="select_gpu_driver_default">بنەڕەت</string> | 192 | <string name="select_gpu_driver_default">بنەڕەت</string> |
| 191 | <string name="select_gpu_driver_use_default">بەکارهێنانی وەگەڕخەری GPU ی بنەڕەت</string> | 193 | <string name="select_gpu_driver_use_default">بەکارهێنانی وەگەڕخەری GPU ی بنەڕەت</string> |
| 192 | <string name="select_gpu_driver_error">وەگەڕخەری نادروست هەڵبژێردرا، بە بەکارهێنانی بنەڕەتی سیستەم!</string> | ||
| 193 | <string name="system_gpu_driver">وەگەڕخەری GPU ی سیستەم</string> | 194 | <string name="system_gpu_driver">وەگەڕخەری GPU ی سیستەم</string> |
| 194 | <string name="installing_driver">دامەزراندنی وەگەڕخەر...</string> | 195 | <string name="installing_driver">دامەزراندنی وەگەڕخەر...</string> |
| 195 | 196 | ||
| @@ -201,7 +202,8 @@ | |||
| 201 | <string name="preferences_audio">دەنگ</string> | 202 | <string name="preferences_audio">دەنگ</string> |
| 202 | <string name="preferences_theme">ڕەنگ و ڕووکار</string> | 203 | <string name="preferences_theme">ڕەنگ و ڕووکار</string> |
| 203 | <string name="preferences_debug">چاککردنەوە</string> | 204 | <string name="preferences_debug">چاککردنەوە</string> |
| 204 | 205 | <string name="path">Ú•ÛŽÚ•Û•Ùˆ</string> | |
| 206 | <string name="version">وەشان</string> | ||
| 205 | <!-- ROM loading errors --> | 207 | <!-- ROM loading errors --> |
| 206 | <string name="loader_error_encrypted">ڕۆمەکەت کۆدکراوە</string> | 208 | <string name="loader_error_encrypted">ڕۆمەکەت کۆدکراوە</string> |
| 207 | <string name="loader_error_encrypted_keys_description"><![CDATA[تکایە دڵنیابەوە لەدامەزراوی <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ÙØ§ÛŒÙ„ەکەت بۆ ئەوەی بتوانرێت یارییەکان کۆد بکرێنەوە.]]></string> | 209 | <string name="loader_error_encrypted_keys_description"><![CDATA[تکایە دڵنیابەوە لەدامەزراوی <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ÙØ§ÛŒÙ„ەکەت بۆ ئەوەی بتوانرێت یارییەکان کۆد بکرێنەوە.]]></string> |
| @@ -228,6 +230,7 @@ | |||
| 228 | <string name="emulation_pause">وەستاندنی ئیمولەیشن</string> | 230 | <string name="emulation_pause">وەستاندنی ئیمولەیشن</string> |
| 229 | <string name="emulation_unpause">لادانی وەستاندنی ئیمولەیشن</string> | 231 | <string name="emulation_unpause">لادانی وەستاندنی ئیمولەیشن</string> |
| 230 | <string name="emulation_input_overlay">هەڵبژاردەکانی داپۆشەر</string> | 232 | <string name="emulation_input_overlay">هەڵبژاردەکانی داپۆشەر</string> |
| 233 | <string name="touchscreen">رووکاری لەمسی</string> | ||
| 231 | 234 | ||
| 232 | <string name="load_settings">بارکردنی ڕێکخستنەکان...</string> | 235 | <string name="load_settings">بارکردنی ڕێکخستنەکان...</string> |
| 233 | 236 | ||
| @@ -253,6 +256,7 @@ | |||
| 253 | <string name="region_korea">کۆریا</string> | 256 | <string name="region_korea">کۆریا</string> |
| 254 | <string name="region_taiwan">تایوان</string> | 257 | <string name="region_taiwan">تایوان</string> |
| 255 | 258 | ||
| 259 | <string name="memory_byte_shorthand">B</string> | ||
| 256 | <string name="memory_gigabyte">GB</string> | 260 | <string name="memory_gigabyte">GB</string> |
| 257 | <!-- Renderer APIs --> | 261 | <!-- Renderer APIs --> |
| 258 | <string name="renderer_vulkan">ڤوڵکان</string> | 262 | <string name="renderer_vulkan">ڤوڵکان</string> |
| @@ -290,8 +294,8 @@ | |||
| 290 | <string name="anti_aliasing_fxaa">FXAA</string> | 294 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 291 | <string name="anti_aliasing_smaa">SMAA</string> | 295 | <string name="anti_aliasing_smaa">SMAA</string> |
| 292 | 296 | ||
| 297 | <!-- Screen Layouts --> | ||
| 293 | <string name="screen_layout_auto">خودکار</string> | 298 | <string name="screen_layout_auto">خودکار</string> |
| 294 | |||
| 295 | <!-- Aspect Ratios --> | 299 | <!-- Aspect Ratios --> |
| 296 | <string name="ratio_default">بنەڕەت (16:9)</string> | 300 | <string name="ratio_default">بنەڕەت (16:9)</string> |
| 297 | <string name="ratio_force_four_three">ڕووبەری 4:3</string> | 301 | <string name="ratio_force_four_three">ڕووبەری 4:3</string> |
| @@ -326,6 +330,12 @@ | |||
| 326 | <string name="theme_mode_light">ڕوناکی</string> | 330 | <string name="theme_mode_light">ڕوناکی</string> |
| 327 | <string name="theme_mode_dark">تاریک</string> | 331 | <string name="theme_mode_dark">تاریک</string> |
| 328 | 332 | ||
| 333 | <!-- Anisotropic filtering options --> | ||
| 334 | <string name="multiplier_two">2x</string> | ||
| 335 | <string name="multiplier_four">4x</string> | ||
| 336 | <string name="multiplier_eight">8x</string> | ||
| 337 | <string name="multiplier_sixteen">16x</string> | ||
| 338 | |||
| 329 | <!-- Black backgrounds theme --> | 339 | <!-- Black backgrounds theme --> |
| 330 | <string name="use_black_backgrounds">پاشبنەمای ڕەش</string> | 340 | <string name="use_black_backgrounds">پاشبنەمای ڕەش</string> |
| 331 | <string name="use_black_backgrounds_description">لە کاتی بەکارهێنانی ڕووکاری تاریکدا، پاشبنەمای ڕەش دادەنێ.</string> | 341 | <string name="use_black_backgrounds_description">لە کاتی بەکارهێنانی ڕووکاری تاریکدا، پاشبنەمای ڕەش دادەنێ.</string> |
diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml new file mode 100644 index 000000000..b9a4a11e4 --- /dev/null +++ b/src/android/app/src/main/res/values-cs/strings.xml | |||
| @@ -0,0 +1,265 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> | ||
| 3 | |||
| 4 | <string name="emulation_notification_channel_name">Emulace je aktivnÃ</string> | ||
| 5 | <string name="notice_notification_channel_name">Upozorněnà a chyby</string> | ||
| 6 | <string name="notice_notification_channel_description">Ukáže oznámenà v pÅ™ÃpadÄ› chyby.</string> | ||
| 7 | <string name="notification_permission_not_granted">Oznámenà nejsou oprávněna!</string> | ||
| 8 | |||
| 9 | <!-- Setup strings --> | ||
| 10 | <string name="welcome">VÃtejte!</string> | ||
| 11 | <string name="get_started">ZaÄÃt</string> | ||
| 12 | <string name="keys">KlÃÄe</string> | ||
| 13 | <string name="select_keys">Vybrat klÃÄe</string> | ||
| 14 | <string name="games">Hry</string> | ||
| 15 | <string name="done">Hotovo</string> | ||
| 16 | <string name="done_description">Vše je připraveno.\nUžijte si vaše hry!</string> | ||
| 17 | <string name="text_continue">PokraÄovat</string> | ||
| 18 | <string name="next">DalÅ¡Ã</string> | ||
| 19 | <string name="back">Zpět</string> | ||
| 20 | <string name="add_games">Přidat hry</string> | ||
| 21 | <string name="add_games_description">Vyber svoji složku se hrami</string> | ||
| 22 | <!-- Home strings --> | ||
| 23 | <string name="home_games">Hry</string> | ||
| 24 | <string name="home_search">Hledat</string> | ||
| 25 | <string name="home_settings">NastavenÃ</string> | ||
| 26 | <string name="empty_gamelist">Nebyly nalezeny žádné soubory nebo ještě nebyl vybrán žádný adresář s hrami.</string> | ||
| 27 | <string name="search_and_filter_games">Hledat a filtrovat hry</string> | ||
| 28 | <string name="select_games_folder">Vybrat složku s hrami</string> | ||
| 29 | <string name="manage_game_folders">Spravovat složky s hrami</string> | ||
| 30 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | ||
| 31 | <string name="install_prod_keys">Instalovat prod.keys</string> | ||
| 32 | <string name="install_prod_keys_warning">PÅ™eskoÄit pÅ™idávánà klÃÄů?</string> | ||
| 33 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> | ||
| 34 | <string name="notifications">OznámenÃ</string> | ||
| 35 | <string name="give_permission">UdÄ›lit oprávnÄ›nÃ</string> | ||
| 36 | <string name="notification_warning">PÅ™eskoÄit udÄ›lenà oprávnÄ›nà k oznámenÃ?</string> | ||
| 37 | <string name="notification_warning_description">yuzu vám nebude schopno oznámit důležité informace.</string> | ||
| 38 | <string name="permission_denied">OprávnÄ›nà zamÃtnuto</string> | ||
| 39 | <string name="permission_denied_description">ZamÃtnul jste toto oprávnÄ›nà pÅ™ÃliÅ¡ mnohokrát, musÃte manuálnÄ› udÄ›lit oprávnÄ›nà v nastavenà systému.</string> | ||
| 40 | <string name="about">O aplikaci</string> | ||
| 41 | <string name="about_description">Verze sestavenÃ, titulky a vÃce</string> | ||
| 42 | <string name="warning_help">Pomoc</string> | ||
| 43 | <string name="warning_skip">PÅ™eskoÄit</string> | ||
| 44 | <string name="warning_cancel">Zrušit</string> | ||
| 45 | <string name="install_amiibo_keys">Instalovat Amiibo klÃÄe</string> | ||
| 46 | <string name="install_amiibo_keys_description">Povinné použità Amiibo ve hře</string> | ||
| 47 | <string name="invalid_keys_file">Vybran̩ kl̀e jsou neplatn̩</string> | ||
| 48 | <string name="install_keys_success">KlÃÄe úspěšnÄ› nainstalovány</string> | ||
| 49 | <string name="reading_keys_failure">Chyba pÅ™i Ätenà šifrovacÃch klÃÄů</string> | ||
| 50 | <string name="invalid_keys_error">Neplatné Å¡ifrovacà klÃÄe</string> | ||
| 51 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | ||
| 52 | <string name="gpu_driver_manager">Správce ovladaÄe GPU</string> | ||
| 53 | <string name="install_gpu_driver">Instalovat GPU ovladaÄ</string> | ||
| 54 | <string name="advanced_settings">PokroÄilé nastavenÃ</string> | ||
| 55 | <string name="settings_description">Konfigurovat nastavenà emulátoru</string> | ||
| 56 | <string name="search_recently_played">Nedávno hrané</string> | ||
| 57 | <string name="search_recently_added">Nedávno přidané</string> | ||
| 58 | <string name="search_homebrew">Homebrew</string> | ||
| 59 | <string name="open_user_folder">OtevÅ™Ãt yuzu složku</string> | ||
| 60 | <string name="open_user_folder_description">Spravovat soubory yuzu</string> | ||
| 61 | <string name="no_file_manager">Nenalezen žádný správce souborů</string> | ||
| 62 | <string name="notification_no_directory_link">Nepovedlo se otevÅ™Ãt yuzu složku</string> | ||
| 63 | <string name="manage_save_data">Spravovat data postupu ve hře</string> | ||
| 64 | <string name="manage_save_data_description">Data postupu nalezeny. ProsÃm vyberte možnost.</string> | ||
| 65 | <string name="import_export_saves_description">Importovat nebo exportovat data postupu</string> | ||
| 66 | <string name="save_file_imported_success">Uspěšně importováno</string> | ||
| 67 | <string name="save_file_invalid_zip_structure">Neplatná struktura dat postupu</string> | ||
| 68 | <string name="import_saves">Importovat</string> | ||
| 69 | <string name="export_saves">Exportovat</string> | ||
| 70 | <string name="install_firmware">Nainstalovat firmware</string> | ||
| 71 | <string name="firmware_installing">Instalovánà firmwaru</string> | ||
| 72 | <string name="firmware_installed_success">Firmware byl úspěšně nainstalován</string> | ||
| 73 | <string name="firmware_installed_failure">Instalace firmwaru selhala</string> | ||
| 74 | <string name="install_game_content">Nainstalovat obsah hry</string> | ||
| 75 | <string name="install_game_content_description">Nainstalovat aktualizace hry nebo DLC</string> | ||
| 76 | <string name="installing_game_content">Instalovánà obsahu...</string> | ||
| 77 | <string name="install_game_content_failure">Chyba při instalaci soubor(ů) do NAND</string> | ||
| 78 | <string name="manage_yuzu_data">Spravovat data yuzu</string> | ||
| 79 | <string name="game_folders">Složky s hrami</string> | ||
| 80 | <string name="folder_already_added">Tato složka byla již přidána!</string> | ||
| 81 | <string name="game_folder_properties">Vlastnosti složky s hrami</string> | ||
| 82 | <string name="album_applet_description">Zobrazovat obrázky uložené v uživatelské složce se snÃmky obrazovky pomocà systémového prohlÞeÄe fotografiÃ</string> | ||
| 83 | <string name="cabinet_nickname_and_owner">Nastavenà pÅ™ezdÃvky a vlastnÃka</string> | ||
| 84 | <!-- About screen strings --> | ||
| 85 | <string name="gaia_is_not_real">Gaia nenà skuteÄná</string> | ||
| 86 | <string name="copied_to_clipboard">ZkopÃrováno do schránky</string> | ||
| 87 | <string name="about_app_description">Open-source Switch emulátor</string> | ||
| 88 | <string name="contributors">Přispěvatelé</string> | ||
| 89 | <string name="contributors_description">Vyrobeno s \u2764 od yuzu týmu</string> | ||
| 90 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | ||
| 91 | <string name="build">ÄŒÃslo sestavenÃ</string> | ||
| 92 | <string name="user_data">Uživatelská data</string> | ||
| 93 | <string name="exporting_user_data">Exportovánà uživatelských dat...</string> | ||
| 94 | <string name="importing_user_data">Importovánà uživatelských dat...</string> | ||
| 95 | <string name="import_user_data">Importovat uživatelská data</string> | ||
| 96 | <string name="invalid_yuzu_backup">Neplatná záloha yuzu</string> | ||
| 97 | <string name="user_data_export_success">Uživatelská data byla úspěšně exportována.</string> | ||
| 98 | <string name="user_data_import_success">Uživatelská data byla úspěšně importována.</string> | ||
| 99 | <string name="user_data_export_cancelled">Export zrušen</string> | ||
| 100 | <string name="support_link">https://discord.gg/u77vRWY</string> | ||
| 101 | <string name="website_link">https://yuzu-emu.org/</string> | ||
| 102 | <string name="github_link">https://github.com/yuzu-emu</string> | ||
| 103 | |||
| 104 | <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> | ||
| 105 | <string name="no_manual_installation">Žádná manuálnà instalace</string> | ||
| 106 | <string name="prioritized_support">Prioritnà podpora</string> | ||
| 107 | <string name="our_eternal_gratitude">NaÅ¡e vÄ›Äná vdÄ›Änost</string> | ||
| 108 | <string name="are_you_interested">Máte zájem?</string> | ||
| 109 | |||
| 110 | <!-- General settings strings --> | ||
| 111 | <string name="frame_limit_enable">Omezit rychlost</string> | ||
| 112 | <string name="cpu_accuracy">CPU přesnost</string> | ||
| 113 | <string name="emulated_region">Emulovaná oblast</string> | ||
| 114 | <string name="emulated_language">Emulovaný jazyk</string> | ||
| 115 | <string name="use_custom_rtc">Vlastnà RTC</string> | ||
| 116 | <!-- Graphics settings strings --> | ||
| 117 | <string name="renderer_accuracy">Úroveň přesnosti</string> | ||
| 118 | <string name="renderer_vsync">VSync režim</string> | ||
| 119 | <string name="renderer_screen_layout">Orientace</string> | ||
| 120 | <string name="renderer_aspect_ratio">Poměr stran</string> | ||
| 121 | <!-- Debug settings strings --> | ||
| 122 | <string name="cpu">CPU</string> | ||
| 123 | <string name="renderer_api">API</string> | ||
| 124 | <!-- Audio settings strings --> | ||
| 125 | <string name="audio_output_engine">Výstupnà engine</string> | ||
| 126 | <string name="audio_volume">Hlasitost</string> | ||
| 127 | <string name="audio_volume_description">Udává hlasitost zvukového výstupu.</string> | ||
| 128 | |||
| 129 | <!-- Miscellaneous --> | ||
| 130 | <string name="slider_default">VýchozÃ</string> | ||
| 131 | <string name="ini_saved">Nastavenà uložena</string> | ||
| 132 | <string name="gameid_saved">Uložena nastavenà pro %1$s</string> | ||
| 133 | <string name="loading">NaÄÃtánÃ...</string> | ||
| 134 | <string name="shutting_down">VypÃnánÃ...</string> | ||
| 135 | <string name="reset_setting_confirmation">Chcete obnovit toto nastavenà zpět na jeho výchozà hodnotu?</string> | ||
| 136 | <string name="reset_to_default">Navrátit k výchozÃmu</string> | ||
| 137 | <string name="reset_all_settings">Resetovat všechna nastaven�</string> | ||
| 138 | <string name="reset_all_settings_description">VÅ¡echna pokroÄilá nastavenà budou obnovena na jejich výchozà konfiguraci. Toto nelze vrátit zpÄ›t.</string> | ||
| 139 | <string name="close">ZavÅ™Ãt</string> | ||
| 140 | <string name="learn_more">Zjistit vÃce</string> | ||
| 141 | <string name="auto">Automatické</string> | ||
| 142 | <string name="string_import">Importovat</string> | ||
| 143 | <string name="export">Exportovat</string> | ||
| 144 | <string name="install">Nainstalovat</string> | ||
| 145 | <string name="delete">Smazat</string> | ||
| 146 | <string name="export_success">Úspěšně exportováno</string> | ||
| 147 | <string name="start">Start</string> | ||
| 148 | <string name="clear">Vymazat</string> | ||
| 149 | <string name="custom">VlastnÃ</string> | ||
| 150 | <!-- GPU driver installation --> | ||
| 151 | <string name="select_gpu_driver">Vybrat GPU ovladaÄ</string> | ||
| 152 | <string name="select_gpu_driver_title">Chcete nahradit váš aktuálnà ovladaÄ GPU?</string> | ||
| 153 | <string name="select_gpu_driver_install">Nainstalovat</string> | ||
| 154 | <string name="select_gpu_driver_default">VýchozÃ</string> | ||
| 155 | <string name="select_gpu_driver_error">Vybrán neplatný ovladaÄ</string> | ||
| 156 | <string name="driver_already_installed">OvladaÄ již nainstalován</string> | ||
| 157 | <string name="system_gpu_driver">Systémový ovladaÄ GPU</string> | ||
| 158 | <string name="installing_driver">Instalovánà ovladaÄe...</string> | ||
| 159 | |||
| 160 | <!-- Preferences Screen --> | ||
| 161 | <string name="preferences_settings">NastavenÃ</string> | ||
| 162 | <string name="preferences_general">Obecné</string> | ||
| 163 | <string name="preferences_system">Systém</string> | ||
| 164 | <string name="preferences_graphics">Grafika</string> | ||
| 165 | <string name="preferences_audio">Zvuk</string> | ||
| 166 | <string name="preferences_audio_description">Výstupnà engine, hlasitost</string> | ||
| 167 | <string name="preferences_theme">Vzhled a barva</string> | ||
| 168 | <string name="preferences_debug">LadÄ›nÃ</string> | ||
| 169 | <!-- Game properties --> | ||
| 170 | <string name="info">Info</string> | ||
| 171 | <string name="path">Cesta</string> | ||
| 172 | <string name="developer">Vývojář</string> | ||
| 173 | <string name="version">Verze</string> | ||
| 174 | <string name="copy_details">ZkopÃrovat podrobnosti</string> | ||
| 175 | <string name="add_ons">Modifkace</string> | ||
| 176 | <string name="addons_game">RozÅ¡ÃÅ™enÃ: %1$s</string> | ||
| 177 | <string name="select_content_type">Typ obsahu</string> | ||
| 178 | <string name="updates_and_dlc">Aktualizace a DLC</string> | ||
| 179 | <string name="mods_and_cheats">Módy a cheaty</string> | ||
| 180 | <string name="addon_installed_successfully">RozÅ¡ÃÅ™enà úspěšnÄ› nainstalováno</string> | ||
| 181 | <string name="verifying_content">Ověřovánà obsahu...</string> | ||
| 182 | <string name="emulation_done">Hotovo</string> | ||
| 183 | <string name="emulation_control_scale">MěřÃtko</string> | ||
| 184 | <string name="emulation_control_opacity">Průhlednost</string> | ||
| 185 | <string name="touchscreen">Dotyková obrazovka</string> | ||
| 186 | |||
| 187 | <!-- Errors and warnings --> | ||
| 188 | <string name="abort_button">Přerušit</string> | ||
| 189 | <string name="continue_button">PokraÄovat</string> | ||
| 190 | <string name="system_archive_not_found">Systémový ArchÃv Nenalezen</string> | ||
| 191 | <string name="save_load_error">UkládacÃ/NaÄÃtacà chyba</string> | ||
| 192 | <string name="fatal_error">Fatálnà Chyba</string> | ||
| 193 | <!-- Region Names --> | ||
| 194 | <string name="region_japan">Japonsko</string> | ||
| 195 | <string name="region_usa">USA</string> | ||
| 196 | <string name="region_europe">Evropa</string> | ||
| 197 | <string name="region_australia">Austrálie</string> | ||
| 198 | <string name="region_china">ÄŒÃna</string> | ||
| 199 | <string name="region_korea">Korea</string> | ||
| 200 | <string name="region_taiwan">Taiwan</string> | ||
| 201 | |||
| 202 | <string name="memory_byte_shorthand">B</string> | ||
| 203 | <string name="memory_gigabyte">GB</string> | ||
| 204 | <!-- Renderer APIs --> | ||
| 205 | <string name="renderer_vulkan">Vulkan</string> | ||
| 206 | <string name="renderer_none">Žádné</string> | ||
| 207 | |||
| 208 | <!-- Renderer Accuracy --> | ||
| 209 | <string name="renderer_accuracy_normal">NormálnÃ</string> | ||
| 210 | <string name="renderer_accuracy_high">Vysoká</string> | ||
| 211 | <!-- Resolutions --> | ||
| 212 | <string name="resolution_half">0.5X (360p/540p)</string> | ||
| 213 | <string name="resolution_three_quarter">0.75X (540p/810p)</string> | ||
| 214 | <string name="resolution_one">1X (720p/1080p)</string> | ||
| 215 | <string name="resolution_two">2X (1440p/2160p) (Pomalé)</string> | ||
| 216 | <string name="resolution_three">3X (2160p/3240p) (Pomalé)</string> | ||
| 217 | <string name="resolution_four">4X (2880p/4320p) (Pomalé)</string> | ||
| 218 | |||
| 219 | <string name="scaling_filter_bilinear">BilineárnÃ</string> | ||
| 220 | <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string> | ||
| 221 | |||
| 222 | <!-- Anti-Aliasing --> | ||
| 223 | <string name="anti_aliasing_none">Žádné</string> | ||
| 224 | <string name="anti_aliasing_fxaa">FXAA</string> | ||
| 225 | <string name="anti_aliasing_smaa">SMAA</string> | ||
| 226 | |||
| 227 | <!-- Screen Layouts --> | ||
| 228 | <string name="screen_layout_auto">Automatické</string> | ||
| 229 | <!-- Aspect Ratios --> | ||
| 230 | <string name="ratio_default">Výchozà (16:9)</string> | ||
| 231 | <string name="ratio_force_four_three">Vynutit 4:3</string> | ||
| 232 | <string name="ratio_force_twenty_one_nine">Vynutit 21:9</string> | ||
| 233 | <!-- CPU Accuracy --> | ||
| 234 | <string name="cpu_accuracy_accurate">Přesné</string> | ||
| 235 | <string name="cpu_accuracy_unsafe">NebezpeÄné</string> | ||
| 236 | <string name="gamepad_home">Home</string> | ||
| 237 | <string name="building_shaders">Budovánà shaderů</string> | ||
| 238 | |||
| 239 | <!-- Theme options --> | ||
| 240 | <string name="change_app_theme">Změnit vzhled aplikace</string> | ||
| 241 | <string name="theme_default">VýchozÃ</string> | ||
| 242 | <string name="theme_material_you">Material You</string> | ||
| 243 | |||
| 244 | <!-- Theme Modes --> | ||
| 245 | <string name="change_theme_mode">Změnit styl vzhledu</string> | ||
| 246 | <string name="theme_mode_follow_system">Podle systému</string> | ||
| 247 | <string name="theme_mode_light">Světlé</string> | ||
| 248 | <string name="theme_mode_dark">Tmavé</string> | ||
| 249 | |||
| 250 | <!-- Anisotropic filtering options --> | ||
| 251 | <string name="multiplier_two">2x</string> | ||
| 252 | <string name="multiplier_four">4x</string> | ||
| 253 | <string name="multiplier_eight">8x</string> | ||
| 254 | <string name="multiplier_sixteen">16x</string> | ||
| 255 | |||
| 256 | <!-- Black backgrounds theme --> | ||
| 257 | <string name="use_black_backgrounds">ÄŒerná pozadÃ</string> | ||
| 258 | <!-- Picture-In-Picture --> | ||
| 259 | <string name="picture_in_picture">Obraz v obraze</string> | ||
| 260 | <string name="mute">Ztlumit</string> | ||
| 261 | <string name="unmute">Vypnout ztlumenÃ</string> | ||
| 262 | |||
| 263 | <!-- Licenses screen strings --> | ||
| 264 | <string name="licenses">Licence</string> | ||
| 265 | </resources> | ||
diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml index 9c6590b5e..483ea8c88 100644 --- a/src/android/app/src/main/res/values-de/strings.xml +++ b/src/android/app/src/main/res/values-de/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">Es wurden keine Dateien gefunden oder es wurde noch kein Spielverzeichnis ausgewählt.</string> | 34 | <string name="empty_gamelist">Es wurden keine Dateien gefunden oder es wurde noch kein Spielverzeichnis ausgewählt.</string> |
| 35 | <string name="search_and_filter_games">Spiele suchen und filtern</string> | 35 | <string name="search_and_filter_games">Spiele suchen und filtern</string> |
| 36 | <string name="select_games_folder">Spieleverzeichnis auswählen</string> | 36 | <string name="select_games_folder">Spieleverzeichnis auswählen</string> |
| 37 | <string name="manage_game_folders">Spiele-Ordner verwalten</string> | ||
| 37 | <string name="select_games_folder_description">Erlaubt yuzu die Spieleliste zu füllen</string> | 38 | <string name="select_games_folder_description">Erlaubt yuzu die Spieleliste zu füllen</string> |
| 38 | <string name="add_games_warning">Auswahl des Spieleverzeichnisses überspringen?</string> | 39 | <string name="add_games_warning">Auswahl des Spieleverzeichnisses überspringen?</string> |
| 39 | <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string> | 40 | <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string> |
| @@ -67,9 +68,11 @@ | |||
| 67 | <string name="invalid_keys_error">Ungültige Schlüssel</string> | 68 | <string name="invalid_keys_error">Ungültige Schlüssel</string> |
| 68 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 69 | <string name="install_keys_failure_description">Die ausgewählte Datei ist falsch oder beschädigt. Bitte kopieren Sie Ihre Schlüssel erneut.</string> | 70 | <string name="install_keys_failure_description">Die ausgewählte Datei ist falsch oder beschädigt. Bitte kopieren Sie Ihre Schlüssel erneut.</string> |
| 71 | <string name="gpu_driver_manager">GPU-Treiber Verwaltung</string> | ||
| 70 | <string name="install_gpu_driver">GPU-Treiber installieren</string> | 72 | <string name="install_gpu_driver">GPU-Treiber installieren</string> |
| 71 | <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string> | 73 | <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string> |
| 72 | <string name="advanced_settings">Erweiterte Einstellungen</string> | 74 | <string name="advanced_settings">Erweiterte Einstellungen</string> |
| 75 | <string name="advanced_settings_game">Erweiterte Einstellungen: %1$s</string> | ||
| 73 | <string name="settings_description">Emulatoreinstellungen konfigurieren</string> | 76 | <string name="settings_description">Emulatoreinstellungen konfigurieren</string> |
| 74 | <string name="search_recently_played">Kürzlich gespielt</string> | 77 | <string name="search_recently_played">Kürzlich gespielt</string> |
| 75 | <string name="search_recently_added">Kürzlich hinzugefügt</string> | 78 | <string name="search_recently_added">Kürzlich hinzugefügt</string> |
| @@ -83,7 +86,11 @@ | |||
| 83 | <string name="notification_no_directory_link_description">Bitte suche den Benutzerordner manuell über die Seitenleiste des Dateimanagers.</string> | 86 | <string name="notification_no_directory_link_description">Bitte suche den Benutzerordner manuell über die Seitenleiste des Dateimanagers.</string> |
| 84 | <string name="manage_save_data">Speicherdaten verwalten</string> | 87 | <string name="manage_save_data">Speicherdaten verwalten</string> |
| 85 | <string name="manage_save_data_description">Speicherdaten gefunden. Bitte wähle unten eine Option aus.</string> | 88 | <string name="manage_save_data_description">Speicherdaten gefunden. Bitte wähle unten eine Option aus.</string> |
| 89 | <string name="import_save_warning">Speicherdaten importieren</string> | ||
| 90 | <string name="import_save_warning_description">Das überschreibt alle existierenden Speicherdaten für dieses Spiel mit der ausgewählten Datei. Wirklich fortfahren?</string> | ||
| 86 | <string name="import_export_saves_description">Speicherdaten importieren oder exportieren</string> | 91 | <string name="import_export_saves_description">Speicherdaten importieren oder exportieren</string> |
| 92 | <string name="save_files_importing">Importiere Speicherdaten...</string> | ||
| 93 | <string name="save_files_exporting">Exportiere Speicherdaten...</string> | ||
| 87 | <string name="save_file_imported_success">Erfolgreich importiert</string> | 94 | <string name="save_file_imported_success">Erfolgreich importiert</string> |
| 88 | <string name="save_file_invalid_zip_structure">Ungültige Speicherverzeichnisstruktur</string> | 95 | <string name="save_file_invalid_zip_structure">Ungültige Speicherverzeichnisstruktur</string> |
| 89 | <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string> | 96 | <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string> |
| @@ -98,8 +105,17 @@ | |||
| 98 | <string name="share_log_description">Debug-Logs an yuzu zur Untersuchung absenden</string> | 105 | <string name="share_log_description">Debug-Logs an yuzu zur Untersuchung absenden</string> |
| 99 | <string name="share_log_missing">Keine Log-Datei gefunden</string> | 106 | <string name="share_log_missing">Keine Log-Datei gefunden</string> |
| 100 | <string name="install_game_content">Spiel installieren</string> | 107 | <string name="install_game_content">Spiel installieren</string> |
| 101 | <string name="install_game_content_description">Spiel Update oder DLC installieren</string> | 108 | <string name="install_game_content_description">Spiel-Updates oder DLCs installieren</string> |
| 109 | <string name="installing_game_content">Installiere...</string> | ||
| 110 | <string name="install_game_content_failed_count">%1$d Installationsfehler</string> | ||
| 111 | <string name="install_game_content_success_install">%1$d erfolgreich installiert</string> | ||
| 112 | <string name="install_game_content_success_overwrite">%1$d erfolgreich überschrieben</string> | ||
| 102 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> | 113 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> |
| 114 | <string name="manage_yuzu_data">yuzu-Daten Verwalten</string> | ||
| 115 | <string name="share_save_file">Speicherdaten teilen</string> | ||
| 116 | <string name="game_folders">Spiele-Ordner</string> | ||
| 117 | <string name="add_game_folder">Spiele-Ordner hinzufügen</string> | ||
| 118 | <string name="applets_error_firmware">Firmware nicht installiert</string> | ||
| 103 | <!-- About screen strings --> | 119 | <!-- About screen strings --> |
| 104 | <string name="gaia_is_not_real">Gaia ist nicht real</string> | 120 | <string name="gaia_is_not_real">Gaia ist nicht real</string> |
| 105 | <string name="copied_to_clipboard">In die Zwischenablage kopiert</string> | 121 | <string name="copied_to_clipboard">In die Zwischenablage kopiert</string> |
| @@ -110,6 +126,10 @@ | |||
| 110 | <string name="licenses_description">Projekte, die yuzu für Android möglich machen </string> | 126 | <string name="licenses_description">Projekte, die yuzu für Android möglich machen </string> |
| 111 | <string name="build">Build</string> | 127 | <string name="build">Build</string> |
| 112 | <string name="user_data">Nutzerdaten</string> | 128 | <string name="user_data">Nutzerdaten</string> |
| 129 | <string name="importing_user_data">Importiere Nutzerdaten...</string> | ||
| 130 | <string name="import_user_data">Nutzerdaten importieren</string> | ||
| 131 | <string name="user_data_export_success">Nutzerdaten erfolgreich exportiert</string> | ||
| 132 | <string name="user_data_import_success">Nutzerdaten erfolgreich importiert</string> | ||
| 113 | <string name="user_data_export_cancelled">Export abgebrochen</string> | 133 | <string name="user_data_export_cancelled">Export abgebrochen</string> |
| 114 | <string name="support_link">https://discord.gg/u77vRWY</string> | 134 | <string name="support_link">https://discord.gg/u77vRWY</string> |
| 115 | <string name="website_link">https://yuzu-emu.org/</string> | 135 | <string name="website_link">https://yuzu-emu.org/</string> |
| @@ -137,7 +157,7 @@ | |||
| 137 | <string name="cpu_accuracy">CPU-Genauigkeit</string> | 157 | <string name="cpu_accuracy">CPU-Genauigkeit</string> |
| 138 | <!-- System settings strings --> | 158 | <!-- System settings strings --> |
| 139 | <string name="use_docked_mode">Gedockter Modus</string> | 159 | <string name="use_docked_mode">Gedockter Modus</string> |
| 140 | <string name="use_docked_mode_description">Der Docked Modus erhöht die Auflösung, verringert die aber die Leistung. Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die Leistung.</string> | 160 | <string name="use_docked_mode_description">Der Gedockte-Modus erhöht die Auflösung, verringert aber die Leistung. Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die Leistung.</string> |
| 141 | <string name="emulated_region">Emulierte Region</string> | 161 | <string name="emulated_region">Emulierte Region</string> |
| 142 | <string name="emulated_language">Emulierte Sprache</string> | 162 | <string name="emulated_language">Emulierte Sprache</string> |
| 143 | <string name="select_rtc_date">RTC-Datum auswählen</string> | 163 | <string name="select_rtc_date">RTC-Datum auswählen</string> |
| @@ -145,10 +165,12 @@ | |||
| 145 | <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string> | 165 | <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string> |
| 146 | <!-- Graphics settings strings --> | 166 | <!-- Graphics settings strings --> |
| 147 | <string name="renderer_accuracy">Genauigkeitsstufe</string> | 167 | <string name="renderer_accuracy">Genauigkeitsstufe</string> |
| 168 | <string name="renderer_resolution">Auflösung (Mobil/Gedockt)</string> | ||
| 148 | <string name="renderer_vsync">VSync-Modus</string> | 169 | <string name="renderer_vsync">VSync-Modus</string> |
| 149 | <string name="renderer_screen_layout">Orientierung</string> | 170 | <string name="renderer_screen_layout">Orientierung</string> |
| 150 | <string name="renderer_aspect_ratio">Seitenverhältnis</string> | 171 | <string name="renderer_aspect_ratio">Seitenverhältnis</string> |
| 151 | <string name="renderer_scaling_filter">Fensteranpassungsfilter</string> | 172 | <string name="renderer_scaling_filter">Fensteranpassungsfilter</string> |
| 173 | <string name="renderer_anti_aliasing">Kantenglättung</string> | ||
| 152 | <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string> | 174 | <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string> |
| 153 | <string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</string> | 175 | <string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</string> |
| 154 | <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string> | 176 | <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string> |
| @@ -168,9 +190,12 @@ | |||
| 168 | <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string> | 190 | <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string> |
| 169 | <string name="unimplemented_menu">Unimplementiertes Menü</string> | 191 | <string name="unimplemented_menu">Unimplementiertes Menü</string> |
| 170 | <string name="loading">Lädt...</string> | 192 | <string name="loading">Lädt...</string> |
| 193 | <string name="shutting_down">Beendet...</string> | ||
| 171 | <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string> | 194 | <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string> |
| 172 | <string name="reset_to_default">Auf Standard zurücksetzen</string> | 195 | <string name="reset_to_default">Auf Standard zurücksetzen</string> |
| 196 | <string name="reset_to_default_description">Setzt alle erweiterten Einstellungen zurück</string> | ||
| 173 | <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string> | 197 | <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string> |
| 198 | <string name="reset_all_settings_description">Alle erweiterten Einstellungen werden auf ihren Standardwert zurückgesetzt. Dies kann nicht rückgängig gemacht werden.</string> | ||
| 174 | <string name="settings_reset">Einstellungen zurückgesetzt</string> | 199 | <string name="settings_reset">Einstellungen zurückgesetzt</string> |
| 175 | <string name="close">Schließen</string> | 200 | <string name="close">Schließen</string> |
| 176 | <string name="learn_more">Mehr erfahren</string> | 201 | <string name="learn_more">Mehr erfahren</string> |
| @@ -182,14 +207,20 @@ | |||
| 182 | <string name="export_failed">Export fehlgeschlagen</string> | 207 | <string name="export_failed">Export fehlgeschlagen</string> |
| 183 | <string name="import_failed">Import fehlgeschlagen</string> | 208 | <string name="import_failed">Import fehlgeschlagen</string> |
| 184 | <string name="cancelling">Abbrechen</string> | 209 | <string name="cancelling">Abbrechen</string> |
| 185 | 210 | <string name="install">Installieren</string> | |
| 211 | <string name="delete">Löschen</string> | ||
| 212 | <string name="edit">Bearbeiten</string> | ||
| 213 | <string name="export_success">Erfolgreich exportiert</string> | ||
| 214 | <string name="start">Start</string> | ||
| 215 | <string name="clear">Löschen</string> | ||
| 216 | <string name="custom">Benutzerdefiniert</string> | ||
| 186 | <!-- GPU driver installation --> | 217 | <!-- GPU driver installation --> |
| 187 | <string name="select_gpu_driver">GPU-Treiber auswählen</string> | 218 | <string name="select_gpu_driver">GPU-Treiber auswählen</string> |
| 188 | <string name="select_gpu_driver_title">Möchtest du deinen aktuellen GPU-Treiber ersetzen?</string> | 219 | <string name="select_gpu_driver_title">Möchtest du deinen aktuellen GPU-Treiber ersetzen?</string> |
| 189 | <string name="select_gpu_driver_install">Installieren</string> | 220 | <string name="select_gpu_driver_install">Installieren</string> |
| 190 | <string name="select_gpu_driver_default">Standard</string> | 221 | <string name="select_gpu_driver_default">Standard</string> |
| 191 | <string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string> | 222 | <string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string> |
| 192 | <string name="select_gpu_driver_error">Ungültiger Treiber ausgewählt, Standard-Treiber wird verwendet!</string> | 223 | <string name="driver_already_installed">Treiber bereits installiert</string> |
| 193 | <string name="system_gpu_driver">System GPU-Treiber</string> | 224 | <string name="system_gpu_driver">System GPU-Treiber</string> |
| 194 | <string name="installing_driver">Treiber wird installiert...</string> | 225 | <string name="installing_driver">Treiber wird installiert...</string> |
| 195 | 226 | ||
| @@ -197,11 +228,37 @@ | |||
| 197 | <string name="preferences_settings">Einstellungen</string> | 228 | <string name="preferences_settings">Einstellungen</string> |
| 198 | <string name="preferences_general">Allgemein</string> | 229 | <string name="preferences_general">Allgemein</string> |
| 199 | <string name="preferences_system">System</string> | 230 | <string name="preferences_system">System</string> |
| 231 | <string name="preferences_system_description">Gedockter Modus, Region, Sprache</string> | ||
| 200 | <string name="preferences_graphics">Grafik</string> | 232 | <string name="preferences_graphics">Grafik</string> |
| 233 | <string name="preferences_graphics_description">Genauigkeitsstufe, Auflösung, Shader-Cache</string> | ||
| 201 | <string name="preferences_audio">Audio</string> | 234 | <string name="preferences_audio">Audio</string> |
| 235 | <string name="preferences_audio_description">Ausgabe-Engine, Lautstärke</string> | ||
| 202 | <string name="preferences_theme">Theme und Farbe</string> | 236 | <string name="preferences_theme">Theme und Farbe</string> |
| 203 | <string name="preferences_debug">Debug</string> | 237 | <string name="preferences_debug">Debug</string> |
| 204 | 238 | <!-- Game properties --> | |
| 239 | <string name="info">Info</string> | ||
| 240 | <string name="info_description">Programm-ID, Entwickler, Version</string> | ||
| 241 | <string name="per_game_settings">Spieleinstellungen</string> | ||
| 242 | <string name="per_game_settings_description">Einstellungen für dieses Spiel ändern</string> | ||
| 243 | <string name="path">Pfad</string> | ||
| 244 | <string name="program_id">Programm-ID</string> | ||
| 245 | <string name="developer">Entwickler</string> | ||
| 246 | <string name="version">Version</string> | ||
| 247 | <string name="copy_details">Details kopieren</string> | ||
| 248 | <string name="add_ons">Add-ons</string> | ||
| 249 | <string name="add_ons_description">Mods, Updates und DLC aktivieren oder deaktivieren</string> | ||
| 250 | <string name="clear_shader_cache">Shader-Cache löschen</string> | ||
| 251 | <string name="clear_shader_cache_description">Löscht alle für dieses Spiel erstellten Shader</string> | ||
| 252 | <string name="cleared_shaders_successfully">Shader erfolgreich gelöscht</string> | ||
| 253 | <string name="addons_game">Add-ons: %1$s</string> | ||
| 254 | <string name="save_data">Speicherdaten</string> | ||
| 255 | <string name="save_data_description">Importiert oder exportiert Speicherdaten für dieses Spiel</string> | ||
| 256 | <string name="delete_save_data">Speicherdaten löschen</string> | ||
| 257 | <string name="delete_save_data_description">Löscht alle Speicherdaten für dieses Spiel</string> | ||
| 258 | <string name="delete_save_data_warning_description">Das löscht unwiederbringlich alle Speicherdaten für dieses Spiel. Wirklich fortfahren?</string> | ||
| 259 | <string name="save_data_deleted_successfully">Speicherdaten erfolgreich gelöscht</string> | ||
| 260 | <string name="invalid_directory">Ungültiges Verzeichnis</string> | ||
| 261 | <string name="addon_installed_successfully">Add-on erfolgreich installiert</string> | ||
| 205 | <!-- ROM loading errors --> | 262 | <!-- ROM loading errors --> |
| 206 | <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string> | 263 | <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string> |
| 207 | <string name="loader_error_encrypted_keys_description"><![CDATA[Bitte stelle sicher dass die <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> Datei installiert ist, damit Spiele entschlüsselt werden können.]]></string> | 264 | <string name="loader_error_encrypted_keys_description"><![CDATA[Bitte stelle sicher dass die <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> Datei installiert ist, damit Spiele entschlüsselt werden können.]]></string> |
| @@ -220,7 +277,10 @@ | |||
| 220 | <string name="emulation_control_opacity">Transparenz</string> | 277 | <string name="emulation_control_opacity">Transparenz</string> |
| 221 | <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string> | 278 | <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string> |
| 222 | <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string> | 279 | <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string> |
| 280 | <string name="emulation_pause">Emulation pausieren</string> | ||
| 281 | <string name="emulation_unpause">Emulation fortsetzen</string> | ||
| 223 | <string name="emulation_input_overlay">Overlay-Optionen</string> | 282 | <string name="emulation_input_overlay">Overlay-Optionen</string> |
| 283 | <string name="touchscreen">Touchscreen</string> | ||
| 224 | 284 | ||
| 225 | <string name="load_settings">Lade Einstellungen...</string> | 285 | <string name="load_settings">Lade Einstellungen...</string> |
| 226 | 286 | ||
| @@ -248,6 +308,7 @@ | |||
| 248 | 308 | ||
| 249 | <!-- Memory Sizes --> | 309 | <!-- Memory Sizes --> |
| 250 | <string name="memory_byte">Byte</string> | 310 | <string name="memory_byte">Byte</string> |
| 311 | <string name="memory_byte_shorthand">B</string> | ||
| 251 | <string name="memory_kilobyte">KB</string> | 312 | <string name="memory_kilobyte">KB</string> |
| 252 | <string name="memory_megabyte">MB</string> | 313 | <string name="memory_megabyte">MB</string> |
| 253 | <string name="memory_gigabyte">GB</string> | 314 | <string name="memory_gigabyte">GB</string> |
| @@ -291,9 +352,10 @@ | |||
| 291 | <string name="anti_aliasing_fxaa">FXAA</string> | 352 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 292 | <string name="anti_aliasing_smaa">SMAA</string> | 353 | <string name="anti_aliasing_smaa">SMAA</string> |
| 293 | 354 | ||
| 294 | <string name="screen_layout_portrait">Portrait</string> | 355 | <!-- Screen Layouts --> |
| 295 | <string name="screen_layout_auto">Auto</string> | 356 | <string name="screen_layout_auto">Auto</string> |
| 296 | 357 | <string name="screen_layout_landscape">Horizontal</string> | |
| 358 | <string name="screen_layout_portrait">Vertikal</string> | ||
| 297 | <!-- Aspect Ratios --> | 359 | <!-- Aspect Ratios --> |
| 298 | <string name="ratio_default">Standard (16:9)</string> | 360 | <string name="ratio_default">Standard (16:9)</string> |
| 299 | <string name="ratio_force_four_three">4:3 erzwingen</string> | 361 | <string name="ratio_force_four_three">4:3 erzwingen</string> |
| @@ -318,22 +380,27 @@ | |||
| 318 | <string name="building_shaders">Shader werden erstellt</string> | 380 | <string name="building_shaders">Shader werden erstellt</string> |
| 319 | 381 | ||
| 320 | <!-- Theme options --> | 382 | <!-- Theme options --> |
| 321 | <string name="change_app_theme">App-Thema ändern</string> | 383 | <string name="change_app_theme">Theme</string> |
| 322 | <string name="theme_default">Standard</string> | 384 | <string name="theme_default">Standard</string> |
| 323 | <string name="theme_material_you">Material You</string> | 385 | <string name="theme_material_you">Material You</string> |
| 324 | 386 | ||
| 325 | <!-- Theme Modes --> | 387 | <!-- Theme Modes --> |
| 326 | <string name="change_theme_mode">Themen-Modus ändern</string> | 388 | <string name="change_theme_mode">Design</string> |
| 327 | <string name="theme_mode_follow_system">System folgen</string> | 389 | <string name="theme_mode_follow_system">System folgen</string> |
| 328 | <string name="theme_mode_light">Hell</string> | 390 | <string name="theme_mode_light">Hell</string> |
| 329 | <string name="theme_mode_dark">Dunkel</string> | 391 | <string name="theme_mode_dark">Dunkel</string> |
| 330 | 392 | ||
| 331 | <!-- Audio output engines --> | ||
| 332 | <string name="cubeb">cubeb</string> | 393 | <string name="cubeb">cubeb</string> |
| 333 | 394 | ||
| 395 | <!-- Anisotropic filtering options --> | ||
| 396 | <string name="multiplier_two">2x</string> | ||
| 397 | <string name="multiplier_four">4x</string> | ||
| 398 | <string name="multiplier_eight">8x</string> | ||
| 399 | <string name="multiplier_sixteen">16x</string> | ||
| 400 | |||
| 334 | <!-- Black backgrounds theme --> | 401 | <!-- Black backgrounds theme --> |
| 335 | <string name="use_black_backgrounds">Schwarze Hintergründe</string> | 402 | <string name="use_black_backgrounds">Schwarze Hintergründe</string> |
| 336 | <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Themes, schwarze Hintergründe verwenden.</string> | 403 | <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Designs, schwarze Hintergründe verwenden.</string> |
| 337 | 404 | ||
| 338 | <!-- Picture-In-Picture --> | 405 | <!-- Picture-In-Picture --> |
| 339 | <string name="picture_in_picture">Bild im Bild</string> | 406 | <string name="picture_in_picture">Bild im Bild</string> |
diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml index 103ac6e65..c3825710b 100644 --- a/src/android/app/src/main/res/values-es/strings.xml +++ b/src/android/app/src/main/res/values-es/strings.xml | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | <string name="app_disclaimer">Este software ejecuta juegos para la videoconsola Nintendo Switch. Los videojuegos o claves no vienen incluidos.<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 está ejecutándose</string> |
| 8 | <string name="notice_notification_channel_name">Avisos y errores</string> | 8 | <string name="notice_notification_channel_name">Avisos y errores</string> |
| 9 | <string name="notice_notification_channel_description">Mostrar notificaciones cuándo algo vaya mal.</string> | 9 | <string name="notice_notification_channel_description">Mostrar notificaciones cuándo algo vaya mal.</string> |
| 10 | <string name="notification_permission_not_granted">¡Permisos de notificación no concedidos!</string> | 10 | <string name="notification_permission_not_granted">¡Permisos de notificación no concedidos!</string> |
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">No se ha encontrado ningún archivo o aún no se ha seleccionado ningún directorio de juegos.</string> | 34 | <string name="empty_gamelist">No se ha encontrado ningún archivo o aún no se ha seleccionado ningún directorio de juegos.</string> |
| 35 | <string name="search_and_filter_games">Busca y filtra juegos</string> | 35 | <string name="search_and_filter_games">Busca y filtra juegos</string> |
| 36 | <string name="select_games_folder">Seleccionar carpeta de juegos</string> | 36 | <string name="select_games_folder">Seleccionar carpeta de juegos</string> |
| 37 | <string name="manage_game_folders">Gestionar carpetas de juegos</string> | ||
| 37 | <string name="select_games_folder_description">Permite que yuzu llene la lista de juegos</string> | 38 | <string name="select_games_folder_description">Permite que yuzu llene la lista de juegos</string> |
| 38 | <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string> | 39 | <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string> |
| 39 | <string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una carpeta de juegos.</string> | 40 | <string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una carpeta de juegos.</string> |
| @@ -44,23 +45,23 @@ | |||
| 44 | <string name="install_prod_keys">Instalar prod.keys</string> | 45 | <string name="install_prod_keys">Instalar prod.keys</string> |
| 45 | <string name="install_prod_keys_description">Requerido para descifrar juegos</string> | 46 | <string name="install_prod_keys_description">Requerido para descifrar juegos</string> |
| 46 | <string name="install_prod_keys_warning">¿Omitir agregar claves?</string> | 47 | <string name="install_prod_keys_warning">¿Omitir agregar claves?</string> |
| 47 | <string name="install_prod_keys_warning_description">Se requieren claves válidas para emular juegos. Solo las aplicaciones homebrew funcionarán si continúas.</string> | 48 | <string name="install_prod_keys_warning_description">Se requieren claves válidas para emular juegos. Solo las aplicaciones homebrew funcionarán si continúas.</string> |
| 48 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> | 49 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> |
| 49 | <string name="notifications">Notificaciones</string> | 50 | <string name="notifications">Notificaciones</string> |
| 50 | <string name="notifications_description">Otorgue el permiso de notificación con el botón de abajo.</string> | 51 | <string name="notifications_description">Otorga el permiso de notificación con el botón de abajo.</string> |
| 51 | <string name="give_permission">Conceder permiso</string> | 52 | <string name="give_permission">Conceder permiso</string> |
| 52 | <string name="notification_warning">¿Omitir conceder el permiso de notificación?</string> | 53 | <string name="notification_warning">¿Omitir conceder el permiso de notificación?</string> |
| 53 | <string name="notification_warning_description">yuzu no podrá notificarte información importante.</string> | 54 | <string name="notification_warning_description">yuzu no podrá notificarte información importante.</string> |
| 54 | <string name="permission_denied">Permiso denegado</string> | 55 | <string name="permission_denied">Permiso denegado</string> |
| 55 | <string name="permission_denied_description">Negó este permiso demasiadas veces y ahora debe otorgarlo manualmente en la configuración del sistema.</string> | 56 | <string name="permission_denied_description">Se ha denegado este permiso demasiadas veces y ahora debes otorgarlo de forma manual en la configuración del sistema.</string> |
| 56 | <string name="about">Acerca de</string> | 57 | <string name="about">Acerca de</string> |
| 57 | <string name="about_description">Versión, créditos y más</string> | 58 | <string name="about_description">Versión, créditos y más</string> |
| 58 | <string name="warning_help">Ayuda</string> | 59 | <string name="warning_help">Ayuda</string> |
| 59 | <string name="warning_skip">Siguiente</string> | 60 | <string name="warning_skip">Siguiente</string> |
| 60 | <string name="warning_cancel">Cancelar</string> | 61 | <string name="warning_cancel">Cancelar</string> |
| 61 | <string name="install_amiibo_keys">Instalar clave de Amiiboo</string> | 62 | <string name="install_amiibo_keys">Instalar claves de Amiibo</string> |
| 62 | <string name="install_amiibo_keys_description">Necesario para usar Amiibo en el juego</string> | 63 | <string name="install_amiibo_keys_description">Necesario para usar Amiibos en el juego</string> |
| 63 | <string name="invalid_keys_file">Archivo de claves seleccionado inválido</string> | 64 | <string name="invalid_keys_file">Archivo de claves seleccionado no válido</string> |
| 64 | <string name="install_keys_success">Claves instaladas correctamente</string> | 65 | <string name="install_keys_success">Claves instaladas correctamente</string> |
| 65 | <string name="reading_keys_failure">Error al leer las claves de cifrado</string> | 66 | <string name="reading_keys_failure">Error al leer las claves de cifrado</string> |
| 66 | <string name="install_prod_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .keys y pruebe otra vez.</string> | 67 | <string name="install_prod_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .keys y pruebe otra vez.</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">Claves de cifrado no válidas</string> | 69 | <string name="invalid_keys_error">Claves de cifrado no válidas</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string> | 71 | <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string> |
| 72 | <string name="gpu_driver_manager">Explorador de drivers de GPU</string> | ||
| 71 | <string name="install_gpu_driver">Instalar driver de GPU</string> | 73 | <string name="install_gpu_driver">Instalar driver de GPU</string> |
| 72 | <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string> | 74 | <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string> |
| 73 | <string name="advanced_settings">Opciones avanzadas</string> | 75 | <string name="advanced_settings">Opciones avanzadas</string> |
| @@ -85,7 +87,11 @@ | |||
| 85 | <string name="notification_no_directory_link_description">Por favor, busque la carpeta user con el panel lateral del explorador de archivos de forma manual.</string> | 87 | <string name="notification_no_directory_link_description">Por favor, busque la carpeta user con el panel lateral del explorador de archivos de forma manual.</string> |
| 86 | <string name="manage_save_data">Administrar datos de guardado</string> | 88 | <string name="manage_save_data">Administrar datos de guardado</string> |
| 87 | <string name="manage_save_data_description">Guardar los datos encontrados. Por favor, seleccione una opción de abajo.</string> | 89 | <string name="manage_save_data_description">Guardar los datos encontrados. Por favor, seleccione una opción de abajo.</string> |
| 90 | <string name="import_save_warning">Importar datos de guardado</string> | ||
| 91 | <string name="import_save_warning_description">Ésto sobreescribirá todos los datos de guardado existentes con el archivo proporcionado. ¿Está seguro de querer continuar?</string> | ||
| 88 | <string name="import_export_saves_description">Importar o exportar archivos de guardado</string> | 92 | <string name="import_export_saves_description">Importar o exportar archivos de guardado</string> |
| 93 | <string name="save_files_importing">Importando archivos de guardado...</string> | ||
| 94 | <string name="save_files_exporting">Exportando archivos de guardado...</string> | ||
| 89 | <string name="save_file_imported_success">Importado correctamente</string> | 95 | <string name="save_file_imported_success">Importado correctamente</string> |
| 90 | <string name="save_file_invalid_zip_structure">Estructura del directorio de guardado no válido</string> | 96 | <string name="save_file_invalid_zip_structure">Estructura del directorio de guardado no válido</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string> | 97 | <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string> |
| @@ -95,7 +101,7 @@ | |||
| 95 | <string name="install_firmware_description">El firmware debe estar en un archivo ZIP y es necesario para ejecutar algunos juegos</string> | 101 | <string name="install_firmware_description">El firmware debe estar en un archivo ZIP y es necesario para ejecutar algunos juegos</string> |
| 96 | <string name="firmware_installing">Instalando firmware</string> | 102 | <string name="firmware_installing">Instalando firmware</string> |
| 97 | <string name="firmware_installed_success">Firmware instalado con éxito</string> | 103 | <string name="firmware_installed_success">Firmware instalado con éxito</string> |
| 98 | <string name="firmware_installed_failure">Falló la instalación de firmware</string> | 104 | <string name="firmware_installed_failure">Error en la instalación de firmware</string> |
| 99 | <string name="firmware_installed_failure_description">Asegúrese de que los archivos nca del firmware estén en la raÃz del zip e inténtelo de nuevo.</string> | 105 | <string name="firmware_installed_failure_description">Asegúrese de que los archivos nca del firmware estén en la raÃz del zip e inténtelo de nuevo.</string> |
| 100 | <string name="share_log">Compartir registros de depuración</string> | 106 | <string name="share_log">Compartir registros de depuración</string> |
| 101 | <string name="share_log_description">Comparta el archivo de registro de yuzu para depurar problemas</string> | 107 | <string name="share_log_description">Comparta el archivo de registro de yuzu para depurar problemas</string> |
| @@ -115,9 +121,43 @@ | |||
| 115 | <string name="custom_driver_not_supported">Drivers personalizados no soportados</string> | 121 | <string name="custom_driver_not_supported">Drivers personalizados no soportados</string> |
| 116 | <string name="custom_driver_not_supported_description">En estos momentos, la carga de drivers personalizados no está disponible para este dispositivo..\n¡Comprueba esta opción en el futuro para ver si ya está añadido el soporte a ese dispositivo!</string> | 122 | <string name="custom_driver_not_supported_description">En estos momentos, la carga de drivers personalizados no está disponible para este dispositivo..\n¡Comprueba esta opción en el futuro para ver si ya está añadido el soporte a ese dispositivo!</string> |
| 117 | <string name="manage_yuzu_data">Administrar datos de yuzu</string> | 123 | <string name="manage_yuzu_data">Administrar datos de yuzu</string> |
| 118 | <string name="manage_yuzu_data_description">Importa/exporta el firmware, las keys, los datos de usuario, ¡y más!</string> | 124 | <string name="manage_yuzu_data_description">Importa/exporta el firmware, las claves, los datos de usuario, ¡y más!</string> |
| 119 | <string name="share_save_file">Compartir archivo de guardado</string> | 125 | <string name="share_save_file">Compartir archivo de guardado</string> |
| 120 | <string name="export_save_failed">La exportación del guardado falló</string> | 126 | <string name="export_save_failed">Error al exportar el archivo de guardado</string> |
| 127 | <string name="game_folders">Carpetas de juegos</string> | ||
| 128 | <string name="deep_scan">Escaneo recursivo </string> | ||
| 129 | <string name="add_game_folder">Añadir carpeta con juegos</string> | ||
| 130 | <string name="folder_already_added">¡Está carpeta ya se habÃa añadido!</string> | ||
| 131 | <string name="game_folder_properties">Propiedades de la carpeta de juegos</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="one">No se ha podido importar %d archivo de guardado.</item> | ||
| 134 | <item quantity="many">No se han podido importar %d archivos de guardado.</item> | ||
| 135 | <item quantity="other">No se han podido importar %d archivos de guardado.</item> | ||
| 136 | </plurals> | ||
| 137 | <plurals name="saves_import_success"> | ||
| 138 | <item quantity="one">%d archivo de guardado importado con éxito.</item> | ||
| 139 | <item quantity="many">%d archivos de guardado importados con éxito.</item> | ||
| 140 | <item quantity="other">%d archivos de guardado importados con éxito.</item> | ||
| 141 | </plurals> | ||
| 142 | <string name="no_save_data_found">No hay archivos de guardado</string> | ||
| 143 | |||
| 144 | <!-- Applet launcher strings --> | ||
| 145 | <string name="applets">Ejecutador de applet</string> | ||
| 146 | <string name="applets_description">Ejecutar applets de sistema usando el firmware instalado</string> | ||
| 147 | <string name="applets_error_firmware">Firmware no instalado</string> | ||
| 148 | <string name="applets_error_applet">Applet no disponible</string> | ||
| 149 | <string name="applets_error_description"><![CDATA[Asegúrese de que el archivo<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> y el <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> estén instalados e inténtelo de nuevo.]]></string> | ||
| 150 | <string name="album_applet">Ãlbum</string> | ||
| 151 | <string name="album_applet_description">Ver las imágenes que están en la carpeta \"screenshots\" del usuario con el visor de fotos del sistema</string> | ||
| 152 | <string name="mii_edit_applet">Editor de Mii</string> | ||
| 153 | <string name="mii_edit_applet_description">Mira y edita Mii con el editor del sistema</string> | ||
| 154 | <string name="cabinet_applet">Cabinet</string> | ||
| 155 | <string name="cabinet_applet_description">Edita y borra los datos guardado del amiibo</string> | ||
| 156 | <string name="cabinet_launcher">Ejecutador de Cabinet</string> | ||
| 157 | <string name="cabinet_nickname_and_owner">Configuración del apodo y propietario</string> | ||
| 158 | <string name="cabinet_game_data_eraser">Borrador de datos de juego</string> | ||
| 159 | <string name="cabinet_restorer">Restaurador</string> | ||
| 160 | <string name="cabinet_formatter">Formateador</string> | ||
| 121 | 161 | ||
| 122 | <!-- About screen strings --> | 162 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia no es real</string> | 163 | <string name="gaia_is_not_real">Gaia no es real</string> |
| @@ -161,6 +201,7 @@ | |||
| 161 | <string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje especÃfico de la velocidad normal.</string> | 201 | <string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje especÃfico de la velocidad normal.</string> |
| 162 | <string name="frame_limit_slider">Limitar porcentaje de velocidad</string> | 202 | <string name="frame_limit_slider">Limitar porcentaje de velocidad</string> |
| 163 | <string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. 100% es la velocidad normal. Valores más altos o bajos incrementarán o disminuirán el lÃmite de velocidad.</string> | 203 | <string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. 100% es la velocidad normal. Valores más altos o bajos incrementarán o disminuirán el lÃmite de velocidad.</string> |
| 204 | <string name="cpu_backend">Motor de CPU</string> | ||
| 164 | <string name="cpu_accuracy">Precisión de CPU</string> | 205 | <string name="cpu_accuracy">Precisión de CPU</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 206 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 207 | ||
| @@ -186,11 +227,13 @@ | |||
| 186 | <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string> | 227 | <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string> |
| 187 | <string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string> | 228 | <string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string> |
| 188 | <string name="renderer_asynchronous_shaders">Usar shaders asÃncronos</string> | 229 | <string name="renderer_asynchronous_shaders">Usar shaders asÃncronos</string> |
| 189 | <string name="renderer_asynchronous_shaders_description">Compila shaders de manera asÃncrona, reduciendo los parones, pero puede introducir fallos.</string> | 230 | <string name="renderer_asynchronous_shaders_description">Compila shaders de manera asÃncrona, reduce los parones pero puede introducir fallos.</string> |
| 190 | <string name="renderer_reactive_flushing">Usar limpieza reactiva</string> | 231 | <string name="renderer_reactive_flushing">Usar limpieza reactiva</string> |
| 191 | <string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string> | 232 | <string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string> |
| 192 | <string name="use_disk_shader_cache">Caché de shaders en disco</string> | 233 | <string name="use_disk_shader_cache">Caché de shaders en disco</string> |
| 193 | <string name="use_disk_shader_cache_description">Reduce los parones almacenando y cargando shaders generados.</string> | 234 | <string name="use_disk_shader_cache_description">Reduce los parones almacenando y cargando shaders generados.</string> |
| 235 | <string name="anisotropic_filtering">Filtrado anisotrópico</string> | ||
| 236 | <string name="anisotropic_filtering_description">Mejora la calidad de las texturas al ser observadas desde ángulos oblicuos</string> | ||
| 194 | 237 | ||
| 195 | <!-- Debug settings strings --> | 238 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 239 | <string name="cpu">CPU</string> |
| @@ -217,6 +260,7 @@ | |||
| 217 | <string name="shutting_down">Saliendo...</string> | 260 | <string name="shutting_down">Saliendo...</string> |
| 218 | <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string> | 261 | <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string> |
| 219 | <string name="reset_to_default">Restablecer a predeterminado</string> | 262 | <string name="reset_to_default">Restablecer a predeterminado</string> |
| 263 | <string name="reset_to_default_description">Reinicia todos los ajustes avanzados</string> | ||
| 220 | <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string> | 264 | <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string> |
| 221 | <string name="reset_all_settings_description">Todas las opciones avanzadas se restablecerán a su configuración predeterminada. Esta acción no se puede deshacer.</string> | 265 | <string name="reset_all_settings_description">Todas las opciones avanzadas se restablecerán a su configuración predeterminada. Esta acción no se puede deshacer.</string> |
| 222 | <string name="settings_reset">Reiniciar la configuracion</string> | 266 | <string name="settings_reset">Reiniciar la configuracion</string> |
| @@ -230,14 +274,24 @@ | |||
| 230 | <string name="export_failed">La exportación falló</string> | 274 | <string name="export_failed">La exportación falló</string> |
| 231 | <string name="import_failed">La importación falló</string> | 275 | <string name="import_failed">La importación falló</string> |
| 232 | <string name="cancelling">Cancelando</string> | 276 | <string name="cancelling">Cancelando</string> |
| 233 | 277 | <string name="install">Instalar</string> | |
| 278 | <string name="delete">Borrar</string> | ||
| 279 | <string name="edit">Editar</string> | ||
| 280 | <string name="export_success">Exportado correctamente</string> | ||
| 281 | <string name="start">Comenzar</string> | ||
| 282 | <string name="clear">Limpiar</string> | ||
| 283 | <string name="global">Global</string> | ||
| 284 | <string name="custom">Perzonalizado</string> | ||
| 285 | <string name="notice">Aviso</string> | ||
| 286 | <string name="import_complete">La importación se completó</string> | ||
| 234 | <!-- GPU driver installation --> | 287 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">Seleccionar driver GPU</string> | 288 | <string name="select_gpu_driver">Seleccionar driver GPU</string> |
| 236 | <string name="select_gpu_driver_title">¿Quiere reemplazar el driver de GPU actual?</string> | 289 | <string name="select_gpu_driver_title">¿Quiere reemplazar el driver de GPU actual?</string> |
| 237 | <string name="select_gpu_driver_install">Instalar</string> | 290 | <string name="select_gpu_driver_install">Instalar</string> |
| 238 | <string name="select_gpu_driver_default">Predeterminado</string> | 291 | <string name="select_gpu_driver_default">Predeterminado</string> |
| 239 | <string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string> | 292 | <string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string> |
| 240 | <string name="select_gpu_driver_error">¡Driver no válido, utilizando el predeterminado del sistema!</string> | 293 | <string name="select_gpu_driver_error">Driver no válido seleccionado</string> |
| 294 | <string name="driver_already_installed">Driver ya instalado</string> | ||
| 241 | <string name="system_gpu_driver">Driver GPU del sistema</string> | 295 | <string name="system_gpu_driver">Driver GPU del sistema</string> |
| 242 | <string name="installing_driver">Instalando driver...</string> | 296 | <string name="installing_driver">Instalando driver...</string> |
| 243 | 297 | ||
| @@ -245,11 +299,52 @@ | |||
| 245 | <string name="preferences_settings">Ajustes</string> | 299 | <string name="preferences_settings">Ajustes</string> |
| 246 | <string name="preferences_general">General</string> | 300 | <string name="preferences_general">General</string> |
| 247 | <string name="preferences_system">Sistema</string> | 301 | <string name="preferences_system">Sistema</string> |
| 302 | <string name="preferences_system_description">Modo en Dock, región, idioma</string> | ||
| 248 | <string name="preferences_graphics">Gráficos</string> | 303 | <string name="preferences_graphics">Gráficos</string> |
| 304 | <string name="preferences_graphics_description">Nivel de precisión, resolución, caché de shaders</string> | ||
| 249 | <string name="preferences_audio">Audio</string> | 305 | <string name="preferences_audio">Audio</string> |
| 306 | <string name="preferences_audio_description">Motor de salida, volumen</string> | ||
| 250 | <string name="preferences_theme">Tema y color</string> | 307 | <string name="preferences_theme">Tema y color</string> |
| 251 | <string name="preferences_debug">Depuración</string> | 308 | <string name="preferences_debug">Depuración</string> |
| 252 | 309 | <string name="preferences_debug_description">CPU/GPU debug, API gráfica, fastMEM</string> | |
| 310 | |||
| 311 | <!-- Game properties --> | ||
| 312 | <string name="info">Información</string> | ||
| 313 | <string name="info_description">ID de programa, desarrollador, versión</string> | ||
| 314 | <string name="per_game_settings">Configuración por juego</string> | ||
| 315 | <string name="per_game_settings_description">Editar opciones especÃficas para este juego</string> | ||
| 316 | <string name="launch_options">Ejecutar configuración</string> | ||
| 317 | <string name="path">Ruta</string> | ||
| 318 | <string name="program_id">ID de programa</string> | ||
| 319 | <string name="developer">Desarrollador</string> | ||
| 320 | <string name="version">Versión</string> | ||
| 321 | <string name="copy_details">Copiar detalles</string> | ||
| 322 | <string name="add_ons">Extras/Add-ons</string> | ||
| 323 | <string name="add_ons_description">Activa/desactiva mods, actualizaciones y DLC</string> | ||
| 324 | <string name="clear_shader_cache">Limpiar la caché de shaders</string> | ||
| 325 | <string name="clear_shader_cache_description">Elimina todos los shaders construidos mientras se jugaba al juego</string> | ||
| 326 | <string name="clear_shader_cache_warning_description">Experimentarás más parones mientras que la caché de shaders se regenera</string> | ||
| 327 | <string name="cleared_shaders_successfully">Shaders limpiados con éxito</string> | ||
| 328 | <string name="addons_game">Addons: %1$s</string> | ||
| 329 | <string name="save_data">Datos de guardado</string> | ||
| 330 | <string name="save_data_description">Controla los datos de guardado de este juego</string> | ||
| 331 | <string name="delete_save_data">Borrar datos de guardado</string> | ||
| 332 | <string name="delete_save_data_description">Elimina todos los datos de guardado de este juego</string> | ||
| 333 | <string name="delete_save_data_warning_description">Ésto elimina de manera permanente todos los datos de guardado de este juego. ¿Seguro que quieres continuar?</string> | ||
| 334 | <string name="save_data_deleted_successfully">Datos de guardado eliminados con éxito</string> | ||
| 335 | <string name="select_content_type">Tipo de contenido</string> | ||
| 336 | <string name="updates_and_dlc">Actualizaciones y DLC</string> | ||
| 337 | <string name="mods_and_cheats">Mods y trucos</string> | ||
| 338 | <string name="addon_notice">Aviso importante de addons</string> | ||
| 339 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 340 | <string name="addon_notice_description">Para instalar mods y trucos, debes seleccionar una carpeta que contiene los directorios cheats/, romfs/, o exefs/ . ¡No podemos confirmar si éstos serán compatibles con tu juego, asà que ten cuidado!</string> | ||
| 341 | <string name="invalid_directory">Directorio no válido</string> | ||
| 342 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 343 | <string name="invalid_directory_description">Por favor, asegúrese de que el directorio que ha selecionado incluye las carpetas cheats/, romfs/, o exefs/ e inténtelo de nuevo.</string> | ||
| 344 | <string name="addon_installed_successfully">Addon instalado con éxito</string> | ||
| 345 | <string name="verifying_content">Verificando contenido...</string> | ||
| 346 | <string name="content_install_notice">Aviso importante de contenido</string> | ||
| 347 | <string name="content_install_notice_description">El contenido seleccionado no es de este juego.\n¿Instalar de todas maneras?</string> | ||
| 253 | <!-- ROM loading errors --> | 348 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">Su ROM está encriptada</string> | 349 | <string name="loader_error_encrypted">Su ROM está encriptada</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga las guÃas para redumpear<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> | 350 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga las guÃas para redumpear<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> |
| @@ -277,6 +372,7 @@ | |||
| 277 | <string name="emulation_pause">Pausar emulación</string> | 372 | <string name="emulation_pause">Pausar emulación</string> |
| 278 | <string name="emulation_unpause">Despausar emulación</string> | 373 | <string name="emulation_unpause">Despausar emulación</string> |
| 279 | <string name="emulation_input_overlay">Opciones de overlay</string> | 374 | <string name="emulation_input_overlay">Opciones de overlay</string> |
| 375 | <string name="touchscreen">Pantalla táctil</string> | ||
| 280 | 376 | ||
| 281 | <string name="load_settings">Cargando configuración...</string> | 377 | <string name="load_settings">Cargando configuración...</string> |
| 282 | 378 | ||
| @@ -308,6 +404,7 @@ | |||
| 308 | 404 | ||
| 309 | <!-- Memory Sizes --> | 405 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 406 | <string name="memory_byte">Byte</string> |
| 407 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">KB</string> | 408 | <string name="memory_kilobyte">KB</string> |
| 312 | <string name="memory_megabyte">MB</string> | 409 | <string name="memory_megabyte">MB</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 410 | <string name="memory_gigabyte">GB</string> |
| @@ -352,9 +449,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 449 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 450 | ||
| 354 | <!-- Screen Layouts --> | 451 | <!-- Screen Layouts --> |
| 452 | <string name="screen_layout_auto">Auto</string> | ||
| 453 | <string name="screen_layout_sensor_landscape">Sensor paisaje</string> | ||
| 355 | <string name="screen_layout_landscape">Paisaje</string> | 454 | <string name="screen_layout_landscape">Paisaje</string> |
| 455 | <string name="screen_layout_reverse_landscape">Paisaje inverso</string> | ||
| 456 | <string name="screen_layout_sensor_portrait">Sensor retrato</string> | ||
| 356 | <string name="screen_layout_portrait">Retrato</string> | 457 | <string name="screen_layout_portrait">Retrato</string> |
| 357 | <string name="screen_layout_auto">Auto</string> | 458 | <string name="screen_layout_reverse_portrait">Retrato inverso</string> |
| 358 | 459 | ||
| 359 | <!-- Aspect Ratios --> | 460 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">Predeterminado (16:9)</string> | 461 | <string name="ratio_default">Predeterminado (16:9)</string> |
| @@ -363,6 +464,10 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">Forzar 16:10</string> | 464 | <string name="ratio_force_sixteen_ten">Forzar 16:10</string> |
| 364 | <string name="ratio_stretch">Ajustar a la ventana</string> | 465 | <string name="ratio_stretch">Ajustar a la ventana</string> |
| 365 | 466 | ||
| 467 | <!-- CPU Backend --> | ||
| 468 | <string name="cpu_backend_dynarmic">DynARMic (lento)</string> | ||
| 469 | <string name="cpu_backend_nce">Ejecución nativa de código (NCE)</string> | ||
| 470 | |||
| 366 | <!-- CPU Accuracy --> | 471 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">Preciso</string> | 472 | <string name="cpu_accuracy_accurate">Preciso</string> |
| 368 | <string name="cpu_accuracy_unsafe">Impreciso</string> | 473 | <string name="cpu_accuracy_unsafe">Impreciso</string> |
| @@ -391,8 +496,15 @@ | |||
| 391 | <string name="theme_mode_dark">Oscuro</string> | 496 | <string name="theme_mode_dark">Oscuro</string> |
| 392 | 497 | ||
| 393 | <!-- Audio output engines --> | 498 | <!-- Audio output engines --> |
| 499 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 500 | <string name="cubeb">cubeb</string> |
| 395 | 501 | ||
| 502 | <!-- Anisotropic filtering options --> | ||
| 503 | <string name="multiplier_two">x2</string> | ||
| 504 | <string name="multiplier_four">x4</string> | ||
| 505 | <string name="multiplier_eight">x8</string> | ||
| 506 | <string name="multiplier_sixteen">x16</string> | ||
| 507 | |||
| 396 | <!-- Black backgrounds theme --> | 508 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">Fondos oscuros</string> | 509 | <string name="use_black_backgrounds">Fondos oscuros</string> |
| 398 | <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string> | 510 | <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string> |
diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml index 5a827c50b..667fe33cb 100644 --- a/src/android/app/src/main/res/values-fr/strings.xml +++ b/src/android/app/src/main/res/values-fr/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">Aucun fichier n\'a été trouvé ou aucun répertoire de jeu n\'a encore été sélectionné.</string> | 34 | <string name="empty_gamelist">Aucun fichier n\'a été trouvé ou aucun répertoire de jeu n\'a encore été sélectionné.</string> |
| 35 | <string name="search_and_filter_games">Rechercher et filtrer les jeux</string> | 35 | <string name="search_and_filter_games">Rechercher et filtrer les jeux</string> |
| 36 | <string name="select_games_folder">Sélectionner le dossier des jeux</string> | 36 | <string name="select_games_folder">Sélectionner le dossier des jeux</string> |
| 37 | <string name="manage_game_folders">Gérer les dossiers de jeux</string> | ||
| 37 | <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string> | 38 | <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string> |
| 38 | <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string> | 39 | <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string> |
| 39 | <string name="add_games_warning_description">Les jeux ne seront pas affichés dans la liste des jeux si aucun dossier n\'est sélectionné.</string> | 40 | <string name="add_games_warning_description">Les jeux ne seront pas affichés dans la liste des jeux si aucun dossier n\'est sélectionné.</string> |
| @@ -47,7 +48,7 @@ | |||
| 47 | <string name="install_prod_keys_warning_description">Des clés valides sont nécessaires pour émuler des jeux commerciaux. Seules les applications homebrew fonctionneront si vous continuez.</string> | 48 | <string name="install_prod_keys_warning_description">Des clés valides sont nécessaires pour émuler des jeux commerciaux. Seules les applications homebrew fonctionneront si vous continuez.</string> |
| 48 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> | 49 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> |
| 49 | <string name="notifications">Notifications</string> | 50 | <string name="notifications">Notifications</string> |
| 50 | <string name="notifications_description">Accordez l\'autorisation de notification avec le bouton ci-dessous.</string> | 51 | <string name="notifications_description">Accorder la permission de notification avec le bouton ci-dessous.</string> |
| 51 | <string name="give_permission">Accorder la permission</string> | 52 | <string name="give_permission">Accorder la permission</string> |
| 52 | <string name="notification_warning">Ne pas accorder la permission de notification ?</string> | 53 | <string name="notification_warning">Ne pas accorder la permission de notification ?</string> |
| 53 | <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string> | 54 | <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">Clés de chiffrement invalides</string> | 69 | <string name="invalid_keys_error">Clés de chiffrement invalides</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string> | 71 | <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string> |
| 72 | <string name="gpu_driver_manager">Gestionnaire de pilotes du GPU</string> | ||
| 71 | <string name="install_gpu_driver">Installer le pilote du GPU</string> | 73 | <string name="install_gpu_driver">Installer le pilote du GPU</string> |
| 72 | <string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string> | 74 | <string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string> |
| 73 | <string name="advanced_settings">Paramètres avancés</string> | 75 | <string name="advanced_settings">Paramètres avancés</string> |
| @@ -85,7 +87,11 @@ | |||
| 85 | <string name="notification_no_directory_link_description">Veuillez localiser manuellement le dossier utilisateur avec le panneau latéral du gestionnaire de fichiers.</string> | 87 | <string name="notification_no_directory_link_description">Veuillez localiser manuellement le dossier utilisateur avec le panneau latéral du gestionnaire de fichiers.</string> |
| 86 | <string name="manage_save_data">Gérer les données de sauvegarde</string> | 88 | <string name="manage_save_data">Gérer les données de sauvegarde</string> |
| 87 | <string name="manage_save_data_description">Données de sauvegarde trouvées. Veuillez sélectionner une option ci-dessous.</string> | 89 | <string name="manage_save_data_description">Données de sauvegarde trouvées. Veuillez sélectionner une option ci-dessous.</string> |
| 90 | <string name="import_save_warning">Importer les données de sauvegarde</string> | ||
| 91 | <string name="import_save_warning_description">Cela écrasera toutes les données de sauvegarde existantes avec le fichier fourni. Êtes-vous sûr de vouloir continuer ?</string> | ||
| 88 | <string name="import_export_saves_description">Importer ou exporter des fichiers de sauvegarde</string> | 92 | <string name="import_export_saves_description">Importer ou exporter des fichiers de sauvegarde</string> |
| 93 | <string name="save_files_importing">Importation des fichiers de sauvegarde...</string> | ||
| 94 | <string name="save_files_exporting">Exportation des fichiers de sauvegarde...</string> | ||
| 89 | <string name="save_file_imported_success">Importé avec succès</string> | 95 | <string name="save_file_imported_success">Importé avec succès</string> |
| 90 | <string name="save_file_invalid_zip_structure">Structure de répertoire de sauvegarde non valide</string> | 96 | <string name="save_file_invalid_zip_structure">Structure de répertoire de sauvegarde non valide</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</string> | 97 | <string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</string> |
| @@ -118,6 +124,40 @@ | |||
| 118 | <string name="manage_yuzu_data_description">Importer/exporter le firmware, les clés, les données utilisateur, et bien plus encore !</string> | 124 | <string name="manage_yuzu_data_description">Importer/exporter le firmware, les clés, les données utilisateur, et bien plus encore !</string> |
| 119 | <string name="share_save_file">Partager le fichier de sauvegarde</string> | 125 | <string name="share_save_file">Partager le fichier de sauvegarde</string> |
| 120 | <string name="export_save_failed">Échec de l\'exportation de la sauvegarde</string> | 126 | <string name="export_save_failed">Échec de l\'exportation de la sauvegarde</string> |
| 127 | <string name="game_folders">Dossiers de jeux</string> | ||
| 128 | <string name="deep_scan">Analyse approfondie</string> | ||
| 129 | <string name="add_game_folder">Ajouter un dossier de jeu</string> | ||
| 130 | <string name="folder_already_added">Ce dossier a déjà été ajouté !</string> | ||
| 131 | <string name="game_folder_properties">Propriétés du dossier du jeu</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="one">Échec de l\'importation de %d sauvegarde</item> | ||
| 134 | <item quantity="many">Échec de l\'importation de %d sauvegardes </item> | ||
| 135 | <item quantity="other">Échec de l\'importation de %d sauvegardes</item> | ||
| 136 | </plurals> | ||
| 137 | <plurals name="saves_import_success"> | ||
| 138 | <item quantity="one">%d sauvegarde importée avec succès</item> | ||
| 139 | <item quantity="many">%d sauvegardes importées avec succès</item> | ||
| 140 | <item quantity="other">%d sauvegardes importées avec succès</item> | ||
| 141 | </plurals> | ||
| 142 | <string name="no_save_data_found">Aucune donnée de sauvegarde trouvée</string> | ||
| 143 | |||
| 144 | <!-- Applet launcher strings --> | ||
| 145 | <string name="applets">Lanceur d\'applets</string> | ||
| 146 | <string name="applets_description">Lancer des applets système en utilisant le firmware installé</string> | ||
| 147 | <string name="applets_error_firmware">Firmware non installé</string> | ||
| 148 | <string name="applets_error_applet">Applet non disponible</string> | ||
| 149 | <string name="applets_error_description"><![CDATA[Veuillez vous assurer que le fichier <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> et le <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> sont installés et essayez à nouveau.]]></string> | ||
| 150 | <string name="album_applet">Album</string> | ||
| 151 | <string name="album_applet_description">Afficher les images stockées dans le dossier de captures d\'écran de l\'utilisateur avec le visualiseur de photos système.</string> | ||
| 152 | <string name="mii_edit_applet">Éditeur Mii</string> | ||
| 153 | <string name="mii_edit_applet_description">Visualiser et modifier les Miis avec l\'éditeur système.</string> | ||
| 154 | <string name="cabinet_applet">Cabinet</string> | ||
| 155 | <string name="cabinet_applet_description">Modifier et supprimer des données stockées sur un amiibo</string> | ||
| 156 | <string name="cabinet_launcher">Cabinet</string> | ||
| 157 | <string name="cabinet_nickname_and_owner">Paramètres du surnom et du propriétaire</string> | ||
| 158 | <string name="cabinet_game_data_eraser">Effaceur de données de jeu</string> | ||
| 159 | <string name="cabinet_restorer">Restaurateur</string> | ||
| 160 | <string name="cabinet_formatter">Formateur</string> | ||
| 121 | 161 | ||
| 122 | <!-- About screen strings --> | 162 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia n\'est pas réel</string> | 163 | <string name="gaia_is_not_real">Gaia n\'est pas réel</string> |
| @@ -157,10 +197,11 @@ | |||
| 157 | <string name="are_you_interested">Es tu intéressé ?</string> | 197 | <string name="are_you_interested">Es tu intéressé ?</string> |
| 158 | 198 | ||
| 159 | <!-- General settings strings --> | 199 | <!-- General settings strings --> |
| 160 | <string name="frame_limit_enable">Limitation de vitesse</string> | 200 | <string name="frame_limit_enable">Limiter la vitesse</string> |
| 161 | <string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string> | 201 | <string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string> |
| 162 | <string name="frame_limit_slider">Limite en pourcentage de vitesse</string> | 202 | <string name="frame_limit_slider">Limiter le pourcentage de vitesse</string> |
| 163 | <string name="frame_limit_slider_description">Spécifier le pourcentage pour limiter la vitesse d\'émulation. 100% correspond à la vitesse normale. Des valeurs plus élevées ou plus basses augmenteront ou diminueront la limite de vitesse.</string> | 203 | <string name="frame_limit_slider_description">Spécifier le pourcentage pour limiter la vitesse d\'émulation. 100% correspond à la vitesse normale. Des valeurs plus élevées ou plus basses augmenteront ou diminueront la limite de vitesse.</string> |
| 204 | <string name="cpu_backend">Backend du CPU</string> | ||
| 164 | <string name="cpu_accuracy">Précision du CPU</string> | 205 | <string name="cpu_accuracy">Précision du CPU</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 206 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 207 | ||
| @@ -191,6 +232,8 @@ | |||
| 191 | <string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string> | 232 | <string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string> |
| 192 | <string name="use_disk_shader_cache">Utiliser les shader cache</string> | 233 | <string name="use_disk_shader_cache">Utiliser les shader cache</string> |
| 193 | <string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant localement les shaders générés</string> | 234 | <string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant localement les shaders générés</string> |
| 235 | <string name="anisotropic_filtering">Filtrage anisotropique</string> | ||
| 236 | <string name="anisotropic_filtering_description">Améliore la qualité des textures lorsqu\'elles sont visualisées sous des angles obliques</string> | ||
| 194 | 237 | ||
| 195 | <!-- Debug settings strings --> | 238 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 239 | <string name="cpu">CPU</string> |
| @@ -217,7 +260,8 @@ | |||
| 217 | <string name="shutting_down">Extinction en cours...</string> | 260 | <string name="shutting_down">Extinction en cours...</string> |
| 218 | <string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string> | 261 | <string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string> |
| 219 | <string name="reset_to_default">Réinitialiser par défaut</string> | 262 | <string name="reset_to_default">Réinitialiser par défaut</string> |
| 220 | <string name="reset_all_settings">Réinitialiser tous les réglages ?</string> | 263 | <string name="reset_to_default_description">Réinitialiser tous les paramètres avancés</string> |
| 264 | <string name="reset_all_settings">Réinitialiser tous les paramètres ?</string> | ||
| 221 | <string name="reset_all_settings_description">Tous les paramètres avancés seront réinitialisés à leur configuration par défaut. Ça ne peut pas être annulé.</string> | 265 | <string name="reset_all_settings_description">Tous les paramètres avancés seront réinitialisés à leur configuration par défaut. Ça ne peut pas être annulé.</string> |
| 222 | <string name="settings_reset">Paramètres réinitialisés</string> | 266 | <string name="settings_reset">Paramètres réinitialisés</string> |
| 223 | <string name="close">Fermer</string> | 267 | <string name="close">Fermer</string> |
| @@ -230,14 +274,24 @@ | |||
| 230 | <string name="export_failed">L\'exportation a échoué</string> | 274 | <string name="export_failed">L\'exportation a échoué</string> |
| 231 | <string name="import_failed">L\'importation a échoué</string> | 275 | <string name="import_failed">L\'importation a échoué</string> |
| 232 | <string name="cancelling">Annulation</string> | 276 | <string name="cancelling">Annulation</string> |
| 233 | 277 | <string name="install">Installer</string> | |
| 278 | <string name="delete">Supprimer</string> | ||
| 279 | <string name="edit">Éditer</string> | ||
| 280 | <string name="export_success">Exportation réussie</string> | ||
| 281 | <string name="start">Start</string> | ||
| 282 | <string name="clear">Effacer</string> | ||
| 283 | <string name="global">Global</string> | ||
| 284 | <string name="custom">Personnalisé</string> | ||
| 285 | <string name="notice">Avis</string> | ||
| 286 | <string name="import_complete">Importation terminée</string> | ||
| 234 | <!-- GPU driver installation --> | 287 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">Sélectionner le pilote du GPU</string> | 288 | <string name="select_gpu_driver">Sélectionner le pilote du GPU</string> |
| 236 | <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string> | 289 | <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string> |
| 237 | <string name="select_gpu_driver_install">Installer</string> | 290 | <string name="select_gpu_driver_install">Installer</string> |
| 238 | <string name="select_gpu_driver_default">Par défaut</string> | 291 | <string name="select_gpu_driver_default">Par défaut</string> |
| 239 | <string name="select_gpu_driver_use_default">Utilisation du pilote du GPU par défaut</string> | 292 | <string name="select_gpu_driver_use_default">Utilisation du pilote du GPU par défaut</string> |
| 240 | <string name="select_gpu_driver_error">Pilote non valide sélectionné, utilisation du paramètre par défaut du système !</string> | 293 | <string name="select_gpu_driver_error">Pilote non valide sélectionné</string> |
| 294 | <string name="driver_already_installed">Pilote déjà installé</string> | ||
| 241 | <string name="system_gpu_driver">Pilote du GPU du système</string> | 295 | <string name="system_gpu_driver">Pilote du GPU du système</string> |
| 242 | <string name="installing_driver">Installation du pilote...</string> | 296 | <string name="installing_driver">Installation du pilote...</string> |
| 243 | 297 | ||
| @@ -245,11 +299,52 @@ | |||
| 245 | <string name="preferences_settings">Paramètres</string> | 299 | <string name="preferences_settings">Paramètres</string> |
| 246 | <string name="preferences_general">Général</string> | 300 | <string name="preferences_general">Général</string> |
| 247 | <string name="preferences_system">Système</string> | 301 | <string name="preferences_system">Système</string> |
| 302 | <string name="preferences_system_description">Mode TV, région, langue</string> | ||
| 248 | <string name="preferences_graphics">Vidéo</string> | 303 | <string name="preferences_graphics">Vidéo</string> |
| 304 | <string name="preferences_graphics_description">Niveau de précision, résolution, cache de shaders</string> | ||
| 249 | <string name="preferences_audio">Audio</string> | 305 | <string name="preferences_audio">Audio</string> |
| 306 | <string name="preferences_audio_description">Moteur de sortie, volume</string> | ||
| 250 | <string name="preferences_theme">Thème et couleur</string> | 307 | <string name="preferences_theme">Thème et couleur</string> |
| 251 | <string name="preferences_debug">Débogage</string> | 308 | <string name="preferences_debug">Débogage</string> |
| 252 | 309 | <string name="preferences_debug_description">Débogage CPU/GPU, API graphique, fastmem</string> | |
| 310 | |||
| 311 | <!-- Game properties --> | ||
| 312 | <string name="info">Info</string> | ||
| 313 | <string name="info_description">ID du programme, développeur, version</string> | ||
| 314 | <string name="per_game_settings">Paramètres spécifiques au jeu</string> | ||
| 315 | <string name="per_game_settings_description">Modifier les paramètres spécifiques à ce jeu</string> | ||
| 316 | <string name="launch_options">Lancer la configuration</string> | ||
| 317 | <string name="path">Chemin</string> | ||
| 318 | <string name="program_id">ID du programme</string> | ||
| 319 | <string name="developer">Développeur</string> | ||
| 320 | <string name="version">Version</string> | ||
| 321 | <string name="copy_details">Copier les détails</string> | ||
| 322 | <string name="add_ons">Extensions</string> | ||
| 323 | <string name="add_ons_description">Activer les mods, mises à jour et DLC</string> | ||
| 324 | <string name="clear_shader_cache">Effacer le cache des shaders</string> | ||
| 325 | <string name="clear_shader_cache_description">Supprime tous les shaders générés en jouant à ce jeu</string> | ||
| 326 | <string name="clear_shader_cache_warning_description">Vous risquez de rencontrer davantage de saccades pendant que le cache des shaders se régénère.</string> | ||
| 327 | <string name="cleared_shaders_successfully">Shaders effacés avec succès</string> | ||
| 328 | <string name="addons_game">Addons : %1$s</string> | ||
| 329 | <string name="save_data">Données de sauvegarde</string> | ||
| 330 | <string name="save_data_description">Gérer les données de sauvegarde spécifiques à ce jeu</string> | ||
| 331 | <string name="delete_save_data">Supprimer les données de sauvegarde</string> | ||
| 332 | <string name="delete_save_data_description">Supprime toutes les données de sauvegarde spécifiques à ce jeu</string> | ||
| 333 | <string name="delete_save_data_warning_description">Cela supprime de manière irréversible toutes les données de sauvegarde de ce jeu. Êtes-vous sûr de vouloir continuer ?</string> | ||
| 334 | <string name="save_data_deleted_successfully">Données de sauvegarde supprimées avec succès</string> | ||
| 335 | <string name="select_content_type">Type de contenu</string> | ||
| 336 | <string name="updates_and_dlc">Mises à jour et DLC</string> | ||
| 337 | <string name="mods_and_cheats">Mods et cheats</string> | ||
| 338 | <string name="addon_notice">Notification importante concernant l\'addon</string> | ||
| 339 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 340 | <string name="addon_notice_description">Pour installer des mods et des cheats, vous devez sélectionner un dossier contenant un répertoire cheats/, romfs/ ou exefs/. Nous ne pouvons pas garantir leur compatibilité avec votre jeu, alors soyez prudent !</string> | ||
| 341 | <string name="invalid_directory">Répertoire non valide</string> | ||
| 342 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 343 | <string name="invalid_directory_description">Veuillez vous assurer que le répertoire que vous avez sélectionné contient un dossier cheats/, romfs/ ou exefs/, puis réessayez.</string> | ||
| 344 | <string name="addon_installed_successfully">Addon installé avec succès</string> | ||
| 345 | <string name="verifying_content">Vérification du contenu...</string> | ||
| 346 | <string name="content_install_notice">Avis d\'installation du contenu</string> | ||
| 347 | <string name="content_install_notice_description">Le contenu que vous avez sélectionné ne correspond pas à ce jeu.\nInstaller quand même ?</string> | ||
| 253 | <!-- ROM loading errors --> | 348 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">Votre ROM est cryptée</string> | 349 | <string name="loader_error_encrypted">Votre ROM est cryptée</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour refaire un dump de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartouches de jeu</a> ou de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">titres installés</a>.]]></string> | 350 | <string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour refaire un dump de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartouches de jeu</a> ou de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">titres installés</a>.]]></string> |
| @@ -277,6 +372,7 @@ | |||
| 277 | <string name="emulation_pause">Mettre en pause l\'émulation</string> | 372 | <string name="emulation_pause">Mettre en pause l\'émulation</string> |
| 278 | <string name="emulation_unpause">Reprendre l\'émulation</string> | 373 | <string name="emulation_unpause">Reprendre l\'émulation</string> |
| 279 | <string name="emulation_input_overlay">Options de l\'overlay</string> | 374 | <string name="emulation_input_overlay">Options de l\'overlay</string> |
| 375 | <string name="touchscreen">Écran tactile</string> | ||
| 280 | 376 | ||
| 281 | <string name="load_settings">Chargement des paramètres…</string> | 377 | <string name="load_settings">Chargement des paramètres…</string> |
| 282 | 378 | ||
| @@ -308,6 +404,7 @@ | |||
| 308 | 404 | ||
| 309 | <!-- Memory Sizes --> | 405 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Octet</string> | 406 | <string name="memory_byte">Octet</string> |
| 407 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">Ko</string> | 408 | <string name="memory_kilobyte">Ko</string> |
| 312 | <string name="memory_megabyte">Mo</string> | 409 | <string name="memory_megabyte">Mo</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 410 | <string name="memory_gigabyte">GB</string> |
| @@ -352,9 +449,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 449 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 450 | ||
| 354 | <!-- Screen Layouts --> | 451 | <!-- Screen Layouts --> |
| 452 | <string name="screen_layout_auto">Auto</string> | ||
| 453 | <string name="screen_layout_sensor_landscape">Paysage</string> | ||
| 355 | <string name="screen_layout_landscape">Paysage</string> | 454 | <string name="screen_layout_landscape">Paysage</string> |
| 455 | <string name="screen_layout_reverse_landscape">Paysage inversé</string> | ||
| 456 | <string name="screen_layout_sensor_portrait">Portrait</string> | ||
| 356 | <string name="screen_layout_portrait">Portrait</string> | 457 | <string name="screen_layout_portrait">Portrait</string> |
| 357 | <string name="screen_layout_auto">Auto</string> | 458 | <string name="screen_layout_reverse_portrait">Portrait inversé</string> |
| 358 | 459 | ||
| 359 | <!-- Aspect Ratios --> | 460 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">Par défaut (16:9)</string> | 461 | <string name="ratio_default">Par défaut (16:9)</string> |
| @@ -363,6 +464,10 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">Forcer le 16:10</string> | 464 | <string name="ratio_force_sixteen_ten">Forcer le 16:10</string> |
| 364 | <string name="ratio_stretch">Étirer à la fenêtre</string> | 465 | <string name="ratio_stretch">Étirer à la fenêtre</string> |
| 365 | 466 | ||
| 467 | <!-- CPU Backend --> | ||
| 468 | <string name="cpu_backend_dynarmic">Dynarmic (Lent)</string> | ||
| 469 | <string name="cpu_backend_nce">Exécution de code natif (NCE)</string> | ||
| 470 | |||
| 366 | <!-- CPU Accuracy --> | 471 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">Précis</string> | 472 | <string name="cpu_accuracy_accurate">Précis</string> |
| 368 | <string name="cpu_accuracy_unsafe">Risqué</string> | 473 | <string name="cpu_accuracy_unsafe">Risqué</string> |
| @@ -391,8 +496,15 @@ | |||
| 391 | <string name="theme_mode_dark">Sombre</string> | 496 | <string name="theme_mode_dark">Sombre</string> |
| 392 | 497 | ||
| 393 | <!-- Audio output engines --> | 498 | <!-- Audio output engines --> |
| 499 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 500 | <string name="cubeb">cubeb</string> |
| 395 | 501 | ||
| 502 | <!-- Anisotropic filtering options --> | ||
| 503 | <string name="multiplier_two">2x</string> | ||
| 504 | <string name="multiplier_four">4x</string> | ||
| 505 | <string name="multiplier_eight">8x</string> | ||
| 506 | <string name="multiplier_sixteen">16x</string> | ||
| 507 | |||
| 396 | <!-- Black backgrounds theme --> | 508 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">Arrière-plan noir</string> | 509 | <string name="use_black_backgrounds">Arrière-plan noir</string> |
| 398 | <string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string> | 510 | <string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string> |
diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml index 0af78a57c..41e4450c6 100644 --- a/src/android/app/src/main/res/values-he/strings.xml +++ b/src/android/app/src/main/res/values-he/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">×œ× × ×ž×¦×ו ×§×‘×¦×™× ×ו ×œ× ×‘×—×¨×” ספריית ×§×‘×¦×™× ×‘×™× ×ª×™×™×.</string> | 34 | <string name="empty_gamelist">×œ× × ×ž×¦×ו ×§×‘×¦×™× ×ו ×œ× ×‘×—×¨×” ספריית ×§×‘×¦×™× ×‘×™× ×ª×™×™×.</string> |
| 35 | <string name="search_and_filter_games">חפש ×•×¡× ×Ÿ משחקי×</string> | 35 | <string name="search_and_filter_games">חפש ×•×¡× ×Ÿ משחקי×</string> |
| 36 | <string name="select_games_folder">בחר תיקיית משחקי×</string> | 36 | <string name="select_games_folder">בחר תיקיית משחקי×</string> |
| 37 | <string name="manage_game_folders">× ×”×œ ×ת תיקיית המשחקי×</string> | ||
| 37 | <string name="select_games_folder_description">×פשר ל yuzu ל×כלס ×ת רשימת המשחקי×</string> | 38 | <string name="select_games_folder_description">×פשר ל yuzu ל×כלס ×ת רשימת המשחקי×</string> |
| 38 | <string name="add_games_warning">לדלג על בחירת תיקיית המשחקי×?</string> | 39 | <string name="add_games_warning">לדלג על בחירת תיקיית המשחקי×?</string> |
| 39 | <string name="add_games_warning_description">×ž×©×—×§×™× ×œ× ×™×•×¦×’×• ברשימת ×”×ž×©×—×§×™× ×× ×œ× ×‘×—×¨×” תיקיית משחקי×.</string> | 40 | <string name="add_games_warning_description">×ž×©×—×§×™× ×œ× ×™×•×¦×’×• ברשימת ×”×ž×©×—×§×™× ×× ×œ× ×‘×—×¨×” תיקיית משחקי×.</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">מפתחות ×”×¦×¤× ×” ×œ× ×—×•×§×™×™×</string> | 69 | <string name="invalid_keys_error">מפתחות ×”×¦×¤× ×” ×œ× ×—×•×§×™×™×</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">קבוץ ×©× ×‘×—×¨ מושחת ×ו ×œ× × ×›×•×Ÿ. בבקשה ×”×•×¦× ×ž×—×“×© ×ת המפתחות שלך.</string> | 71 | <string name="install_keys_failure_description">קבוץ ×©× ×‘×—×¨ מושחת ×ו ×œ× × ×›×•×Ÿ. בבקשה ×”×•×¦× ×ž×—×“×© ×ת המפתחות שלך.</string> |
| 72 | <string name="gpu_driver_manager">×ž× ×”×œ ×”×“×¨×™×™×‘×¨×™× ×©×œ המעבד הגרפי</string> | ||
| 71 | <string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string> | 73 | <string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string> |
| 72 | <string name="install_gpu_driver_description">התקן ×“×¨×™×™×‘×¨×™× ××—×¨×™× ×‘×©×‘×™×œ סיכוי ×œ×‘×™×¦×•×¢×™× ×ו דיוק ×’×‘×•×”×”×™× ×™×•×ª×¨</string> | 74 | <string name="install_gpu_driver_description">התקן ×“×¨×™×™×‘×¨×™× ××—×¨×™× ×‘×©×‘×™×œ סיכוי ×œ×‘×™×¦×•×¢×™× ×ו דיוק ×’×‘×•×”×”×™× ×™×•×ª×¨</string> |
| 73 | <string name="advanced_settings">הגדרות מתקדמות</string> | 75 | <string name="advanced_settings">הגדרות מתקדמות</string> |
| @@ -86,6 +88,7 @@ | |||
| 86 | <string name="manage_save_data">× ×”×œ מידע שמור</string> | 88 | <string name="manage_save_data">× ×”×œ מידע שמור</string> |
| 87 | <string name="manage_save_data_description">מידע שמור ×œ× × ×ž×¦×. בבקשה בחר/×™ ×ופציה מלמטה</string> | 89 | <string name="manage_save_data_description">מידע שמור ×œ× × ×ž×¦×. בבקשה בחר/×™ ×ופציה מלמטה</string> |
| 88 | <string name="import_export_saves_description">×™×‘× ×ו ×™×¦× ×§×‘×¦×™ שמירה</string> | 90 | <string name="import_export_saves_description">×™×‘× ×ו ×™×¦× ×§×‘×¦×™ שמירה</string> |
| 91 | <string name="save_files_exporting">×ž×™×™×¦× ×§×‘×¦×™ שמירה...</string> | ||
| 89 | <string name="save_file_imported_success">×™×•×‘× ×‘×”×¦×œ×—×”</string> | 92 | <string name="save_file_imported_success">×™×•×‘× ×‘×”×¦×œ×—×”</string> |
| 90 | <string name="save_file_invalid_zip_structure">×ž×‘× ×” ספריית השמירות ×œ× ×—×•×§×™</string> | 93 | <string name="save_file_invalid_zip_structure">×ž×‘× ×” ספריית השמירות ×œ× ×—×•×§×™</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">התת תיקייה הר××©×•× ×” חייב להיות ×” title ID של המשחק</string> | 94 | <string name="save_file_invalid_zip_structure_description">התת תיקייה הר××©×•× ×” חייב להיות ×” title ID של המשחק</string> |
| @@ -118,6 +121,28 @@ | |||
| 118 | <string name="manage_yuzu_data_description">יב×/×™×¦× firmware, keys, מידע של משתמש ועוד!</string> | 121 | <string name="manage_yuzu_data_description">יב×/×™×¦× firmware, keys, מידע של משתמש ועוד!</string> |
| 119 | <string name="share_save_file">שתף קובץ שמירה</string> | 122 | <string name="share_save_file">שתף קובץ שמירה</string> |
| 120 | <string name="export_save_failed">× ×›×©×œ ×‘×™×™×¦×•× ×©×ž×™×¨×”</string> | 123 | <string name="export_save_failed">× ×›×©×œ ×‘×™×™×¦×•× ×©×ž×™×¨×”</string> |
| 124 | <string name="game_folders">תיקיית משחקי×</string> | ||
| 125 | <string name="deep_scan">סריקה עמוקה</string> | ||
| 126 | <string name="add_game_folder">הוסף תיקיית משחקי×</string> | ||
| 127 | <string name="folder_already_added">התיקייה הזו × ×•×¡×¤×” כבר!</string> | ||
| 128 | <string name="game_folder_properties">מ××¤×™×™× ×™ תיקיית משחקי×</string> | ||
| 129 | <!-- Applet launcher strings --> | ||
| 130 | <string name="applets">משגר Applet</string> | ||
| 131 | <string name="applets_description">מערכת שיגור Applet משתמשת ×‘×ª×•×›× ×” ×”×ž×•×ª×§× ×ª</string> | ||
| 132 | <string name="applets_error_firmware">×” Firmware ×œ× ×ž×•×ª×§×Ÿ</string> | ||
| 133 | <string name="applets_error_applet">Applet ×œ× ×–×ž×™×Ÿ</string> | ||
| 134 | <string name="applets_error_description"><![CDATA[בבקשה ×•×•×“× ×©×§×‘×¦×™ ×” - <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a>ו <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a>שלך ×ž×•×ª×§× ×™× ×•× ×¡×” שוב.]]></string> | ||
| 135 | <string name="album_applet">×לבו×</string> | ||
| 136 | <string name="album_applet_description">צפה ×‘×ª×ž×•× ×•×ª השמורות בתיקיית צילומי המסך של המשתמש בעזרת מציג ×”×ª×ž×•× ×•×ª של המערכת</string> | ||
| 137 | <string name="mii_edit_applet">עורך Mii</string> | ||
| 138 | <string name="mii_edit_applet_description">צפה וערוך דמויות Mii בעזרת עורך המערכת</string> | ||
| 139 | <string name="cabinet_applet">×רון</string> | ||
| 140 | <string name="cabinet_applet_description">ערוך ומחק מידע השמור על ה amiibo</string> | ||
| 141 | <string name="cabinet_launcher">משגר ××¨×•× ×•×ª</string> | ||
| 142 | <string name="cabinet_nickname_and_owner">×›×™× ×•×™ והגדרות בעלי×</string> | ||
| 143 | <string name="cabinet_game_data_eraser">מחק של × ×ª×•× ×™ משחק</string> | ||
| 144 | <string name="cabinet_restorer">שחזר</string> | ||
| 145 | <string name="cabinet_formatter">×‘×•× ×” ×ª×‘× ×™×•×ª</string> | ||
| 121 | 146 | ||
| 122 | <!-- About screen strings --> | 147 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia ×œ× ×מיתית</string> | 148 | <string name="gaia_is_not_real">Gaia ×œ× ×מיתית</string> |
| @@ -161,6 +186,7 @@ | |||
| 161 | <string name="frame_limit_enable_description">מגביל ×ת מהירות ×”×מולציה ל×חוז מהירות המבוקש מהמהירות הרגילה.</string> | 186 | <string name="frame_limit_enable_description">מגביל ×ת מהירות ×”×מולציה ל×חוז מהירות המבוקש מהמהירות הרגילה.</string> |
| 162 | <string name="frame_limit_slider">הגבל ×ת ×חוז המהירות</string> | 187 | <string name="frame_limit_slider">הגבל ×ת ×חוז המהירות</string> |
| 163 | <string name="frame_limit_slider_description">מדייק ×ת ×חוז מהירות ×”×מולציה. 100% ×–×” מהירות רגילה. ×¢×¨×›×™× ×’×“×•×œ×™× ×ו ×§×˜× ×™× ×™×יצו ×ו ×™×טו ×ת מהירות ×”×מולציה.</string> | 188 | <string name="frame_limit_slider_description">מדייק ×ת ×חוז מהירות ×”×מולציה. 100% ×–×” מהירות רגילה. ×¢×¨×›×™× ×’×“×•×œ×™× ×ו ×§×˜× ×™× ×™×יצו ×ו ×™×טו ×ת מהירות ×”×מולציה.</string> |
| 189 | <string name="cpu_backend">קצה ×”×חורי של המעבד</string> | ||
| 164 | <string name="cpu_accuracy">דיוק המעבד</string> | 190 | <string name="cpu_accuracy">דיוק המעבד</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 191 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 192 | ||
| @@ -185,23 +211,38 @@ | |||
| 185 | <string name="renderer_anti_aliasing">שיטת Anti-aliasing</string> | 211 | <string name="renderer_anti_aliasing">שיטת Anti-aliasing</string> |
| 186 | <string name="renderer_force_max_clock">החזק מהירות שעון מקסימלית (רק ל Adreno)</string> | 212 | <string name="renderer_force_max_clock">החזק מהירות שעון מקסימלית (רק ל Adreno)</string> |
| 187 | <string name="renderer_force_max_clock_description">מכריח לדחוף ×ת מהירויות המעבד הגרפי ×œ×ž×§×¡×™×ž×•× (הגבלות ×—×•× ×™×ž×©×™×›×• לתפקד).</string> | 213 | <string name="renderer_force_max_clock_description">מכריח לדחוף ×ת מהירויות המעבד הגרפי ×œ×ž×§×¡×™×ž×•× (הגבלות ×—×•× ×™×ž×©×™×›×• לתפקד).</string> |
| 214 | <string name="renderer_asynchronous_shaders">השתמש ×‘×©×™×™×“×¨×™× ××¡×™× ×›×¨×•× ×™×</string> | ||
| 215 | <string name="renderer_asynchronous_shaders_description">מקמפל ×©×™×™×“×¨×™× ×‘×¦×•×¨×” ××¡× ×›×¨×•× ×™×ª, מפחית תקיעות ×ך עלול ×œ×’×¨×•× ×œ×‘×¢×™×•×ª גרפיות.</string> | ||
| 216 | <string name="renderer_reactive_flushing">השתמש בהבהוב תגובתי</string> | ||
| 188 | <string name="renderer_reactive_flushing_description">משפר ×ת הדיוק של ×”×מולציה ×‘×ž×©×—×§×™× ×ž×¡×•×™×™×ž×™× ×‘×ž×—×™×¨ של ביצועי×.</string> | 217 | <string name="renderer_reactive_flushing_description">משפר ×ת הדיוק של ×”×מולציה ×‘×ž×©×—×§×™× ×ž×¡×•×™×™×ž×™× ×‘×ž×—×™×¨ של ביצועי×.</string> |
| 218 | <string name="use_disk_shader_cache">מטמון השיידר של הדיסק</string> | ||
| 219 | <string name="use_disk_shader_cache_description">מפחית בתקיעות על ידי ×חסון מקומי ×•×˜×¢×™× ×” של ×©×™×™×“×¨×™× ×”× ×•×¦×¨×™×. </string> | ||
| 189 | <!-- Debug settings strings --> | 220 | <!-- Debug settings strings --> |
| 190 | <string name="cpu">מעבד</string> | 221 | <string name="cpu">מעבד</string> |
| 222 | <string name="cpu_debug_mode">דיב××’×™× ×’ למעבד</string> | ||
| 191 | <string name="cpu_debug_mode_description">×ž×›× ×™×¡ ×ת המעבד למצב דיב××’ ×יטי</string> | 223 | <string name="cpu_debug_mode_description">×ž×›× ×™×¡ ×ת המעבד למצב דיב××’ ×יטי</string> |
| 192 | <string name="gpu">מעבד גרפי</string> | 224 | <string name="gpu">מעבד גרפי</string> |
| 225 | <string name="renderer_api">ממשק ×ª×•×›× ×”</string> | ||
| 226 | <string name="renderer_debug">דיב××’×™× ×’ בגרפיקה</string> | ||
| 227 | <string name="renderer_debug_description">קובע ×ת ממשק ×”×ª×•×›× ×” של הגרפיקות למצב דיב××’×™× ×’ ×יטי.</string> | ||
| 228 | <string name="fastmem">Fastmem</string> | ||
| 229 | |||
| 193 | <!-- Audio settings strings --> | 230 | <!-- Audio settings strings --> |
| 194 | <string name="audio_output_engine">×ž× ×•×¢ פלט</string> | 231 | <string name="audio_output_engine">×ž× ×•×¢ פלט</string> |
| 195 | <string name="audio_volume">עוצמת שמע</string> | 232 | <string name="audio_volume">עוצמת שמע</string> |
| 233 | <string name="audio_volume_description">מציין ×ת עוצמת ×”×ודיו שיוצ×.</string> | ||
| 234 | |||
| 196 | <!-- Miscellaneous --> | 235 | <!-- Miscellaneous --> |
| 197 | <string name="slider_default">ברירת מחדל</string> | 236 | <string name="slider_default">ברירת מחדל</string> |
| 198 | <string name="ini_saved">הגדרות שמורות</string> | 237 | <string name="ini_saved">הגדרות שמורות</string> |
| 199 | <string name="gameid_saved">הגדרות שמורות עבור %1$s</string> | 238 | <string name="gameid_saved">הגדרות שמורות עבור %1$s</string> |
| 200 | <string name="error_saving">תקלה בשמירת %1$s.ini: %2$s</string> | 239 | <string name="error_saving">תקלה בשמירת %1$s.ini: %2$s</string> |
| 240 | <string name="unimplemented_menu">תפריט ×©×œ× ×™×•×©×</string> | ||
| 201 | <string name="loading">טוען...</string> | 241 | <string name="loading">טוען...</string> |
| 202 | <string name="shutting_down">כיבוי...</string> | 242 | <string name="shutting_down">כיבוי...</string> |
| 203 | <string name="reset_setting_confirmation">×תה ×ž×¢×•× ×™×™×Ÿ ל×פס ×ת ההגדרה הזו חזרה לברירת המחדל?</string> | 243 | <string name="reset_setting_confirmation">×תה ×ž×¢×•× ×™×™×Ÿ ל×פס ×ת ההגדרה הזו חזרה לברירת המחדל?</string> |
| 204 | <string name="reset_to_default">×פס לברירת המחדל</string> | 244 | <string name="reset_to_default">×פס לברירת המחדל</string> |
| 245 | <string name="reset_to_default_description">מ×פס ×ת כל ההגדרות המתקדמות.</string> | ||
| 205 | <string name="reset_all_settings">ל×פס ×ת כל ההגדרות?</string> | 246 | <string name="reset_all_settings">ל×פס ×ת כל ההגדרות?</string> |
| 206 | <string name="reset_all_settings_description">כל ההגדרות המתקדמות ×™×ופסו לברירת המחדל. ×œ× × ×™×ª×Ÿ לבטל פעולה זו.</string> | 247 | <string name="reset_all_settings_description">כל ההגדרות המתקדמות ×™×ופסו לברירת המחדל. ×œ× × ×™×ª×Ÿ לבטל פעולה זו.</string> |
| 207 | <string name="settings_reset">×פס הגדרות</string> | 248 | <string name="settings_reset">×פס הגדרות</string> |
| @@ -209,19 +250,26 @@ | |||
| 209 | <string name="learn_more">למד עוד</string> | 250 | <string name="learn_more">למד עוד</string> |
| 210 | <string name="auto">×וטומטי</string> | 251 | <string name="auto">×וטומטי</string> |
| 211 | <string name="submit">שלח</string> | 252 | <string name="submit">שלח</string> |
| 253 | <string name="string_null">ריק</string> | ||
| 212 | <string name="string_import">ייבו×</string> | 254 | <string name="string_import">ייבו×</string> |
| 213 | <string name="export">ייצו×</string> | 255 | <string name="export">ייצו×</string> |
| 214 | <string name="export_failed">×™×™×¦×•× × ×›×©×œ</string> | 256 | <string name="export_failed">×™×™×¦×•× × ×›×©×œ</string> |
| 215 | <string name="import_failed">×™×™×‘×•× × ×›×©×œ</string> | 257 | <string name="import_failed">×™×™×‘×•× × ×›×©×œ</string> |
| 216 | <string name="cancelling">מבטל</string> | 258 | <string name="cancelling">מבטל</string> |
| 217 | 259 | <string name="install">התקן</string> | |
| 260 | <string name="delete">מחק</string> | ||
| 261 | <string name="edit">ערוך</string> | ||
| 262 | <string name="export_success">×™×•×¦× ×‘×”×¦×œ×—×”</string> | ||
| 263 | <string name="start">התחלה</string> | ||
| 264 | <string name="clear">× ×§×”</string> | ||
| 218 | <!-- GPU driver installation --> | 265 | <!-- GPU driver installation --> |
| 219 | <string name="select_gpu_driver">בחר דרייבר למעבד הגרפי</string> | 266 | <string name="select_gpu_driver">בחר דרייבר למעבד הגרפי</string> |
| 220 | <string name="select_gpu_driver_title">×תה ×ž×¢×•× ×™×™×Ÿ להחליף ×ת הדרייבר של המעבד הגרפי שלך?</string> | 267 | <string name="select_gpu_driver_title">×תה ×ž×¢×•× ×™×™×Ÿ להחליף ×ת הדרייבר של המעבד הגרפי שלך?</string> |
| 221 | <string name="select_gpu_driver_install">התקן</string> | 268 | <string name="select_gpu_driver_install">התקן</string> |
| 222 | <string name="select_gpu_driver_default">ברירת מחדל</string> | 269 | <string name="select_gpu_driver_default">ברירת מחדל</string> |
| 223 | <string name="select_gpu_driver_use_default">משתמש בדרייבר ברירת המחדל של המעבד הגרפי</string> | 270 | <string name="select_gpu_driver_use_default">משתמש בדרייבר ברירת המחדל של המעבד הגרפי</string> |
| 224 | <string name="select_gpu_driver_error">דרייבר ×œ× ×—×•×§×™ × ×‘×—×¨, משתמש בברירת המחדל של המערכת!</string> | 271 | <string name="select_gpu_driver_error">× ×‘×—×¨ דרייבר ×œ× ×—×•×§×™</string> |
| 272 | <string name="driver_already_installed">הדרייבר כבר מותקן</string> | ||
| 225 | <string name="system_gpu_driver">דרייבר של המעבד הגרפי של המערכת</string> | 273 | <string name="system_gpu_driver">דרייבר של המעבד הגרפי של המערכת</string> |
| 226 | <string name="installing_driver">מתקין דרייבר...</string> | 274 | <string name="installing_driver">מתקין דרייבר...</string> |
| 227 | 275 | ||
| @@ -229,11 +277,27 @@ | |||
| 229 | <string name="preferences_settings">הגדרות</string> | 277 | <string name="preferences_settings">הגדרות</string> |
| 230 | <string name="preferences_general">כללי</string> | 278 | <string name="preferences_general">כללי</string> |
| 231 | <string name="preferences_system">מערכת</string> | 279 | <string name="preferences_system">מערכת</string> |
| 280 | <string name="preferences_system_description">מצב מעוגן, ×יזור, שפה</string> | ||
| 232 | <string name="preferences_graphics">גרפיקה</string> | 281 | <string name="preferences_graphics">גרפיקה</string> |
| 282 | <string name="preferences_graphics_description">רמת דיוק, רזולוציה, מטמון שיידרי×</string> | ||
| 233 | <string name="preferences_audio">שמע</string> | 283 | <string name="preferences_audio">שמע</string> |
| 284 | <string name="preferences_audio_description">×ž× ×•×¢ פלט, עוצמת שמע</string> | ||
| 234 | <string name="preferences_theme">צבע ×•× ×•×©×</string> | 285 | <string name="preferences_theme">צבע ×•× ×•×©×</string> |
| 286 | <string name="preferences_debug">דיב××’</string> | ||
| 287 | <string name="preferences_debug_description">דיב××’×™× ×’ עבור מעבד/מעבד גרפי, ממשק ×ª×•×›× ×” עבור הגרפיקות, fastmem</string> | ||
| 288 | |||
| 289 | <!-- Game properties --> | ||
| 290 | <string name="info">מידע</string> | ||
| 291 | <string name="path">דרך</string> | ||
| 292 | <string name="developer">מפתח</string> | ||
| 293 | <string name="version">גרסה</string> | ||
| 294 | <string name="add_ons">תוספי×</string> | ||
| 235 | <!-- ROM loading errors --> | 295 | <!-- ROM loading errors --> |
| 236 | <string name="loader_error_encrypted">המשחק שלך מוצפן</string> | 296 | <string name="loader_error_encrypted">המשחק שלך מוצפן</string> |
| 297 | <string name="loader_error_encrypted_roms_description"><![CDATA[×× × ×¢×§×•×‘ ×חרי ×”×ž×“×¨×™×›×™× ×›×“×™ לבצע redump של <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">כרטיסי המשחק</a>×ו <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">הכותרות ×”×ž×•×ª×§× ×•×ª</a> שלך.]]></string> | ||
| 298 | <string name="loader_error_encrypted_keys_description"><![CDATA[×× × ×•×•×“× ×©×§×•×‘×¥ ×”-<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> מותקן כך ×©× ×™×ª×Ÿ ×™×”×™×” ×œ×¤×¢× ×— משחקי×.]]></string> | ||
| 299 | <string name="loader_error_video_core">התרחשה בעיה ב×תחול של ליבת הוויד×ו</string> | ||
| 300 | <string name="loader_error_video_core_description">×–×” בדרך כלל × ×’×¨× ×¢×œ ידי דרייבר ×œ× ×ž×ª××™× ×¢×‘×•×¨ המעבד הגרפי. ×”×ª×§× ×ª דרייבר ×שר מת××™× ×œ×ž×¢×‘×“ הגרפי יכול לפתור ×ת הבעיה הזו.</string> | ||
| 237 | <string name="loader_error_invalid_format">×ין ×פשרות לטעון ×ת המשחק</string> | 301 | <string name="loader_error_invalid_format">×ין ×פשרות לטעון ×ת המשחק</string> |
| 238 | <string name="loader_error_file_not_found">קובץ המשחק ×œ× ×§×™×™×</string> | 302 | <string name="loader_error_file_not_found">קובץ המשחק ×œ× ×§×™×™×</string> |
| 239 | 303 | ||
| @@ -241,10 +305,22 @@ | |||
| 241 | <string name="emulation_exit">×¦× ×ž×”×מולציה</string> | 305 | <string name="emulation_exit">×¦× ×ž×”×מולציה</string> |
| 242 | <string name="emulation_done">סיו×</string> | 306 | <string name="emulation_done">סיו×</string> |
| 243 | <string name="emulation_fps_counter">סופר FPS</string> | 307 | <string name="emulation_fps_counter">סופר FPS</string> |
| 308 | <string name="emulation_toggle_controls">החלפת בקרי×</string> | ||
| 309 | <string name="emulation_rel_stick_center">מרכז ג׳ויסטיק יחסי</string> | ||
| 310 | <string name="emulation_dpad_slide">החלקת D-pad</string> | ||
| 311 | <string name="emulation_haptics">רטט מגע</string> | ||
| 312 | <string name="emulation_show_overlay">הצג ×ת שכבת-העל</string> | ||
| 313 | <string name="emulation_toggle_all">החלף הכל</string> | ||
| 314 | <string name="emulation_control_adjust">הת×× ×ת שכבת-העל</string> | ||
| 244 | <string name="emulation_control_scale">×§× ×” מידה</string> | 315 | <string name="emulation_control_scale">×§× ×” מידה</string> |
| 245 | <string name="emulation_control_opacity">שקיפות</string> | 316 | <string name="emulation_control_opacity">שקיפות</string> |
| 317 | <string name="emulation_touch_overlay_reset">×פס ×ת שכבת-העל</string> | ||
| 318 | <string name="emulation_touch_overlay_edit">ערוך שכבת-על</string> | ||
| 246 | <string name="emulation_pause">עצור ×מולציה</string> | 319 | <string name="emulation_pause">עצור ×מולציה</string> |
| 247 | <string name="emulation_unpause">המשך ×מולציה</string> | 320 | <string name="emulation_unpause">המשך ×מולציה</string> |
| 321 | <string name="emulation_input_overlay">×ופציות עבור שכבת-על</string> | ||
| 322 | <string name="touchscreen">מסך מגע</string> | ||
| 323 | |||
| 248 | <string name="load_settings">טוען הגדרות...</string> | 324 | <string name="load_settings">טוען הגדרות...</string> |
| 249 | 325 | ||
| 250 | <!-- Software keyboard --> | 326 | <!-- Software keyboard --> |
| @@ -258,6 +334,8 @@ | |||
| 258 | <string name="system_archive_general">×רכיון מערכת</string> | 334 | <string name="system_archive_general">×רכיון מערכת</string> |
| 259 | <string name="save_load_error">בעיית שמירה/×˜×¢×™× ×”</string> | 335 | <string name="save_load_error">בעיית שמירה/×˜×¢×™× ×”</string> |
| 260 | <string name="fatal_error">שגי××” חמורה</string> | 336 | <string name="fatal_error">שגי××” חמורה</string> |
| 337 | <string name="fatal_error_message">שגי××” חמורה התרחשה. בדוק ×ת היומן לפרטי×./nהמשך הסימולציה עשוי ×œ×’×¨×•× ×œ×§×¨×™×¡×•×ª ולב××’×™×.</string> | ||
| 338 | <string name="performance_warning">כיבוי הגדרה זו ישפיע משמעותית על ביצועי הסימולציה! לחוויה הטובה ביותר, מומלץ להש×יר ×ת הגדרה זו מופעלת.</string> | ||
| 261 | <string name="device_memory_inadequate">RAM המכשיר: %1$s/nמומלץ: %2$s</string> | 339 | <string name="device_memory_inadequate">RAM המכשיר: %1$s/nמומלץ: %2$s</string> |
| 262 | <string name="memory_formatted">%1$s%2$s</string> | 340 | <string name="memory_formatted">%1$s%2$s</string> |
| 263 | <string name="no_game_present">×ין משחק ×©× ×™×ª×Ÿ להריץ!</string> | 341 | <string name="no_game_present">×ין משחק ×©× ×™×ª×Ÿ להריץ!</string> |
| @@ -273,6 +351,7 @@ | |||
| 273 | 351 | ||
| 274 | <!-- Memory Sizes --> | 352 | <!-- Memory Sizes --> |
| 275 | <string name="memory_byte">בייט</string> | 353 | <string name="memory_byte">בייט</string> |
| 354 | <string name="memory_byte_shorthand">B</string> | ||
| 276 | <string name="memory_kilobyte">KB</string> | 355 | <string name="memory_kilobyte">KB</string> |
| 277 | <string name="memory_megabyte">MB</string> | 356 | <string name="memory_megabyte">MB</string> |
| 278 | <string name="memory_gigabyte">GB</string> | 357 | <string name="memory_gigabyte">GB</string> |
| @@ -297,12 +376,17 @@ | |||
| 297 | <string name="resolution_three">3X (2160p/3240p) (×יטי)</string> | 376 | <string name="resolution_three">3X (2160p/3240p) (×יטי)</string> |
| 298 | <string name="resolution_four">4X (2880p/4320p) (×יטי)</string> | 377 | <string name="resolution_four">4X (2880p/4320p) (×יטי)</string> |
| 299 | 378 | ||
| 379 | <!-- Renderer VSync --> | ||
| 380 | <string name="renderer_vsync_immediate">מיידי (כבוי)</string> | ||
| 300 | <string name="renderer_vsync_mailbox">תיבת דו×ר</string> | 381 | <string name="renderer_vsync_mailbox">תיבת דו×ר</string> |
| 301 | <string name="renderer_vsync_fifo">FIFO (On)</string> | 382 | <string name="renderer_vsync_fifo">FIFO (On)</string> |
| 302 | <string name="renderer_vsync_fifo_relaxed">FIFO × ×™× ×•×—</string> | 383 | <string name="renderer_vsync_fifo_relaxed">FIFO × ×™× ×•×—</string> |
| 303 | 384 | ||
| 304 | <!-- Scaling Filters --> | 385 | <!-- Scaling Filters --> |
| 305 | <string name="scaling_filter_nearest_neighbor">השכן הקרוב ביותר</string> | 386 | <string name="scaling_filter_nearest_neighbor">השכן הקרוב ביותר</string> |
| 387 | <string name="scaling_filter_bilinear">×‘×™×œ×™× ×™×רי</string> | ||
| 388 | <string name="scaling_filter_bicubic">Bicubic</string> | ||
| 389 | <string name="scaling_filter_gaussian">Gaussian</string> | ||
| 306 | <string name="scaling_filter_scale_force">ScaleForce</string> | 390 | <string name="scaling_filter_scale_force">ScaleForce</string> |
| 307 | <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string> | 391 | <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string> |
| 308 | 392 | ||
| @@ -312,10 +396,9 @@ | |||
| 312 | <string name="anti_aliasing_smaa">SMAA</string> | 396 | <string name="anti_aliasing_smaa">SMAA</string> |
| 313 | 397 | ||
| 314 | <!-- Screen Layouts --> | 398 | <!-- Screen Layouts --> |
| 399 | <string name="screen_layout_auto">×וטומטי</string> | ||
| 315 | <string name="screen_layout_landscape">לרוחב</string> | 400 | <string name="screen_layout_landscape">לרוחב</string> |
| 316 | <string name="screen_layout_portrait">ל×ורך</string> | 401 | <string name="screen_layout_portrait">ל×ורך</string> |
| 317 | <string name="screen_layout_auto">×וטומטי</string> | ||
| 318 | |||
| 319 | <!-- Aspect Ratios --> | 402 | <!-- Aspect Ratios --> |
| 320 | <string name="ratio_default">ברירת מחדל (16:9)</string> | 403 | <string name="ratio_default">ברירת מחדל (16:9)</string> |
| 321 | <string name="ratio_force_four_three">הכרח 4:3</string> | 404 | <string name="ratio_force_four_three">הכרח 4:3</string> |
| @@ -323,6 +406,10 @@ | |||
| 323 | <string name="ratio_force_sixteen_ten">הכרח 16:10</string> | 406 | <string name="ratio_force_sixteen_ten">הכרח 16:10</string> |
| 324 | <string name="ratio_stretch">הרחב לגודל המסך</string> | 407 | <string name="ratio_stretch">הרחב לגודל המסך</string> |
| 325 | 408 | ||
| 409 | <!-- CPU Backend --> | ||
| 410 | <string name="cpu_backend_dynarmic">×“×™× ×ž×™ (×יטי)</string> | ||
| 411 | <string name="cpu_backend_nce">ביצוע קוד מקורי (NCE)</string> | ||
| 412 | |||
| 326 | <!-- CPU Accuracy --> | 413 | <!-- CPU Accuracy --> |
| 327 | <string name="cpu_accuracy_accurate">מדויק</string> | 414 | <string name="cpu_accuracy_accurate">מדויק</string> |
| 328 | <string name="cpu_accuracy_unsafe">×œ× ×‘×˜×•×—</string> | 415 | <string name="cpu_accuracy_unsafe">×œ× ×‘×˜×•×—</string> |
| @@ -335,6 +422,10 @@ | |||
| 335 | <string name="gamepad_home">בית</string> | 422 | <string name="gamepad_home">בית</string> |
| 336 | <string name="gamepad_screenshot">×¦×™×œ×•× ×ž×¡×š</string> | 423 | <string name="gamepad_screenshot">×¦×™×œ×•× ×ž×¡×š</string> |
| 337 | 424 | ||
| 425 | <!-- Disk shader cache --> | ||
| 426 | <string name="preparing_shaders">מכין שיידרי×</string> | ||
| 427 | <string name="building_shaders">×‘×•× ×” שיידרי×</string> | ||
| 428 | |||
| 338 | <!-- Theme options --> | 429 | <!-- Theme options --> |
| 339 | <string name="change_app_theme">×©× ×” ×ת × ×•×©× ×”×פליקצייה</string> | 430 | <string name="change_app_theme">×©× ×” ×ת × ×•×©× ×”×פליקצייה</string> |
| 340 | <string name="theme_default">ברירת מחדל</string> | 431 | <string name="theme_default">ברירת מחדל</string> |
| @@ -346,9 +437,14 @@ | |||
| 346 | <string name="theme_mode_light">בהיר</string> | 437 | <string name="theme_mode_light">בהיר</string> |
| 347 | <string name="theme_mode_dark">×›×”×”</string> | 438 | <string name="theme_mode_dark">×›×”×”</string> |
| 348 | 439 | ||
| 349 | <!-- Audio output engines --> | ||
| 350 | <string name="cubeb">cubeb</string> | 440 | <string name="cubeb">cubeb</string> |
| 351 | 441 | ||
| 442 | <!-- Anisotropic filtering options --> | ||
| 443 | <string name="multiplier_two">2x</string> | ||
| 444 | <string name="multiplier_four">4x</string> | ||
| 445 | <string name="multiplier_eight">8x</string> | ||
| 446 | <string name="multiplier_sixteen">16x</string> | ||
| 447 | |||
| 352 | <!-- Black backgrounds theme --> | 448 | <!-- Black backgrounds theme --> |
| 353 | <string name="use_black_backgrounds">×¨×§×¢×™× ×©×—×•×¨×™×</string> | 449 | <string name="use_black_backgrounds">×¨×§×¢×™× ×©×—×•×¨×™×</string> |
| 354 | <string name="use_black_backgrounds_description">×›×©×ž×ª×©×ž×©×™× ×‘×ž×¦×‘ ×›×”×”, ×©× ×¨×§×¢×™× ×©×—×•×¨×™×.</string> | 450 | <string name="use_black_backgrounds_description">×›×©×ž×ª×©×ž×©×™× ×‘×ž×¦×‘ ×›×”×”, ×©× ×¨×§×¢×™× ×©×—×•×¨×™×.</string> |
diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml index 6563ba288..554da0816 100644 --- a/src/android/app/src/main/res/values-hu/strings.xml +++ b/src/android/app/src/main/res/values-hu/strings.xml | |||
| @@ -35,6 +35,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 35 | <string name="empty_gamelist">Nem található fájl, vagy még nincs kiválasztva könyvtár.</string> | 35 | <string name="empty_gamelist">Nem található fájl, vagy még nincs kiválasztva könyvtár.</string> |
| 36 | <string name="search_and_filter_games">Játékok keresése és szűrése</string> | 36 | <string name="search_and_filter_games">Játékok keresése és szűrése</string> |
| 37 | <string name="select_games_folder">Játékmappa kiválasztása</string> | 37 | <string name="select_games_folder">Játékmappa kiválasztása</string> |
| 38 | <string name="manage_game_folders">Játékmappák kezelése</string> | ||
| 38 | <string name="add_games_warning">Kihagyod a játékok mappa kiválasztását?</string> | 39 | <string name="add_games_warning">Kihagyod a játékok mappa kiválasztását?</string> |
| 39 | <string name="add_games_warning_description">A játékok nem jelennek meg a Játékok listában, ha egy mappa nincs kijelölve.</string> | 40 | <string name="add_games_warning_description">A játékok nem jelennek meg a Játékok listában, ha egy mappa nincs kijelölve.</string> |
| 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 41 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| @@ -68,6 +69,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 68 | <string name="invalid_keys_error">Érvénytelen titkosÃtókulcsok</string> | 69 | <string name="invalid_keys_error">Érvénytelen titkosÃtókulcsok</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">A kiválasztott fájl helytelen, vagy sérült. ÃllÃts össze egy új kulcsot.</string> | 71 | <string name="install_keys_failure_description">A kiválasztott fájl helytelen, vagy sérült. ÃllÃts össze egy új kulcsot.</string> |
| 72 | <string name="gpu_driver_manager">GPU illesztőprogram-kezelő</string> | ||
| 71 | <string name="install_gpu_driver">GPU illesztÅ‘program telepÃtése</string> | 73 | <string name="install_gpu_driver">GPU illesztÅ‘program telepÃtése</string> |
| 72 | <string name="install_gpu_driver_description">AlternatÃv illesztÅ‘programok telepÃtése az esetlegesen elérhetÅ‘ teljesÃtmény és pontosság érdekében</string> | 74 | <string name="install_gpu_driver_description">AlternatÃv illesztÅ‘programok telepÃtése az esetlegesen elérhetÅ‘ teljesÃtmény és pontosság érdekében</string> |
| 73 | <string name="advanced_settings">Haladó beállÃtások</string> | 75 | <string name="advanced_settings">Haladó beállÃtások</string> |
| @@ -84,7 +86,11 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 84 | <string name="notification_no_directory_link_description">Kérjük, manuálisan keresd meg a felhasználói mappát a fájlkezelő oldalsó paneljével.</string> | 86 | <string name="notification_no_directory_link_description">Kérjük, manuálisan keresd meg a felhasználói mappát a fájlkezelő oldalsó paneljével.</string> |
| 85 | <string name="manage_save_data">Mentésadatok kezelése</string> | 87 | <string name="manage_save_data">Mentésadatok kezelése</string> |
| 86 | <string name="manage_save_data_description">Mentés található. Kérjük, válassz egyet az alábbi opciók közül.</string> | 88 | <string name="manage_save_data_description">Mentés található. Kérjük, válassz egyet az alábbi opciók közül.</string> |
| 89 | <string name="import_save_warning">Mentési fájlok importálása</string> | ||
| 90 | <string name="import_save_warning_description">Ezzel felülÃrod a fájlban lévÅ‘ mentett adatokat. Biztosan szeretnéd folytatni?</string> | ||
| 87 | <string name="import_export_saves_description">Mentési fájlok importálás vagy exportálása</string> | 91 | <string name="import_export_saves_description">Mentési fájlok importálás vagy exportálása</string> |
| 92 | <string name="save_files_importing">Mentési fájlok importálása...</string> | ||
| 93 | <string name="save_files_exporting">Mentési fájlok exportálása...</string> | ||
| 88 | <string name="save_file_imported_success">Sikeresen importálva</string> | 94 | <string name="save_file_imported_success">Sikeresen importálva</string> |
| 89 | <string name="save_file_invalid_zip_structure">Érvénytelen mentési könyvtárstruktúra</string> | 95 | <string name="save_file_invalid_zip_structure">Érvénytelen mentési könyvtárstruktúra</string> |
| 90 | <string name="save_file_invalid_zip_structure_description">Az elsÅ‘ almappa neve a játék azonosÃtója kell, hogy legyen.</string> | 96 | <string name="save_file_invalid_zip_structure_description">Az elsÅ‘ almappa neve a játék azonosÃtója kell, hogy legyen.</string> |
| @@ -117,6 +123,38 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 117 | <string name="manage_yuzu_data_description">Firmware, kulcsok, felhasználói adatok és egyebek importálása/exportálása</string> | 123 | <string name="manage_yuzu_data_description">Firmware, kulcsok, felhasználói adatok és egyebek importálása/exportálása</string> |
| 118 | <string name="share_save_file">Mentési fájl megosztása</string> | 124 | <string name="share_save_file">Mentési fájl megosztása</string> |
| 119 | <string name="export_save_failed">A mentés exportálása sikertelen</string> | 125 | <string name="export_save_failed">A mentés exportálása sikertelen</string> |
| 126 | <string name="game_folders">Játékmappák</string> | ||
| 127 | <string name="deep_scan">Mély szkennelés</string> | ||
| 128 | <string name="add_game_folder">Játékmappa hozzáadása</string> | ||
| 129 | <string name="folder_already_added">Ez a mappa már hozzá lett adva!</string> | ||
| 130 | <string name="game_folder_properties">Játékmappa tulajdonságok</string> | ||
| 131 | <plurals name="saves_import_failed"> | ||
| 132 | <item quantity="one">%dmentés importálása sikertelen</item> | ||
| 133 | <item quantity="other">%dmentés importálása sikertelen</item> | ||
| 134 | </plurals> | ||
| 135 | <plurals name="saves_import_success"> | ||
| 136 | <item quantity="one">%dmentés sikeresen importálva</item> | ||
| 137 | <item quantity="other">%dmentés sikeresen importálva</item> | ||
| 138 | </plurals> | ||
| 139 | <string name="no_save_data_found">Nem található mentett adat</string> | ||
| 140 | |||
| 141 | <!-- Applet launcher strings --> | ||
| 142 | <string name="applets">Applet indÃtó</string> | ||
| 143 | <string name="applets_description">Rendszer appletek indÃtása a telepÃtett firmware-rel</string> | ||
| 144 | <string name="applets_error_firmware">Firmware nincs telepÃtve</string> | ||
| 145 | <string name="applets_error_applet">Applet nem elérhető</string> | ||
| 146 | <string name="applets_error_description"><![CDATA[Kérjük, gyÅ‘zÅ‘dj meg róla, hogy a <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> fájl és a <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> telepÃtve van, majd próbáld újra.]]></string> | ||
| 147 | <string name="album_applet">Album</string> | ||
| 148 | <string name="album_applet_description">Képernyőképek megtekintése a rendszer fényképnézegetőjével</string> | ||
| 149 | <string name="mii_edit_applet">Mii szerkesztés</string> | ||
| 150 | <string name="mii_edit_applet_description">Miik megtekintése és szerkesztése a rendszerszerkesztővel</string> | ||
| 151 | <string name="cabinet_applet">Kabinet</string> | ||
| 152 | <string name="cabinet_applet_description">Amiibon tárolt adatok szerkesztése és törlése</string> | ||
| 153 | <string name="cabinet_launcher">Kabinet indÃtó</string> | ||
| 154 | <string name="cabinet_nickname_and_owner">Becenév és tulajdonos beállÃtások</string> | ||
| 155 | <string name="cabinet_game_data_eraser">Játékadat eltávolÃtó</string> | ||
| 156 | <string name="cabinet_restorer">HelyreállÃtó</string> | ||
| 157 | <string name="cabinet_formatter">Formázó</string> | ||
| 120 | 158 | ||
| 121 | <!-- About screen strings --> | 159 | <!-- About screen strings --> |
| 122 | <string name="gaia_is_not_real">Gaia nem valódi</string> | 160 | <string name="gaia_is_not_real">Gaia nem valódi</string> |
| @@ -158,6 +196,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 158 | <string name="frame_limit_enable_description">Korlátozza az emuláció sebességét a normál sebesség adott százalékára.</string> | 196 | <string name="frame_limit_enable_description">Korlátozza az emuláció sebességét a normál sebesség adott százalékára.</string> |
| 159 | <string name="frame_limit_slider">Sebességkorlát százaléka</string> | 197 | <string name="frame_limit_slider">Sebességkorlát százaléka</string> |
| 160 | <string name="frame_limit_slider_description">Az emuláció sebességét határozza meg. 100% a normál sebesség. A magasabb értékek növelik, az alacsonyabbak csökkentik a sebességkorlátot.</string> | 198 | <string name="frame_limit_slider_description">Az emuláció sebességét határozza meg. 100% a normál sebesség. A magasabb értékek növelik, az alacsonyabbak csökkentik a sebességkorlátot.</string> |
| 199 | <string name="cpu_backend">CPU backend</string> | ||
| 161 | <string name="cpu_accuracy">CPU pontosság</string> | 200 | <string name="cpu_accuracy">CPU pontosság</string> |
| 162 | <string name="value_with_units">%1$s%2$s</string> | 201 | <string name="value_with_units">%1$s%2$s</string> |
| 163 | 202 | ||
| @@ -188,7 +227,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 188 | <string name="renderer_reactive_flushing_description">JavÃtja a renderelési pontosságot néhány játékban a teljesÃtmény rovására.</string> | 227 | <string name="renderer_reactive_flushing_description">JavÃtja a renderelési pontosságot néhány játékban a teljesÃtmény rovására.</string> |
| 189 | <string name="use_disk_shader_cache">Lemez árnyékoló gyorsÃtótár</string> | 228 | <string name="use_disk_shader_cache">Lemez árnyékoló gyorsÃtótár</string> |
| 190 | <string name="use_disk_shader_cache_description">Csökkenti az akadásokat azáltal, hogy helyileg tárolja és tölti be a generált árnyékolókat.</string> | 229 | <string name="use_disk_shader_cache_description">Csökkenti az akadásokat azáltal, hogy helyileg tárolja és tölti be a generált árnyékolókat.</string> |
| 191 | 230 | <string name="anisotropic_filtering">Anizotropikus szűrés</string> | |
| 192 | <!-- Debug settings strings --> | 231 | <!-- Debug settings strings --> |
| 193 | <string name="cpu">CPU</string> | 232 | <string name="cpu">CPU</string> |
| 194 | <string name="cpu_debug_mode">CPU hibakeresés</string> | 233 | <string name="cpu_debug_mode">CPU hibakeresés</string> |
| @@ -196,9 +235,9 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 196 | <string name="gpu">GPU</string> | 235 | <string name="gpu">GPU</string> |
| 197 | <string name="renderer_api">API</string> | 236 | <string name="renderer_api">API</string> |
| 198 | <string name="renderer_debug">Grafikai hibakeresés</string> | 237 | <string name="renderer_debug">Grafikai hibakeresés</string> |
| 199 | <string name="renderer_debug_description">Lassú hibakeresési módba állÃtja a grafikus API-t .</string> | 238 | <string name="renderer_debug_description">Lassú hibakeresÅ‘ módba állÃtja a grafikus API-t .</string> |
| 200 | <!-- Audio settings strings --> | 239 | <!-- Audio settings strings --> |
| 201 | <string name="audio_output_engine">Kimeneti rendszer</string> | 240 | <string name="audio_output_engine">Kimeneti motor</string> |
| 202 | <string name="audio_volume">Hangerő</string> | 241 | <string name="audio_volume">Hangerő</string> |
| 203 | <string name="audio_volume_description">Hangkimenet hangerejének megadása</string> | 242 | <string name="audio_volume_description">Hangkimenet hangerejének megadása</string> |
| 204 | 243 | ||
| @@ -212,6 +251,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 212 | <string name="shutting_down">LeállÃtás...</string> | 251 | <string name="shutting_down">LeállÃtás...</string> |
| 213 | <string name="reset_setting_confirmation">Szeretnéd visszaállÃtani a beállÃtások az alapértelmezett értékekre?</string> | 252 | <string name="reset_setting_confirmation">Szeretnéd visszaállÃtani a beállÃtások az alapértelmezett értékekre?</string> |
| 214 | <string name="reset_to_default">Alaphelyzetbe állÃtás</string> | 253 | <string name="reset_to_default">Alaphelyzetbe állÃtás</string> |
| 254 | <string name="reset_to_default_description">VisszaállÃtja a haladó beállÃtásokat</string> | ||
| 215 | <string name="reset_all_settings">Alaphelyzetbe állÃtod a beállÃtásokat?</string> | 255 | <string name="reset_all_settings">Alaphelyzetbe állÃtod a beállÃtásokat?</string> |
| 216 | <string name="reset_all_settings_description">Minden haladó beállÃtás vissza lesz állÃtva az alapértelmezett konfigurációra. Ez a művelet nem vonható vissza.</string> | 256 | <string name="reset_all_settings_description">Minden haladó beállÃtás vissza lesz állÃtva az alapértelmezett konfigurációra. Ez a művelet nem vonható vissza.</string> |
| 217 | <string name="settings_reset">BeállÃtások alaphelyzetbe állÃtva</string> | 257 | <string name="settings_reset">BeállÃtások alaphelyzetbe állÃtva</string> |
| @@ -219,12 +259,24 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 219 | <string name="learn_more">Tudj meg többet</string> | 259 | <string name="learn_more">Tudj meg többet</string> |
| 220 | <string name="auto">Automatikus</string> | 260 | <string name="auto">Automatikus</string> |
| 221 | <string name="submit">Küldés</string> | 261 | <string name="submit">Küldés</string> |
| 222 | <string name="string_null">Nulla</string> | 262 | <string name="string_null">Null</string> |
| 223 | <string name="string_import">Importálás</string> | 263 | <string name="string_import">Importálás</string> |
| 224 | <string name="export">Exportálás</string> | 264 | <string name="export">Exportálás</string> |
| 225 | <string name="export_failed">Exportálás sikertelen</string> | 265 | <string name="export_failed">Exportálás sikertelen</string> |
| 226 | <string name="import_failed">Importálás sikertelen</string> | 266 | <string name="import_failed">Importálás sikertelen</string> |
| 227 | <string name="cancelling">MegszakÃtás</string> | 267 | <string name="cancelling">MegszakÃtás</string> |
| 268 | <string name="install">TelepÃtés</string> | ||
| 269 | <string name="delete">Törlés</string> | ||
| 270 | <string name="edit">Szerkesztés</string> | ||
| 271 | <string name="export_success">Sikeresen exportálva</string> | ||
| 272 | <string name="start">Start</string> | ||
| 273 | <string name="clear">Törlés</string> | ||
| 274 | <string name="global">Globális</string> | ||
| 275 | <string name="custom">Egyéni</string> | ||
| 276 | <string name="notice">ÉrtesÃtés</string> | ||
| 277 | <string name="import_complete">Importálás befejezve</string> | ||
| 278 | <string name="more_options">További opciók</string> | ||
| 279 | <string name="use_global_setting">Globális beállÃtás használata</string> | ||
| 228 | 280 | ||
| 229 | <!-- GPU driver installation --> | 281 | <!-- GPU driver installation --> |
| 230 | <string name="select_gpu_driver">Válassz GPU illesztőprogramot</string> | 282 | <string name="select_gpu_driver">Válassz GPU illesztőprogramot</string> |
| @@ -232,7 +284,8 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 232 | <string name="select_gpu_driver_install">TelepÃtés</string> | 284 | <string name="select_gpu_driver_install">TelepÃtés</string> |
| 233 | <string name="select_gpu_driver_default">Alapértelmezett</string> | 285 | <string name="select_gpu_driver_default">Alapértelmezett</string> |
| 234 | <string name="select_gpu_driver_use_default">Alapértelmezett GPU illesztőprogram használata</string> | 286 | <string name="select_gpu_driver_use_default">Alapértelmezett GPU illesztőprogram használata</string> |
| 235 | <string name="select_gpu_driver_error">Érvénytelen driver kiválasztva, a rendszer alapértelmezett lesz használva!</string> | 287 | <string name="select_gpu_driver_error">Érvénytelen illesztőprogram kiválasztva</string> |
| 288 | <string name="driver_already_installed">Az illesztÅ‘program már telepÃtve van</string> | ||
| 236 | <string name="system_gpu_driver">Rendszer GPU illesztőprogram</string> | 289 | <string name="system_gpu_driver">Rendszer GPU illesztőprogram</string> |
| 237 | <string name="installing_driver">IllesztÅ‘program telepÃtése...</string> | 290 | <string name="installing_driver">IllesztÅ‘program telepÃtése...</string> |
| 238 | 291 | ||
| @@ -240,10 +293,54 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 240 | <string name="preferences_settings">BeállÃtások</string> | 293 | <string name="preferences_settings">BeállÃtások</string> |
| 241 | <string name="preferences_general">Ãltalános</string> | 294 | <string name="preferences_general">Ãltalános</string> |
| 242 | <string name="preferences_system">Rendszer</string> | 295 | <string name="preferences_system">Rendszer</string> |
| 296 | <string name="preferences_system_description">Dokkolt mód, régió, nyelv</string> | ||
| 243 | <string name="preferences_graphics">Grafika</string> | 297 | <string name="preferences_graphics">Grafika</string> |
| 298 | <string name="preferences_graphics_description">Pontossági szint, felbontás, árnyékoló gyorsÃtótár</string> | ||
| 244 | <string name="preferences_audio">Hang</string> | 299 | <string name="preferences_audio">Hang</string> |
| 300 | <string name="preferences_audio_description">Kimeneti motor, hangerő</string> | ||
| 245 | <string name="preferences_theme">Téma és szÃnek</string> | 301 | <string name="preferences_theme">Téma és szÃnek</string> |
| 246 | <string name="preferences_debug">Hibakeresés</string> | 302 | <string name="preferences_debug">Hibakeresés</string> |
| 303 | <string name="preferences_debug_description">CPU/GPU hibakeresés, grafikus API, fastmem</string> | ||
| 304 | |||
| 305 | <!-- Game properties --> | ||
| 306 | <string name="info">Infó</string> | ||
| 307 | <string name="info_description">Program ID, fejlesztő, verzió</string> | ||
| 308 | <string name="per_game_settings">Játékonkénti beállÃtások</string> | ||
| 309 | <string name="per_game_settings_description">Játékspecifikus beállÃtások szerkesztése</string> | ||
| 310 | <string name="launch_options">IndÃtási konfiguráció</string> | ||
| 311 | <string name="path">Útvonal</string> | ||
| 312 | <string name="program_id">Program ID</string> | ||
| 313 | <string name="developer">Fejlesztő</string> | ||
| 314 | <string name="version">Verzió</string> | ||
| 315 | <string name="copy_details">Részletek másolása</string> | ||
| 316 | <string name="add_ons">KiegészÃtÅ‘k</string> | ||
| 317 | <string name="add_ons_description">Modok, frissÃtések és DLC váltása</string> | ||
| 318 | <string name="clear_shader_cache">Ãrnyékoló gyorsÃtótár ürÃtése</string> | ||
| 319 | <string name="clear_shader_cache_description">EltávolÃtja a játék által létrehozott árnyékolókat.</string> | ||
| 320 | <string name="clear_shader_cache_warning_description">Az árnyékoló gyorsÃtótár regenerálódása során több akadozást fogsz tapasztalni.</string> | ||
| 321 | <string name="cleared_shaders_successfully">Ãrnyékolók sikeresen ürÃtve</string> | ||
| 322 | <string name="addons_game">KiegészÃtÅ‘k: %1$s</string> | ||
| 323 | <string name="save_data">Mentett adatok</string> | ||
| 324 | <string name="save_data_description">Játékspecifikus mentett adatok kezelése</string> | ||
| 325 | <string name="delete_save_data">Mentett adatok törlése</string> | ||
| 326 | <string name="delete_save_data_description">EltávolÃtja az összes játékhoz tartozó mentett adatot.</string> | ||
| 327 | <string name="delete_save_data_warning_description">Ez helyreállÃthatatlanul eltávolÃtja a játék összes mentett adatát. Biztosan szeretnéd folytatni?</string> | ||
| 328 | <string name="save_data_deleted_successfully">Mentett adatok sikeresen törölve</string> | ||
| 329 | <string name="select_content_type">Tartalom tÃpusa</string> | ||
| 330 | <string name="updates_and_dlc">FrissÃtések és DLC</string> | ||
| 331 | <string name="mods_and_cheats">Modok és csalások</string> | ||
| 332 | <string name="addon_notice">Fontos kiegészÃtÅ‘ értesÃtés</string> | ||
| 333 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 334 | <string name="addon_notice_description">A modok és csalások telepÃtéséhez olyan mappát válassz, amely tartalmaz cheats/, romfs/ vagy exefs/ könyvtárat. Nem tudjuk garantálni, hogy ezek kompatibilisek lesznek a játékoddal, ezért légy óvatos!</string> | ||
| 335 | <string name="invalid_directory">Érvénytelen könyvtár</string> | ||
| 336 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 337 | <string name="invalid_directory_description">Kérjük, győződj meg róla, hogy a kiválasztott könyvtár tartalmazza a cheats/, romfs/ vagy exefs/ mappát, majd próbáld újra.</string> | ||
| 338 | <string name="addon_installed_successfully">KiegészÃtÅ‘ sikeresen telepÃtve</string> | ||
| 339 | <string name="verifying_content">Tartalom ellenőrzése...</string> | ||
| 340 | <string name="content_install_notice">Tartalom telepÃtési értesÃtés</string> | ||
| 341 | <string name="content_install_notice_description">A kiválasztott tartalom nem ehhez a játékhoz tartozik.\nÃgy is telepÃted?</string> | ||
| 342 | <string name="confirm_uninstall">EltávolÃtás megerÅ‘sÃtése</string> | ||
| 343 | <string name="confirm_uninstall_description">Biztosan törölni szeretnéd ezt a kiegészÃtÅ‘t?</string> | ||
| 247 | 344 | ||
| 248 | <!-- ROM loading errors --> | 345 | <!-- ROM loading errors --> |
| 249 | <string name="loader_error_encrypted">ROM titkosÃtva</string> | 346 | <string name="loader_error_encrypted">ROM titkosÃtva</string> |
| @@ -270,6 +367,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 270 | <string name="emulation_pause">Emuláció szünetelése</string> | 367 | <string name="emulation_pause">Emuláció szünetelése</string> |
| 271 | <string name="emulation_unpause">Emuláció folytatása</string> | 368 | <string name="emulation_unpause">Emuláció folytatása</string> |
| 272 | <string name="emulation_input_overlay">Ãtfedés beállÃtásai</string> | 369 | <string name="emulation_input_overlay">Ãtfedés beállÃtásai</string> |
| 370 | <string name="touchscreen">Érintőképernyő</string> | ||
| 273 | 371 | ||
| 274 | <string name="load_settings">BeállÃtások betöltése...</string> | 372 | <string name="load_settings">BeállÃtások betöltése...</string> |
| 275 | 373 | ||
| @@ -301,6 +399,7 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 301 | 399 | ||
| 302 | <!-- Memory Sizes --> | 400 | <!-- Memory Sizes --> |
| 303 | <string name="memory_byte">Bájt</string> | 401 | <string name="memory_byte">Bájt</string> |
| 402 | <string name="memory_byte_shorthand">B</string> | ||
| 304 | <string name="memory_kilobyte">KB</string> | 403 | <string name="memory_kilobyte">KB</string> |
| 305 | <string name="memory_megabyte">MB</string> | 404 | <string name="memory_megabyte">MB</string> |
| 306 | <string name="memory_gigabyte">GB</string> | 405 | <string name="memory_gigabyte">GB</string> |
| @@ -345,9 +444,11 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 345 | <string name="anti_aliasing_smaa">SMAA</string> | 444 | <string name="anti_aliasing_smaa">SMAA</string> |
| 346 | 445 | ||
| 347 | <!-- Screen Layouts --> | 446 | <!-- Screen Layouts --> |
| 447 | <string name="screen_layout_auto">Automatikus</string> | ||
| 348 | <string name="screen_layout_landscape">Fekvő</string> | 448 | <string name="screen_layout_landscape">Fekvő</string> |
| 449 | <string name="screen_layout_reverse_landscape">Fekvő (fejjel lefelé)</string> | ||
| 349 | <string name="screen_layout_portrait">Ãlló</string> | 450 | <string name="screen_layout_portrait">Ãlló</string> |
| 350 | <string name="screen_layout_auto">Automatikus</string> | 451 | <string name="screen_layout_reverse_portrait">Ãlló (fejjel lefelé)</string> |
| 351 | 452 | ||
| 352 | <!-- Aspect Ratios --> | 453 | <!-- Aspect Ratios --> |
| 353 | <string name="ratio_default">Alapértelmezett (16:9)</string> | 454 | <string name="ratio_default">Alapértelmezett (16:9)</string> |
| @@ -356,6 +457,8 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 356 | <string name="ratio_force_sixteen_ten">16:10 kényszerÃtése</string> | 457 | <string name="ratio_force_sixteen_ten">16:10 kényszerÃtése</string> |
| 357 | <string name="ratio_stretch">Ablakhoz nyújtás</string> | 458 | <string name="ratio_stretch">Ablakhoz nyújtás</string> |
| 358 | 459 | ||
| 460 | <!-- CPU Backend --> | ||
| 461 | <string name="cpu_backend_dynarmic">Dinamikus (lassú)</string> | ||
| 359 | <!-- CPU Accuracy --> | 462 | <!-- CPU Accuracy --> |
| 360 | <string name="cpu_accuracy_accurate">Pontos</string> | 463 | <string name="cpu_accuracy_accurate">Pontos</string> |
| 361 | <string name="cpu_accuracy_unsafe">Nem biztonságos</string> | 464 | <string name="cpu_accuracy_unsafe">Nem biztonságos</string> |
| @@ -382,8 +485,15 @@ Válaszd ki a(z) <b>Games</b> mappát az alábbi gombbal.</string> | |||
| 382 | <string name="theme_mode_dark">Sötét</string> | 485 | <string name="theme_mode_dark">Sötét</string> |
| 383 | 486 | ||
| 384 | <!-- Audio output engines --> | 487 | <!-- Audio output engines --> |
| 488 | <string name="oboe">oboe</string> | ||
| 385 | <string name="cubeb">cubeb</string> | 489 | <string name="cubeb">cubeb</string> |
| 386 | 490 | ||
| 491 | <!-- Anisotropic filtering options --> | ||
| 492 | <string name="multiplier_two">2x</string> | ||
| 493 | <string name="multiplier_four">4x</string> | ||
| 494 | <string name="multiplier_eight">8x</string> | ||
| 495 | <string name="multiplier_sixteen">16x</string> | ||
| 496 | |||
| 387 | <!-- Black backgrounds theme --> | 497 | <!-- Black backgrounds theme --> |
| 388 | <string name="use_black_backgrounds">Fekete háttér</string> | 498 | <string name="use_black_backgrounds">Fekete háttér</string> |
| 389 | <string name="use_black_backgrounds_description">Sötét téma használatakor fekete háttér használata.</string> | 499 | <string name="use_black_backgrounds_description">Sötét téma használatakor fekete háttér használata.</string> |
diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml index 5afebb4c4..61b39f57f 100644 --- a/src/android/app/src/main/res/values-it/strings.xml +++ b/src/android/app/src/main/res/values-it/strings.xml | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | <string name="keys_description">Seleziona il tuo file <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">Seleziona le chiavi</string> | 18 | <string name="select_keys">Seleziona le chiavi</string> |
| 19 | <string name="games">Giochi</string> | 19 | <string name="games">Giochi</string> |
| 20 | <string name="games_description">Seleziona la cartella <b>Games</b> con il pulsante in basso.</string> | 20 | <string name="games_description">Seleziona la cartella dei <b>giochi</b> con il pulsante in basso.</string> |
| 21 | <string name="done">Fatto</string> | 21 | <string name="done">Fatto</string> |
| 22 | <string name="done_description">È tutto pronto.\nDivertiti a giocare!</string> | 22 | <string name="done_description">È tutto pronto.\nDivertiti a giocare!</string> |
| 23 | <string name="text_continue">Continua</string> | 23 | <string name="text_continue">Continua</string> |
| @@ -33,7 +33,7 @@ | |||
| 33 | <string name="home_settings">Impostazioni</string> | 33 | <string name="home_settings">Impostazioni</string> |
| 34 | <string name="empty_gamelist">Non sono stati trovati file o non è stata ancora selezionata alcuna directory di gioco.</string> | 34 | <string name="empty_gamelist">Non sono stati trovati file o non è stata ancora selezionata alcuna directory di gioco.</string> |
| 35 | <string name="search_and_filter_games">Cerca e filtra i giochi</string> | 35 | <string name="search_and_filter_games">Cerca e filtra i giochi</string> |
| 36 | <string name="select_games_folder">Seleziona la cartella di gioco</string> | 36 | <string name="select_games_folder">Seleziona la cartella dei giochi</string> |
| 37 | <string name="select_games_folder_description">Consente a yuzu di popolare l\'elenco dei giochi</string> | 37 | <string name="select_games_folder_description">Consente a yuzu di popolare l\'elenco dei giochi</string> |
| 38 | <string name="add_games_warning">Saltare la selezione della cartella dei giochi?</string> | 38 | <string name="add_games_warning">Saltare la selezione della cartella dei giochi?</string> |
| 39 | <string name="add_games_warning_description">I giochi non saranno mostrati nella lista dei giochi se una cartella non è selezionata.</string> | 39 | <string name="add_games_warning_description">I giochi non saranno mostrati nella lista dei giochi se una cartella non è selezionata.</string> |
| @@ -68,6 +68,7 @@ | |||
| 68 | <string name="invalid_keys_error">Chiavi di crittografia non valide</string> | 68 | <string name="invalid_keys_error">Chiavi di crittografia non valide</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string> | 70 | <string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string> |
| 71 | <string name="gpu_driver_manager">Gestore driver GPU</string> | ||
| 71 | <string name="install_gpu_driver">Installa i driver GPU</string> | 72 | <string name="install_gpu_driver">Installa i driver GPU</string> |
| 72 | <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string> | 73 | <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string> |
| 73 | <string name="advanced_settings">Impostazioni avanzate</string> | 74 | <string name="advanced_settings">Impostazioni avanzate</string> |
| @@ -118,6 +119,23 @@ | |||
| 118 | <string name="manage_yuzu_data_description">Importa/Esporta il firmware, le keys, i dati utente, e altro!</string> | 119 | <string name="manage_yuzu_data_description">Importa/Esporta il firmware, le keys, i dati utente, e altro!</string> |
| 119 | <string name="share_save_file">Condividi i tuoi dati di salvataggio</string> | 120 | <string name="share_save_file">Condividi i tuoi dati di salvataggio</string> |
| 120 | <string name="export_save_failed">Errore durante l\'esportazione del salvataggio</string> | 121 | <string name="export_save_failed">Errore durante l\'esportazione del salvataggio</string> |
| 122 | <!-- Applet launcher strings --> | ||
| 123 | <string name="applets">Avvia applet</string> | ||
| 124 | <string name="applets_description">Avvia applet di sistema usando il firmware installato</string> | ||
| 125 | <string name="applets_error_firmware">Firmware non installato</string> | ||
| 126 | <string name="applets_error_applet">Applet non disponibile</string> | ||
| 127 | <string name="applets_error_description"><![CDATA[Assicurati che il file <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> e il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> siano installati e riprova.]]></string> | ||
| 128 | <string name="album_applet">Album</string> | ||
| 129 | <string name="album_applet_description">Visualizza le immagini salvate nella cartella screenshots dell\'utente con il visualizzatore immagini di sistema</string> | ||
| 130 | <string name="mii_edit_applet">Modifica Mii</string> | ||
| 131 | <string name="mii_edit_applet_description">Visualizza e modifica Mii con l\'editor di sistema</string> | ||
| 132 | <string name="cabinet_applet">Cabinet</string> | ||
| 133 | <string name="cabinet_applet_description">Modifica ed elimina i dati salvati sugli amiibo</string> | ||
| 134 | <string name="cabinet_launcher">Avvia Cabinet</string> | ||
| 135 | <string name="cabinet_nickname_and_owner">Impostazioni nickname e proprietario</string> | ||
| 136 | <string name="cabinet_game_data_eraser">Cancella dati di gioco</string> | ||
| 137 | <string name="cabinet_restorer">Ripristina</string> | ||
| 138 | <string name="cabinet_formatter">Formatta</string> | ||
| 121 | 139 | ||
| 122 | <!-- About screen strings --> | 140 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia non è reale</string> | 141 | <string name="gaia_is_not_real">Gaia non è reale</string> |
| @@ -191,7 +209,6 @@ | |||
| 191 | <string name="renderer_reactive_flushing_description">Migliora l\'accuratezza della grafica in alcuni giochi, al costo delle performance.</string> | 209 | <string name="renderer_reactive_flushing_description">Migliora l\'accuratezza della grafica in alcuni giochi, al costo delle performance.</string> |
| 192 | <string name="use_disk_shader_cache">Usa la cache delle shader</string> | 210 | <string name="use_disk_shader_cache">Usa la cache delle shader</string> |
| 193 | <string name="use_disk_shader_cache_description">Riduce lo stuttering caricando le shader già compilate all\'avvio.</string> | 211 | <string name="use_disk_shader_cache_description">Riduce lo stuttering caricando le shader già compilate all\'avvio.</string> |
| 194 | |||
| 195 | <!-- Debug settings strings --> | 212 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 213 | <string name="cpu">CPU</string> |
| 197 | <string name="cpu_debug_mode">Debug della CPU</string> | 214 | <string name="cpu_debug_mode">Debug della CPU</string> |
| @@ -230,14 +247,19 @@ | |||
| 230 | <string name="export_failed">Esportazione Fallita</string> | 247 | <string name="export_failed">Esportazione Fallita</string> |
| 231 | <string name="import_failed">Importazione Fallita</string> | 248 | <string name="import_failed">Importazione Fallita</string> |
| 232 | <string name="cancelling">Cancellazione</string> | 249 | <string name="cancelling">Cancellazione</string> |
| 233 | 250 | <string name="install">Installa</string> | |
| 251 | <string name="delete">Elimina</string> | ||
| 252 | <string name="start">Start</string> | ||
| 253 | <string name="clear">Cancella</string> | ||
| 254 | <string name="custom">Personalizzato</string> | ||
| 234 | <!-- GPU driver installation --> | 255 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">Seleziona il driver della GPU</string> | 256 | <string name="select_gpu_driver">Seleziona il driver della GPU</string> |
| 236 | <string name="select_gpu_driver_title">Vuoi sostituire il driver della tua GPU attuale?</string> | 257 | <string name="select_gpu_driver_title">Vuoi sostituire il driver della tua GPU attuale?</string> |
| 237 | <string name="select_gpu_driver_install">Installa</string> | 258 | <string name="select_gpu_driver_install">Installa</string> |
| 238 | <string name="select_gpu_driver_default">Predefinito</string> | 259 | <string name="select_gpu_driver_default">Predefinito</string> |
| 239 | <string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string> | 260 | <string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string> |
| 240 | <string name="select_gpu_driver_error">Il driver selezionato è invalido, è in utilizzo quello predefinito di sistema!</string> | 261 | <string name="select_gpu_driver_error">Driver selezionato non valido</string> |
| 262 | <string name="driver_already_installed">Driver già installato</string> | ||
| 241 | <string name="system_gpu_driver">Driver GPU del sistema</string> | 263 | <string name="system_gpu_driver">Driver GPU del sistema</string> |
| 242 | <string name="installing_driver">Installando i driver...</string> | 264 | <string name="installing_driver">Installando i driver...</string> |
| 243 | 265 | ||
| @@ -249,7 +271,12 @@ | |||
| 249 | <string name="preferences_audio">Audio</string> | 271 | <string name="preferences_audio">Audio</string> |
| 250 | <string name="preferences_theme">Tema e colori</string> | 272 | <string name="preferences_theme">Tema e colori</string> |
| 251 | <string name="preferences_debug">Debug</string> | 273 | <string name="preferences_debug">Debug</string> |
| 252 | 274 | <!-- Game properties --> | |
| 275 | <string name="info">Info</string> | ||
| 276 | <string name="path">Percorso</string> | ||
| 277 | <string name="developer">Sviluppatore</string> | ||
| 278 | <string name="version">Versione</string> | ||
| 279 | <string name="add_ons">Add-on</string> | ||
| 253 | <!-- ROM loading errors --> | 280 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">La tua ROM è criptata</string> | 281 | <string name="loader_error_encrypted">La tua ROM è criptata</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[Segui la nostra guida per fare il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">dump delle tue cartucce di gioco</a>oppure <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">dei titoli già installati</a>.]]></string> | 282 | <string name="loader_error_encrypted_roms_description"><![CDATA[Segui la nostra guida per fare il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">dump delle tue cartucce di gioco</a>oppure <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">dei titoli già installati</a>.]]></string> |
| @@ -263,20 +290,21 @@ | |||
| 263 | <string name="emulation_exit">Arresta emulazione</string> | 290 | <string name="emulation_exit">Arresta emulazione</string> |
| 264 | <string name="emulation_done">Fatto</string> | 291 | <string name="emulation_done">Fatto</string> |
| 265 | <string name="emulation_fps_counter">Contatore FPS</string> | 292 | <string name="emulation_fps_counter">Contatore FPS</string> |
| 266 | <string name="emulation_toggle_controls">Controlli a interruttore</string> | 293 | <string name="emulation_toggle_controls">Attiva/disattiva comandi</string> |
| 267 | <string name="emulation_rel_stick_center">Centro relativo degli Stick</string> | 294 | <string name="emulation_rel_stick_center">Centro relativo degli Stick</string> |
| 268 | <string name="emulation_dpad_slide">DPad A Scorrimento</string> | 295 | <string name="emulation_dpad_slide">DPad A Scorrimento</string> |
| 269 | <string name="emulation_haptics">Feedback Aptico</string> | 296 | <string name="emulation_haptics">Feedback Aptico</string> |
| 270 | <string name="emulation_show_overlay">Mostra l\'Overlay</string> | 297 | <string name="emulation_show_overlay">Mostra l\'overlay</string> |
| 271 | <string name="emulation_toggle_all">Attiva/Disattiva tutto</string> | 298 | <string name="emulation_toggle_all">Attiva/Disattiva tutto</string> |
| 272 | <string name="emulation_control_adjust">Modifica l\'Overlay</string> | 299 | <string name="emulation_control_adjust">Regola l\'overlay</string> |
| 273 | <string name="emulation_control_scale">Scala</string> | 300 | <string name="emulation_control_scale">Scala</string> |
| 274 | <string name="emulation_control_opacity">Opacità </string> | 301 | <string name="emulation_control_opacity">Opacità </string> |
| 275 | <string name="emulation_touch_overlay_reset">Reimposta l\'Overlay</string> | 302 | <string name="emulation_touch_overlay_reset">Reimposta l\'overlay</string> |
| 276 | <string name="emulation_touch_overlay_edit">Modifica l\'Overlay</string> | 303 | <string name="emulation_touch_overlay_edit">Modifica l\'overlay</string> |
| 277 | <string name="emulation_pause">Sospendi l\'emulazione</string> | 304 | <string name="emulation_pause">Sospendi l\'emulazione</string> |
| 278 | <string name="emulation_unpause">Riprendi l\'emulazione</string> | 305 | <string name="emulation_unpause">Riprendi l\'emulazione</string> |
| 279 | <string name="emulation_input_overlay">Opzioni overlay</string> | 306 | <string name="emulation_input_overlay">Opzioni overlay</string> |
| 307 | <string name="touchscreen">Touchscreen</string> | ||
| 280 | 308 | ||
| 281 | <string name="load_settings">Carico le impostazioni...</string> | 309 | <string name="load_settings">Carico le impostazioni...</string> |
| 282 | 310 | ||
| @@ -308,6 +336,7 @@ | |||
| 308 | 336 | ||
| 309 | <!-- Memory Sizes --> | 337 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 338 | <string name="memory_byte">Byte</string> |
| 339 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">Kb</string> | 340 | <string name="memory_kilobyte">Kb</string> |
| 312 | <string name="memory_megabyte">Mb</string> | 341 | <string name="memory_megabyte">Mb</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 342 | <string name="memory_gigabyte">GB</string> |
| @@ -352,10 +381,9 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 381 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 382 | ||
| 354 | <!-- Screen Layouts --> | 383 | <!-- Screen Layouts --> |
| 384 | <string name="screen_layout_auto">Automatico</string> | ||
| 355 | <string name="screen_layout_landscape">Layout Orizzontale</string> | 385 | <string name="screen_layout_landscape">Layout Orizzontale</string> |
| 356 | <string name="screen_layout_portrait">Layout Verticale</string> | 386 | <string name="screen_layout_portrait">Layout Verticale</string> |
| 357 | <string name="screen_layout_auto">Automatico</string> | ||
| 358 | |||
| 359 | <!-- Aspect Ratios --> | 387 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">Predefinito (16:9)</string> | 388 | <string name="ratio_default">Predefinito (16:9)</string> |
| 361 | <string name="ratio_force_four_three">Forza 4:3</string> | 389 | <string name="ratio_force_four_three">Forza 4:3</string> |
| @@ -390,9 +418,14 @@ | |||
| 390 | <string name="theme_mode_light">Chiaro</string> | 418 | <string name="theme_mode_light">Chiaro</string> |
| 391 | <string name="theme_mode_dark">Scuro</string> | 419 | <string name="theme_mode_dark">Scuro</string> |
| 392 | 420 | ||
| 393 | <!-- Audio output engines --> | ||
| 394 | <string name="cubeb">cubeb</string> | 421 | <string name="cubeb">cubeb</string> |
| 395 | 422 | ||
| 423 | <!-- Anisotropic filtering options --> | ||
| 424 | <string name="multiplier_two">2x</string> | ||
| 425 | <string name="multiplier_four">4x</string> | ||
| 426 | <string name="multiplier_eight">8x</string> | ||
| 427 | <string name="multiplier_sixteen">16x</string> | ||
| 428 | |||
| 396 | <!-- Black backgrounds theme --> | 429 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">Sfondi neri</string> | 430 | <string name="use_black_backgrounds">Sfondi neri</string> |
| 398 | <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string> | 431 | <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string> |
diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml index 3be4e7d26..0cff40bb6 100644 --- a/src/android/app/src/main/res/values-ja/strings.xml +++ b/src/android/app/src/main/res/values-ja/strings.xml | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„ã¨ã€ã‚²ãƒ¼ãƒ ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string> | 39 | <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„ã¨ã€ã‚²ãƒ¼ãƒ ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string> |
| 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| 41 | <string name="home_search_games">ゲームを検索</string> | 41 | <string name="home_search_games">ゲームを検索</string> |
| 42 | <string name="search_settings">検索è¨å®š</string> | 42 | <string name="search_settings">è¨å®šã‚’検索</string> |
| 43 | <string name="games_dir_selected">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¾ã—ãŸ</string> | 43 | <string name="games_dir_selected">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¾ã—ãŸ</string> |
| 44 | <string name="install_prod_keys">prod.keys</string> | 44 | <string name="install_prod_keys">prod.keys</string> |
| 45 | <string name="install_prod_keys_description">製å“版ゲームã®å¾©å·åŒ–ã«å¿…è¦ã§ã™</string> | 45 | <string name="install_prod_keys_description">製å“版ゲームã®å¾©å·åŒ–ã«å¿…è¦ã§ã™</string> |
| @@ -68,6 +68,7 @@ | |||
| 68 | <string name="invalid_keys_error">æš—å·åŒ–ã‚ーãŒç„¡åй</string> | 68 | <string name="invalid_keys_error">æš—å·åŒ–ã‚ーãŒç„¡åй</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">ファイルãŒé–“é•ã£ã¦ã„ã‚‹ã‹ç ´æã—ã¦ã„ã¾ã™ã€‚ã‚ーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string> | 70 | <string name="install_keys_failure_description">ファイルãŒé–“é•ã£ã¦ã„ã‚‹ã‹ç ´æã—ã¦ã„ã¾ã™ã€‚ã‚ーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string> |
| 71 | <string name="gpu_driver_manager">GPUドライãƒãƒ¼ã®ç®¡ç†</string> | ||
| 71 | <string name="install_gpu_driver">GPUドライãƒãƒ¼</string> | 72 | <string name="install_gpu_driver">GPUドライãƒãƒ¼</string> |
| 72 | <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string> | 73 | <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string> |
| 73 | <string name="advanced_settings">高度ãªè¨å®š</string> | 74 | <string name="advanced_settings">高度ãªè¨å®š</string> |
| @@ -111,6 +112,9 @@ | |||
| 111 | <string name="custom_driver_not_supported">カスタムドライãƒã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“</string> | 112 | <string name="custom_driver_not_supported">カスタムドライãƒã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“</string> |
| 112 | <string name="manage_yuzu_data">yuzu データを管ç†</string> | 113 | <string name="manage_yuzu_data">yuzu データを管ç†</string> |
| 113 | <string name="share_save_file">セーブファイルを共有</string> | 114 | <string name="share_save_file">セーブファイルを共有</string> |
| 115 | <string name="applets_error_firmware">ファームウェア未インストール</string> | ||
| 116 | <string name="album_applet">アルãƒãƒ </string> | ||
| 117 | <string name="cabinet_nickname_and_owner">ニックãƒãƒ¼ãƒ ã¨æ‰€æœ‰è€…ã®è¨å®š</string> | ||
| 114 | <!-- About screen strings --> | 118 | <!-- About screen strings --> |
| 115 | <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string> | 119 | <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string> |
| 116 | <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string> | 120 | <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string> |
| @@ -178,10 +182,9 @@ | |||
| 178 | <string name="renderer_reactive_flushing_description">一部ã®ã‚²ãƒ¼ãƒ ã«ãŠã„ã¦ã€ãƒ‘ãƒ•ã‚©ãƒ¼ãƒžãƒ³ã‚¹ã‚’çŠ ç‰²ã«ã—ãªãŒã‚‰ã‚‚ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ç²¾åº¦ã‚’å‘上ã•ã›ã¾ã™ã€‚</string> | 182 | <string name="renderer_reactive_flushing_description">一部ã®ã‚²ãƒ¼ãƒ ã«ãŠã„ã¦ã€ãƒ‘ãƒ•ã‚©ãƒ¼ãƒžãƒ³ã‚¹ã‚’çŠ ç‰²ã«ã—ãªãŒã‚‰ã‚‚ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ç²¾åº¦ã‚’å‘上ã•ã›ã¾ã™ã€‚</string> |
| 179 | <string name="use_disk_shader_cache">ディスクシェーダーã‚ャッシュ</string> | 183 | <string name="use_disk_shader_cache">ディスクシェーダーã‚ャッシュ</string> |
| 180 | <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’端末ã«ä¿å˜ã—ã¦èªã¿è¾¼ã¿ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string> | 184 | <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’端末ã«ä¿å˜ã—ã¦èªã¿è¾¼ã¿ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string> |
| 181 | |||
| 182 | <!-- Debug settings strings --> | 185 | <!-- Debug settings strings --> |
| 183 | <string name="cpu">CPU</string> | 186 | <string name="cpu">CPU</string> |
| 184 | <string name="cpu_debug_mode">CPU デãƒãƒƒã‚®ãƒ³ã‚°</string> | 187 | <string name="cpu_debug_mode">CPUデãƒãƒƒã‚°</string> |
| 185 | <string name="gpu">GPU</string> | 188 | <string name="gpu">GPU</string> |
| 186 | <string name="renderer_api">API</string> | 189 | <string name="renderer_api">API</string> |
| 187 | <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string> | 190 | <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string> |
| @@ -215,14 +218,17 @@ | |||
| 215 | <string name="export_failed">エクスãƒãƒ¼ãƒˆå¤±æ•—</string> | 218 | <string name="export_failed">エクスãƒãƒ¼ãƒˆå¤±æ•—</string> |
| 216 | <string name="import_failed">インãƒãƒ¼ãƒˆå¤±æ•—</string> | 219 | <string name="import_failed">インãƒãƒ¼ãƒˆå¤±æ•—</string> |
| 217 | <string name="cancelling">ã‚ャンセルä¸</string> | 220 | <string name="cancelling">ã‚ャンセルä¸</string> |
| 218 | 221 | <string name="install">インストール</string> | |
| 222 | <string name="delete">削除</string> | ||
| 223 | <string name="start">é–‹å§‹</string> | ||
| 224 | <string name="clear">クリア</string> | ||
| 225 | <string name="custom">カスタム</string> | ||
| 219 | <!-- GPU driver installation --> | 226 | <!-- GPU driver installation --> |
| 220 | <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string> | 227 | <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string> |
| 221 | <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string> | 228 | <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string> |
| 222 | <string name="select_gpu_driver_install">インストール</string> | 229 | <string name="select_gpu_driver_install">インストール</string> |
| 223 | <string name="select_gpu_driver_default">デフォルト</string> | 230 | <string name="select_gpu_driver_default">デフォルト</string> |
| 224 | <string name="select_gpu_driver_use_default">デフォルトã®ãƒ‰ãƒ©ã‚¤ãƒã‚’使用ã—ã¾ã™</string> | 231 | <string name="select_gpu_driver_use_default">デフォルトã®ãƒ‰ãƒ©ã‚¤ãƒã‚’使用ã—ã¾ã™</string> |
| 225 | <string name="select_gpu_driver_error">é¸æŠžã•れãŸãƒ‰ãƒ©ã‚¤ãƒãŒç„¡åйã€ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ‡ãƒ•ォルトを使用ã—ã¾ã™!</string> | ||
| 226 | <string name="system_gpu_driver">システムã®GPUドライãƒ</string> | 232 | <string name="system_gpu_driver">システムã®GPUドライãƒ</string> |
| 227 | <string name="installing_driver">インストールä¸â€¦</string> | 233 | <string name="installing_driver">インストールä¸â€¦</string> |
| 228 | 234 | ||
| @@ -234,7 +240,12 @@ | |||
| 234 | <string name="preferences_audio">サウンド</string> | 240 | <string name="preferences_audio">サウンド</string> |
| 235 | <string name="preferences_theme">テーマã¨è‰²</string> | 241 | <string name="preferences_theme">テーマã¨è‰²</string> |
| 236 | <string name="preferences_debug">デãƒãƒƒã‚°</string> | 242 | <string name="preferences_debug">デãƒãƒƒã‚°</string> |
| 237 | 243 | <!-- Game properties --> | |
| 244 | <string name="info">æƒ…å ±</string> | ||
| 245 | <string name="path">パス</string> | ||
| 246 | <string name="developer">開発元</string> | ||
| 247 | <string name="version">ãƒãƒ¼ã‚¸ãƒ§ãƒ³</string> | ||
| 248 | <string name="add_ons">アドオン</string> | ||
| 238 | <!-- ROM loading errors --> | 249 | <!-- ROM loading errors --> |
| 239 | <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string> | 250 | <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string> |
| 240 | <string name="loader_error_encrypted_keys_description"><![CDATA[ゲームã®å¾©å·åŒ–ã«å¿…è¦ãª <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。]]></string> | 251 | <string name="loader_error_encrypted_keys_description"><![CDATA[ゲームã®å¾©å·åŒ–ã«å¿…è¦ãª <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。]]></string> |
| @@ -261,6 +272,7 @@ | |||
| 261 | <string name="emulation_pause">ä¸€æ™‚åœæ¢</string> | 272 | <string name="emulation_pause">ä¸€æ™‚åœæ¢</string> |
| 262 | <string name="emulation_unpause">å†é–‹</string> | 273 | <string name="emulation_unpause">å†é–‹</string> |
| 263 | <string name="emulation_input_overlay">表示オプション</string> | 274 | <string name="emulation_input_overlay">表示オプション</string> |
| 275 | <string name="touchscreen">タッãƒã‚¹ã‚¯ãƒªãƒ¼ãƒ³</string> | ||
| 264 | 276 | ||
| 265 | <string name="load_settings">è¨å®šã‚’ãƒãƒ¼ãƒ‰ä¸â€¦</string> | 277 | <string name="load_settings">è¨å®šã‚’ãƒãƒ¼ãƒ‰ä¸â€¦</string> |
| 266 | 278 | ||
| @@ -292,6 +304,7 @@ | |||
| 292 | 304 | ||
| 293 | <!-- Memory Sizes --> | 305 | <!-- Memory Sizes --> |
| 294 | <string name="memory_byte">Byte</string> | 306 | <string name="memory_byte">Byte</string> |
| 307 | <string name="memory_byte_shorthand">B</string> | ||
| 295 | <string name="memory_kilobyte">KB</string> | 308 | <string name="memory_kilobyte">KB</string> |
| 296 | <string name="memory_megabyte">MB</string> | 309 | <string name="memory_megabyte">MB</string> |
| 297 | <string name="memory_gigabyte">GB</string> | 310 | <string name="memory_gigabyte">GB</string> |
| @@ -336,10 +349,9 @@ | |||
| 336 | <string name="anti_aliasing_smaa">SMAA</string> | 349 | <string name="anti_aliasing_smaa">SMAA</string> |
| 337 | 350 | ||
| 338 | <!-- Screen Layouts --> | 351 | <!-- Screen Layouts --> |
| 352 | <string name="screen_layout_auto">自動</string> | ||
| 339 | <string name="screen_layout_landscape">横長</string> | 353 | <string name="screen_layout_landscape">横長</string> |
| 340 | <string name="screen_layout_portrait">縦長</string> | 354 | <string name="screen_layout_portrait">縦長</string> |
| 341 | <string name="screen_layout_auto">自動</string> | ||
| 342 | |||
| 343 | <!-- Aspect Ratios --> | 355 | <!-- Aspect Ratios --> |
| 344 | <string name="ratio_default">デフォルト (16:9)</string> | 356 | <string name="ratio_default">デフォルト (16:9)</string> |
| 345 | <string name="ratio_force_four_three">強制 4:3</string> | 357 | <string name="ratio_force_four_three">強制 4:3</string> |
| @@ -374,9 +386,14 @@ | |||
| 374 | <string name="theme_mode_light">ライト</string> | 386 | <string name="theme_mode_light">ライト</string> |
| 375 | <string name="theme_mode_dark">ダーク</string> | 387 | <string name="theme_mode_dark">ダーク</string> |
| 376 | 388 | ||
| 377 | <!-- Audio output engines --> | ||
| 378 | <string name="cubeb">cubeb</string> | 389 | <string name="cubeb">cubeb</string> |
| 379 | 390 | ||
| 391 | <!-- Anisotropic filtering options --> | ||
| 392 | <string name="multiplier_two">2x</string> | ||
| 393 | <string name="multiplier_four">4x</string> | ||
| 394 | <string name="multiplier_eight">8x</string> | ||
| 395 | <string name="multiplier_sixteen">16x</string> | ||
| 396 | |||
| 380 | <!-- Black backgrounds theme --> | 397 | <!-- Black backgrounds theme --> |
| 381 | <string name="use_black_backgrounds">完全ãªé»’を使用</string> | 398 | <string name="use_black_backgrounds">完全ãªé»’を使用</string> |
| 382 | <string name="use_black_backgrounds_description">ダークテーマã®èƒŒæ™¯è‰²ã«é»’ãŒé©ç”¨ã•れã¾ã™ã€‚</string> | 399 | <string name="use_black_backgrounds_description">ダークテーマã®èƒŒæ™¯è‰²ã«é»’ãŒé©ç”¨ã•れã¾ã™ã€‚</string> |
diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml index 1b9160a23..eaa6c23ce 100644 --- a/src/android/app/src/main/res/values-ko/strings.xml +++ b/src/android/app/src/main/res/values-ko/strings.xml | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | <string name="back">ì´ì „</string> | 25 | <string name="back">ì´ì „</string> |
| 26 | <string name="add_games">게임 추가</string> | 26 | <string name="add_games">게임 추가</string> |
| 27 | <string name="add_games_description">게임 í´ë” ì„ íƒ</string> | 27 | <string name="add_games_description">게임 í´ë” ì„ íƒ</string> |
| 28 | <string name="step_complete">완료ë˜ì—ˆìŠµë‹ˆë‹¤!</string> | ||
| 29 | |||
| 28 | <!-- Home strings --> | 30 | <!-- Home strings --> |
| 29 | <string name="home_games">게임</string> | 31 | <string name="home_games">게임</string> |
| 30 | <string name="home_search">검색</string> | 32 | <string name="home_search">검색</string> |
| @@ -32,11 +34,13 @@ | |||
| 32 | <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ ë””ë ‰í„°ë¦¬ë¥¼ ì„ íƒí•˜ì§€ 않았습니다.</string> | 34 | <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ ë””ë ‰í„°ë¦¬ë¥¼ ì„ íƒí•˜ì§€ 않았습니다.</string> |
| 33 | <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string> | 35 | <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string> |
| 34 | <string name="select_games_folder">게임 í´ë” ì„ íƒ</string> | 36 | <string name="select_games_folder">게임 í´ë” ì„ íƒ</string> |
| 35 | <string name="select_games_folder_description">yuzuê°€ 게임 목ë¡ì„ 채울 수 있ë„ë¡ í—ˆìš©</string> | 37 | <string name="manage_game_folders">게임 í´ë” 관리</string> |
| 38 | <string name="select_games_folder_description">yuzuì— ê²Œìž„ ëª©ë¡ ì¶”ê°€í•˜ê¸°</string> | ||
| 36 | <string name="add_games_warning">게임 í´ë” ì„ íƒì„ ê±´ë„ˆë›°ê² ìŠµë‹ˆê¹Œ?</string> | 39 | <string name="add_games_warning">게임 í´ë” ì„ íƒì„ ê±´ë„ˆë›°ê² ìŠµë‹ˆê¹Œ?</string> |
| 37 | <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string> | 40 | <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string> |
| 38 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 41 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| 39 | <string name="home_search_games">게임 검색</string> | 42 | <string name="home_search_games">게임 검색</string> |
| 43 | <string name="search_settings">검색 ì„¤ì •</string> | ||
| 40 | <string name="games_dir_selected">게임 ë””ë ‰í„°ë¦¬ë¥¼ ì„¤ì •í–ˆìŠµë‹ˆë‹¤.</string> | 44 | <string name="games_dir_selected">게임 ë””ë ‰í„°ë¦¬ë¥¼ ì„¤ì •í–ˆìŠµë‹ˆë‹¤.</string> |
| 41 | <string name="install_prod_keys">prod.keys 설치</string> | 45 | <string name="install_prod_keys">prod.keys 설치</string> |
| 42 | <string name="install_prod_keys_description">패키지 게임 암호 í•´ë…ì— í•„ìš”</string> | 46 | <string name="install_prod_keys_description">패키지 게임 암호 í•´ë…ì— í•„ìš”</string> |
| @@ -65,9 +69,11 @@ | |||
| 65 | <string name="invalid_keys_error">암호화 키가 올바르지 않ìŒ</string> | 69 | <string name="invalid_keys_error">암호화 키가 올바르지 않ìŒ</string> |
| 66 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 67 | <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. 키를 다시 ë¤í”„하세요.</string> | 71 | <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. 키를 다시 ë¤í”„하세요.</string> |
| 72 | <string name="gpu_driver_manager">GPU 드ë¼ì´ë²„ 관리ìž</string> | ||
| 68 | <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string> | 73 | <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string> |
| 69 | <string name="install_gpu_driver_description">ìž ìž¬ì 으로 ë” ë‚˜ì€ ì„±ëŠ¥ ë˜ëŠ” ì •í™•ì„±ì„ ìœ„í•´ 대체 드ë¼ì´ë²„를 설치하세요.</string> | 74 | <string name="install_gpu_driver_description">ìž ìž¬ì ì¸ ì„±ëŠ¥ ë˜ëŠ” ì •í™•ë„ ê°œì„ ì„ ìœ„í•´ 대체 드ë¼ì´ë²„ 설치</string> |
| 70 | <string name="advanced_settings">ê³ ê¸‰ ì„¤ì •</string> | 75 | <string name="advanced_settings">ê³ ê¸‰ ì„¤ì •</string> |
| 76 | <string name="advanced_settings_game">ê³ ê¸‰ ì„¤ì •: %1$s</string> | ||
| 71 | <string name="settings_description">ì—ë®¬ë ˆì´í„° ì„¤ì • 구성</string> | 77 | <string name="settings_description">ì—ë®¬ë ˆì´í„° ì„¤ì • 구성</string> |
| 72 | <string name="search_recently_played">최근 í”Œë ˆì´</string> | 78 | <string name="search_recently_played">최근 í”Œë ˆì´</string> |
| 73 | <string name="search_recently_added">최근 추가</string> | 79 | <string name="search_recently_added">최근 추가</string> |
| @@ -79,9 +85,13 @@ | |||
| 79 | <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> | 85 | <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> |
| 80 | <string name="notification_no_directory_link">yuzu ë””ë ‰í„°ë¦¬ë¥¼ ì—´ 수 ì—†ìŒ</string> | 86 | <string name="notification_no_directory_link">yuzu ë””ë ‰í„°ë¦¬ë¥¼ ì—´ 수 ì—†ìŒ</string> |
| 81 | <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string> | 87 | <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string> |
| 82 | <string name="manage_save_data">ì €ìž¥ ë°ì´í„° 관리</string> | 88 | <string name="manage_save_data">세ì´ë¸Œ ë°ì´í„° 관리</string> |
| 83 | <string name="manage_save_data_description">ì €ìž¥ ë°ì´í„°ë¥¼ 발견했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string> | 89 | <string name="manage_save_data_description">세ì´ë¸Œ ë°ì´í„°ë¥¼ 발견했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string> |
| 84 | <string name="import_export_saves_description">ì €ìž¥ íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string> | 90 | <string name="import_save_warning">세ì´ë¸Œ ë°ì´í„° ê°€ì ¸ì˜¤ê¸°</string> |
| 91 | <string name="import_save_warning_description">ì´ ìž‘ì—…ì€ ê¸°ì¡´ ë°ì´í„° ì „ì²´ë¥¼ ì„ íƒí•œ 파ì¼ë¡œ ë®ì–´ì”Œì›ë‹ˆë‹¤. 계ì†í•˜ì‹œê² 습니까?</string> | ||
| 92 | <string name="import_export_saves_description">세ì´ë¸Œ íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string> | ||
| 93 | <string name="save_files_importing">세ì´ë¸Œ íŒŒì¼ ê°€ì ¸ì˜¤ëŠ” 중...</string> | ||
| 94 | <string name="save_files_exporting">세ì´ë¸Œ íŒŒì¼ ë‚´ë³´ë‚´ëŠ” 중...</string> | ||
| 85 | <string name="save_file_imported_success">ë°ì´í„°ë¥¼ 불러왔습니다.</string> | 95 | <string name="save_file_imported_success">ë°ì´í„°ë¥¼ 불러왔습니다.</string> |
| 86 | <string name="save_file_invalid_zip_structure">올바르지 ì•Šì€ ì €ìž¥ ë””ë ‰í„°ë¦¬ 구조</string> | 96 | <string name="save_file_invalid_zip_structure">올바르지 ì•Šì€ ì €ìž¥ ë””ë ‰í„°ë¦¬ 구조</string> |
| 87 | <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string> | 97 | <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string> |
| @@ -89,15 +99,62 @@ | |||
| 89 | <string name="export_saves">내보내기</string> | 99 | <string name="export_saves">내보내기</string> |
| 90 | <string name="install_firmware">펌웨어 설치</string> | 100 | <string name="install_firmware">펌웨어 설치</string> |
| 91 | <string name="install_firmware_description">펌웨어는 ZIP 파ì¼ì´ë©° ì¼ë¶€ ê²Œìž„ì„ ë¶€íŒ…í•˜ëŠ” ë° í•„ìš”í•©ë‹ˆë‹¤.</string> | 101 | <string name="install_firmware_description">펌웨어는 ZIP 파ì¼ì´ë©° ì¼ë¶€ ê²Œìž„ì„ ë¶€íŒ…í•˜ëŠ” ë° í•„ìš”í•©ë‹ˆë‹¤.</string> |
| 92 | <string name="firmware_installing">펌웨어 설치</string> | 102 | <string name="firmware_installing">펌웨어 설치 중...</string> |
| 93 | <string name="firmware_installed_success">펌웨어를 설치했습니다.</string> | 103 | <string name="firmware_installed_success">펌웨어를 설치했습니다.</string> |
| 94 | <string name="firmware_installed_failure">펌웨어 설치 실패</string> | 104 | <string name="firmware_installed_failure">펌웨어 설치 실패</string> |
| 105 | <string name="firmware_installed_failure_description">펌웨어 NCA 파ì¼ì´ ZIP 파ì¼ì˜ 루트 ë””ë ‰í† ë¦¬ì— ìœ„ì¹˜í•œì§€ 확ì¸í•˜ê³ 다시 시ë„하세요.</string> | ||
| 95 | <string name="share_log">디버그 로그 ê³µìœ </string> | 106 | <string name="share_log">디버그 로그 ê³µìœ </string> |
| 96 | <string name="share_log_description">yuzuì˜ ë¡œê·¸ 파ì¼ì„ ê³µìœ í•˜ì—¬ ë¬¸ì œ 디버깅하기</string> | 107 | <string name="share_log_description">ë¬¸ì œ í•´ê²°ì„ ìœ„í•œ yuzu 로그 íŒŒì¼ ê³µìœ </string> |
| 97 | <string name="share_log_missing">로그 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다.</string> | 108 | <string name="share_log_missing">로그 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다.</string> |
| 98 | <string name="install_game_content">게임 콘í…ì¸ ì„¤ì¹˜</string> | 109 | <string name="install_game_content">게임 콘í…ì¸ ì„¤ì¹˜</string> |
| 99 | <string name="install_game_content_description">게임 ì—…ë°ì´íЏ ë˜ëŠ” DLC 설치</string> | 110 | <string name="install_game_content_description">게임 ì—…ë°ì´íЏ ë˜ëŠ” DLC 설치</string> |
| 111 | <string name="installing_game_content">콘í…ì¸ ì„¤ì¹˜ 중...</string> | ||
| 112 | <string name="install_game_content_failure">NANDì— íŒŒì¼ì„ 설치하는 ë™ì•ˆ 오류 ë°œìƒ</string> | ||
| 113 | <string name="install_game_content_failure_description">콘í…ì¸ ê°€ ìœ íš¨í•˜ê³ prod.keysê°€ 설치ë˜ì—ˆëŠ”ì§€ 확ì¸í•˜ì„¸ìš”.</string> | ||
| 114 | <string name="install_game_content_failure_base">ì¶©ëŒì„ 방지하기 위해 기본 게임 설치는 허용ë˜ì§€ 않습니다.</string> | ||
| 115 | <string name="install_game_content_failure_file_extension">NSP ë° XCI 콘í…ì¸ ë§Œ ì§€ì›í•©ë‹ˆë‹¤. 게임 콘í…ì¸ ê°€ ìœ íš¨í•œì§€ 확ì¸í•˜ì„¸ìš”.</string> | ||
| 116 | <string name="install_game_content_failed_count">%1$dê°œì˜ ì„¤ì¹˜ 오류</string> | ||
| 117 | <string name="install_game_content_success">게임 콘í…ì¸ ì„¤ì¹˜ë¨</string> | ||
| 118 | <string name="install_game_content_success_install">%1$d개를 설치했습니다.</string> | ||
| 119 | <string name="install_game_content_success_overwrite">%1$d개를 ë®ì–´ì”Œì› 습니다.</string> | ||
| 100 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> | 120 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> |
| 121 | <string name="custom_driver_not_supported">ì‚¬ìš©ìž ì§€ì • 드ë¼ì´ë²„는 ì§€ì›í•˜ì§€ 않습니다.</string> | ||
| 122 | <string name="custom_driver_not_supported_description">ì´ ìž¥ì¹˜ì˜ ì‚¬ìš©ìž ì§€ì • 드ë¼ì´ë²„ ë¡œë”©ì€ í˜„ìž¬ ì§€ì›í•˜ì§€ 않습니다.\në‚˜ì¤‘ì— ì´ ì˜µì…˜ì„ í™•ì¸í•˜ë©´ ì§€ì›ì´ 추가ë˜ì—ˆëŠ”ì§€ 확ì¸í• 수 있습니다.</string> | ||
| 123 | <string name="manage_yuzu_data">yuzu ë°ì´í„° 관리</string> | ||
| 124 | <string name="manage_yuzu_data_description">펌웨어, 키 ê°’, ìœ ì € ë°ì´í„° ë“±ì„ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string> | ||
| 125 | <string name="share_save_file">세ì´ë¸Œ íŒŒì¼ ê³µìœ </string> | ||
| 126 | <string name="export_save_failed">세ì´ë¸Œ 내보내기 실패</string> | ||
| 127 | <string name="game_folders">게임 í´ë”</string> | ||
| 128 | <string name="deep_scan">딥 스캔(하위 í´ë” íƒìƒ‰)</string> | ||
| 129 | <string name="add_game_folder">게임 í´ë” 추가</string> | ||
| 130 | <string name="folder_already_added">ì´ í´ë”는 ì´ë¯¸ 추가ë˜ì–´ 있습니다!</string> | ||
| 131 | <string name="game_folder_properties">게임 í´ë” ì†ì„±</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="other">%dê°œì˜ ì„¸ì´ë¸Œ ê°€ì ¸ì˜¤ê¸° 실패</item> | ||
| 134 | </plurals> | ||
| 135 | <plurals name="saves_import_success"> | ||
| 136 | <item quantity="other">%dê°œì˜ ì„¸ì´ë¸Œë¥¼ ê°€ì ¸ì™”ìŠµë‹ˆë‹¤.</item> | ||
| 137 | </plurals> | ||
| 138 | <string name="no_save_data_found">세ì´ë¸Œ ë°ì´í„°ë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> | ||
| 139 | |||
| 140 | <!-- Applet launcher strings --> | ||
| 141 | <string name="applets">ì• í”Œë¦¿ 런처</string> | ||
| 142 | <string name="applets_description">ì„¤ì¹˜ëœ íŽŒì›¨ì–´ë¥¼ 사용해 시스템 ì• í”Œë¦¿ì„ ì‹¤í–‰í•©ë‹ˆë‹¤.</string> | ||
| 143 | <string name="applets_error_firmware">펌웨어가 설치ë˜ì§€ 않았습니다.</string> | ||
| 144 | <string name="applets_error_applet">ì• í”Œë¦¿ì„ ì‚¬ìš©í• ìˆ˜ ì—†ìŒ</string> | ||
| 145 | <string name="applets_error_description"><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ê³¼ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">펌웨어가</a> 설치ë˜ì—ˆëŠ”ì§€ 확ì¸í•˜ê³ 다시 시ë„하세요.]]></string> | ||
| 146 | <string name="album_applet">앨범</string> | ||
| 147 | <string name="album_applet_description">시스템 사진 뷰어로 ìœ ì € 스í¬ë¦°ìƒ· í´ë”ì— ì €ìž¥ëœ ì´ë¯¸ì§€ë¥¼ 확ì¸í•©ë‹ˆë‹¤. </string> | ||
| 148 | <string name="mii_edit_applet">Mii 편집</string> | ||
| 149 | <string name="mii_edit_applet_description">시스템 ì—디터로 Mii를 ë³´ê³ íŽ¸ì§‘í•©ë‹ˆë‹¤.</string> | ||
| 150 | <string name="cabinet_applet">ìºë¹„ë‹›</string> | ||
| 151 | <string name="cabinet_applet_description">amiiboì— ì €ìž¥ëœ ë°ì´í„°ë¥¼ íŽ¸ì§‘í•˜ê³ ì‚ì œí•©ë‹ˆë‹¤.</string> | ||
| 152 | <string name="cabinet_launcher">ìºë¹„ë‹› 런처</string> | ||
| 153 | <string name="cabinet_nickname_and_owner">닉네임 ë° ì†Œìœ ìž ì„¤ì •</string> | ||
| 154 | <string name="cabinet_game_data_eraser">게임 ë°ì´í„° ì‚ì œ</string> | ||
| 155 | <string name="cabinet_restorer">ë³µì›</string> | ||
| 156 | <string name="cabinet_formatter">í¬ë§·í„°</string> | ||
| 157 | |||
| 101 | <!-- About screen strings --> | 158 | <!-- About screen strings --> |
| 102 | <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string> | 159 | <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string> |
| 103 | <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사ë˜ì—ˆìŠµë‹ˆë‹¤.</string> | 160 | <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사ë˜ì—ˆìŠµë‹ˆë‹¤.</string> |
| @@ -107,6 +164,16 @@ | |||
| 107 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | 164 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> |
| 108 | <string name="licenses_description">Androidìš© yuzu를 가능하게 하는 프로ì 트</string> | 165 | <string name="licenses_description">Androidìš© yuzu를 가능하게 하는 프로ì 트</string> |
| 109 | <string name="build">빌드</string> | 166 | <string name="build">빌드</string> |
| 167 | <string name="user_data">ìœ ì € ë°ì´í„°</string> | ||
| 168 | <string name="user_data_description">ëª¨ë“ ì•± ë°ì´í„°ë¥¼ ê°€ì ¸ì˜¤ê±°ë‚˜ 내보냅니다.\n\nìœ ì € ë°ì´í„°ë¥¼ ê°€ì ¸ì˜¬ 경우 í˜„ìž¬ì˜ ëª¨ë“ ë°ì´í„°ëŠ” ì‚ì œë©ë‹ˆë‹¤.</string> | ||
| 169 | <string name="exporting_user_data">ìœ ì € ë°ì´í„° 내보내는 중...</string> | ||
| 170 | <string name="importing_user_data">ìœ ì € ë°ì´í„° ê°€ì ¸ì˜¤ëŠ” 중...</string> | ||
| 171 | <string name="import_user_data">ìœ ì € ë°ì´í„° ê°€ì ¸ì˜¤ê¸°</string> | ||
| 172 | <string name="invalid_yuzu_backup">올바르지 ì•Šì€ yuzu 백업 파ì¼</string> | ||
| 173 | <string name="user_data_export_success">ìœ ì € ë°ì´í„°ë¥¼ 내보냈습니다.</string> | ||
| 174 | <string name="user_data_import_success">ìœ ì € ë°ì´í„°ë¥¼ ê°€ì ¸ì™”ìŠµë‹ˆë‹¤.</string> | ||
| 175 | <string name="user_data_export_cancelled">내보내기 취소ë¨</string> | ||
| 176 | <string name="user_data_import_failed_description">ìœ ì € ë°ì´í„° í´ë”ê°€ ZIP í´ë”ì˜ ë£¨íŠ¸ ë””ë ‰í† ë¦¬ì— ìœ„ì¹˜í•˜ê³ config/config.ini 구성 파ì¼ì´ 있는지 확ì¸í•˜ê³ 다시 시ë„하세요.</string> | ||
| 110 | <string name="support_link">https://discord.gg/u77vRWY</string> | 177 | <string name="support_link">https://discord.gg/u77vRWY</string> |
| 111 | <string name="website_link">https://yuzu-emu.org/</string> | 178 | <string name="website_link">https://yuzu-emu.org/</string> |
| 112 | <string name="github_link">https://github.com/yuzu-emu</string> | 179 | <string name="github_link">https://github.com/yuzu-emu</string> |
| @@ -130,7 +197,10 @@ | |||
| 130 | <string name="frame_limit_enable_description">ì—ë®¬ë ˆì´ì…˜ ì†ë„를 ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ ì œí•œí•©ë‹ˆë‹¤.</string> | 197 | <string name="frame_limit_enable_description">ì—ë®¬ë ˆì´ì…˜ ì†ë„를 ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ ì œí•œí•©ë‹ˆë‹¤.</string> |
| 131 | <string name="frame_limit_slider">ì†ë„ ì œí•œ 비율</string> | 198 | <string name="frame_limit_slider">ì†ë„ ì œí•œ 비율</string> |
| 132 | <string name="frame_limit_slider_description">ì—ë®¬ë ˆì´ì…˜ ì†ë„ì˜ ì œí•œ ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. 100%ê°€ ì •ìƒ ì†ë„입니다. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string> | 199 | <string name="frame_limit_slider_description">ì—ë®¬ë ˆì´ì…˜ ì†ë„ì˜ ì œí•œ ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. 100%ê°€ ì •ìƒ ì†ë„입니다. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string> |
| 200 | <string name="cpu_backend">CPU 백엔드</string> | ||
| 133 | <string name="cpu_accuracy">CPU ì •í™•ë„</string> | 201 | <string name="cpu_accuracy">CPU ì •í™•ë„</string> |
| 202 | <string name="value_with_units">%1$s%2$s</string> | ||
| 203 | |||
| 134 | <!-- System settings strings --> | 204 | <!-- System settings strings --> |
| 135 | <string name="use_docked_mode">ë… ëª¨ë“œ</string> | 205 | <string name="use_docked_mode">ë… ëª¨ë“œ</string> |
| 136 | <string name="use_docked_mode_description">í•´ìƒë„를 높ì´ë©° ì„±ëŠ¥ì´ ì €í•˜ë©ë‹ˆë‹¤. 비활성화시 휴대 모드가 사용ë˜ë©° í•´ìƒë„는 ë‚®ì•„ì§€ê³ ì„±ëŠ¥ì€ í–¥ìƒë©ë‹ˆë‹¤.</string> | 206 | <string name="use_docked_mode_description">í•´ìƒë„를 높ì´ë©° ì„±ëŠ¥ì´ ì €í•˜ë©ë‹ˆë‹¤. 비활성화시 휴대 모드가 사용ë˜ë©° í•´ìƒë„는 ë‚®ì•„ì§€ê³ ì„±ëŠ¥ì€ í–¥ìƒë©ë‹ˆë‹¤.</string> |
| @@ -139,13 +209,14 @@ | |||
| 139 | <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string> | 209 | <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string> |
| 140 | <string name="select_rtc_time">RTC 시간 ì„ íƒ</string> | 210 | <string name="select_rtc_time">RTC 시간 ì„ íƒ</string> |
| 141 | <string name="use_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC</string> | 211 | <string name="use_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC</string> |
| 142 | <string name="use_custom_rtc_description">현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • 실시간 시계를 ì„¤ì •í• ìˆ˜ 있습니다.</string> | 212 | <string name="use_custom_rtc_description">현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • RTC를 ì„¤ì •í• ìˆ˜ 있습니다.</string> |
| 143 | <string name="set_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC ì„¤ì •</string> | 213 | <string name="set_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC ì„¤ì •</string> |
| 144 | 214 | ||
| 145 | <!-- Graphics settings strings --> | 215 | <!-- Graphics settings strings --> |
| 146 | <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string> | 216 | <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string> |
| 147 | <string name="renderer_resolution">í•´ìƒë„ (휴대 모드/ë… ëª¨ë“œ)</string> | 217 | <string name="renderer_resolution">í•´ìƒë„ (휴대 모드/ë… ëª¨ë“œ)</string> |
| 148 | <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string> | 218 | <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string> |
| 219 | <string name="renderer_screen_layout">화면 방향</string> | ||
| 149 | <string name="renderer_aspect_ratio">화면비</string> | 220 | <string name="renderer_aspect_ratio">화면비</string> |
| 150 | <string name="renderer_scaling_filter">윈ë„ìš° ì ì‘ í•„í„°</string> | 221 | <string name="renderer_scaling_filter">윈ë„ìš° ì ì‘ í•„í„°</string> |
| 151 | <string name="renderer_anti_aliasing">안티ì—ì¼ë¦¬ì–´ì‹± 방법</string> | 222 | <string name="renderer_anti_aliasing">안티ì—ì¼ë¦¬ì–´ì‹± 방법</string> |
| @@ -157,12 +228,21 @@ | |||
| 157 | <string name="renderer_reactive_flushing_description">ì¼ë¶€ 게임ì—서 성능 ì €í•˜ë¥¼ ê°ìˆ˜í•˜ê³ ë Œë”ë§ ì •í™•ë„를 í–¥ìƒí•©ë‹ˆë‹¤.</string> | 228 | <string name="renderer_reactive_flushing_description">ì¼ë¶€ 게임ì—서 성능 ì €í•˜ë¥¼ ê°ìˆ˜í•˜ê³ ë Œë”ë§ ì •í™•ë„를 í–¥ìƒí•©ë‹ˆë‹¤.</string> |
| 158 | <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ</string> | 229 | <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ</string> |
| 159 | <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 ë¡œì»¬ì— ì €ìž¥í•˜ê³ ë¡œë“œí•˜ì—¬ ëŠê¹€ 현ìƒì„ 줄입니다.</string> | 230 | <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 ë¡œì»¬ì— ì €ìž¥í•˜ê³ ë¡œë“œí•˜ì—¬ ëŠê¹€ 현ìƒì„ 줄입니다.</string> |
| 231 | <string name="anisotropic_filtering">비등방성 í•„í„°ë§</string> | ||
| 232 | <string name="anisotropic_filtering_description">경사ê°ì—서 ë³´ì´ëŠ” í…ìŠ¤ì²˜ì˜ í’ˆì§ˆì„ í–¥ìƒì‹œí‚µë‹ˆë‹¤.</string> | ||
| 160 | 233 | ||
| 161 | <!-- Debug settings strings --> | 234 | <!-- Debug settings strings --> |
| 162 | <string name="cpu">CPU</string> | 235 | <string name="cpu">CPU</string> |
| 236 | <string name="cpu_debug_mode">CPU 디버깅</string> | ||
| 237 | <string name="cpu_debug_mode_description">CPU를 ëŠë¦° 디버깅 모드로 ì„¤ì •í•©ë‹ˆë‹¤.</string> | ||
| 238 | <string name="gpu">GPU</string> | ||
| 163 | <string name="renderer_api">API</string> | 239 | <string name="renderer_api">API</string> |
| 164 | <string name="renderer_debug">그래픽 디버깅</string> | 240 | <string name="renderer_debug">그래픽 디버깅</string> |
| 165 | <string name="renderer_debug_description">그래픽 API를 ëŠë¦° 디버깅 모드로 ì„¤ì •í•©ë‹ˆë‹¤.</string> | 241 | <string name="renderer_debug_description">그래픽 API를 ëŠë¦° 디버깅 모드로 ì„¤ì •í•©ë‹ˆë‹¤.</string> |
| 242 | <string name="fastmem">Fastmem</string> | ||
| 243 | |||
| 244 | <!-- Audio settings strings --> | ||
| 245 | <string name="audio_output_engine">ì¶œë ¥ 엔진</string> | ||
| 166 | <string name="audio_volume">볼륨</string> | 246 | <string name="audio_volume">볼륨</string> |
| 167 | <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string> | 247 | <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string> |
| 168 | 248 | ||
| @@ -171,12 +251,15 @@ | |||
| 171 | <string name="ini_saved">ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> | 251 | <string name="ini_saved">ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> |
| 172 | <string name="gameid_saved">%1$s ì „ìš© ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> | 252 | <string name="gameid_saved">%1$s ì „ìš© ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> |
| 173 | <string name="error_saving">%1$s.ini ì €ìž¥ 중 오류 ë°œìƒ: %2$s</string> | 253 | <string name="error_saving">%1$s.ini ì €ìž¥ 중 오류 ë°œìƒ: %2$s</string> |
| 254 | <string name="unimplemented_menu">구현ë˜ì§€ ì•Šì€ ë©”ë‰´</string> | ||
| 174 | <string name="loading">불러오는 중...</string> | 255 | <string name="loading">불러오는 중...</string> |
| 256 | <string name="shutting_down">종료하는 중...</string> | ||
| 175 | <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ ìž¬ì„¤ì •í•˜ê² ìŠµë‹ˆê¹Œ?</string> | 257 | <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ ìž¬ì„¤ì •í•˜ê² ìŠµë‹ˆê¹Œ?</string> |
| 176 | <string name="reset_to_default">기본값으로 ìž¬ì„¤ì •</string> | 258 | <string name="reset_to_default">기본값으로 ìž¬ì„¤ì •</string> |
| 259 | <string name="reset_to_default_description">ëª¨ë“ ê³ ê¸‰ ì„¤ì • 초기화</string> | ||
| 177 | <string name="reset_all_settings">ëª¨ë“ ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string> | 260 | <string name="reset_all_settings">ëª¨ë“ ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string> |
| 178 | <string name="reset_all_settings_description">ëª¨ë“ ê³ ê¸‰ ì„¤ì •ì´ ê¸°ë³¸ 구성으로 ìž¬ì„¤ì •ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다.</string> | 261 | <string name="reset_all_settings_description">ëª¨ë“ ê³ ê¸‰ ì„¤ì •ì´ ê¸°ë³¸ 구성으로 ìž¬ì„¤ì •ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다.</string> |
| 179 | <string name="settings_reset">ì„¤ì • 초기화</string> | 262 | <string name="settings_reset">ì„¤ì •ì„ ì´ˆê¸°í™”í–ˆìŠµë‹ˆë‹¤.</string> |
| 180 | <string name="close">닫기</string> | 263 | <string name="close">닫기</string> |
| 181 | <string name="learn_more">ìžì„¸ížˆ</string> | 264 | <string name="learn_more">ìžì„¸ížˆ</string> |
| 182 | <string name="auto">ìžë™</string> | 265 | <string name="auto">ìžë™</string> |
| @@ -184,13 +267,30 @@ | |||
| 184 | <string name="string_null">Null</string> | 267 | <string name="string_null">Null</string> |
| 185 | <string name="string_import">ê°€ì ¸ì˜¤ê¸°</string> | 268 | <string name="string_import">ê°€ì ¸ì˜¤ê¸°</string> |
| 186 | <string name="export">내보내기</string> | 269 | <string name="export">내보내기</string> |
| 270 | <string name="export_failed">내보내기 실패</string> | ||
| 271 | <string name="import_failed">ê°€ì ¸ì˜¤ê¸° 실패</string> | ||
| 272 | <string name="cancelling">취소하는 중</string> | ||
| 273 | <string name="install">설치</string> | ||
| 274 | <string name="delete">ì‚ì œ</string> | ||
| 275 | <string name="edit">편집</string> | ||
| 276 | <string name="export_success">ë°ì´í„°ë¥¼ 내보냈습니다.</string> | ||
| 277 | <string name="start">시작</string> | ||
| 278 | <string name="clear">초기화</string> | ||
| 279 | <string name="global">글로벌</string> | ||
| 280 | <string name="custom">커스텀</string> | ||
| 281 | <string name="notice">알림</string> | ||
| 282 | <string name="import_complete">ê°€ì ¸ì˜¤ê¸° 완료</string> | ||
| 283 | <string name="more_options">추가 옵션</string> | ||
| 284 | <string name="use_global_setting">글로벌 ì„¤ì • 사용</string> | ||
| 285 | |||
| 187 | <!-- GPU driver installation --> | 286 | <!-- GPU driver installation --> |
| 188 | <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string> | 287 | <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string> |
| 189 | <string name="select_gpu_driver_title">현재 ì‚¬ìš©ì¤‘ì¸ GPU 드ë¼ì´ë²„를 ë³€ê²½í•˜ê² ìŠµë‹ˆê¹Œ?</string> | 288 | <string name="select_gpu_driver_title">현재 ì‚¬ìš©ì¤‘ì¸ GPU 드ë¼ì´ë²„를 ë³€ê²½í•˜ê² ìŠµë‹ˆê¹Œ?</string> |
| 190 | <string name="select_gpu_driver_install">설치</string> | 289 | <string name="select_gpu_driver_install">설치</string> |
| 191 | <string name="select_gpu_driver_default">기본값</string> | 290 | <string name="select_gpu_driver_default">기본값</string> |
| 192 | <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„를 사용합니다.</string> | 291 | <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„를 사용합니다.</string> |
| 193 | <string name="select_gpu_driver_error">ìž˜ëª»ëœ ë“œë¼ì´ë¸Œê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤. 시스템 ê¸°ë³¸ê°’ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.</string> | 292 | <string name="select_gpu_driver_error">ìž˜ëª»ëœ ë“œë¼ì´ë²„ê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤.</string> |
| 293 | <string name="driver_already_installed">ì´ë¯¸ ì„¤ì¹˜ëœ ë“œë¼ì´ë²„입니다.</string> | ||
| 194 | <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string> | 294 | <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string> |
| 195 | <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string> | 295 | <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string> |
| 196 | 296 | ||
| @@ -198,13 +298,58 @@ | |||
| 198 | <string name="preferences_settings">ì„¤ì •</string> | 298 | <string name="preferences_settings">ì„¤ì •</string> |
| 199 | <string name="preferences_general">ì¼ë°˜</string> | 299 | <string name="preferences_general">ì¼ë°˜</string> |
| 200 | <string name="preferences_system">시스템</string> | 300 | <string name="preferences_system">시스템</string> |
| 301 | <string name="preferences_system_description">ë… ëª¨ë“œ, ì§€ì—, 언어</string> | ||
| 201 | <string name="preferences_graphics">그래픽</string> | 302 | <string name="preferences_graphics">그래픽</string> |
| 303 | <string name="preferences_graphics_description">ì •í™•ë„ ìˆ˜ì¤€, í•´ìƒë„, ì…°ì´ë” ìºì‹œ</string> | ||
| 202 | <string name="preferences_audio">오디오</string> | 304 | <string name="preferences_audio">오디오</string> |
| 305 | <string name="preferences_audio_description">ì¶œë ¥ 엔진, 불륨</string> | ||
| 203 | <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string> | 306 | <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string> |
| 204 | <string name="preferences_debug">디버그</string> | 307 | <string name="preferences_debug">디버그</string> |
| 308 | <string name="preferences_debug_description">CPU/GPU 디버깅, 그래픽 API, Fastmem</string> | ||
| 309 | |||
| 310 | <!-- Game properties --> | ||
| 311 | <string name="info">ì •ë³´</string> | ||
| 312 | <string name="info_description">프로그램 ID, 개발ìž, ë²„ì „</string> | ||
| 313 | <string name="per_game_settings">게임별 ì„¤ì •</string> | ||
| 314 | <string name="per_game_settings_description">현재 ê²Œìž„ì— ì ìš©ë˜ëŠ” ì„¤ì •ì„ íŽ¸ì§‘í•©ë‹ˆë‹¤.</string> | ||
| 315 | <string name="launch_options">실행 구성</string> | ||
| 316 | <string name="path">주소</string> | ||
| 317 | <string name="program_id">프로그램 ID</string> | ||
| 318 | <string name="developer">개발ìž</string> | ||
| 319 | <string name="version">ë²„ì „</string> | ||
| 320 | <string name="copy_details">ì„¸ë¶€ì‚¬í• ë³µì‚¬</string> | ||
| 321 | <string name="add_ons">부가 기능</string> | ||
| 322 | <string name="add_ons_description">모드, ì—…ë°ì´íЏ ë° DLC ì „í™˜í•˜ê¸°</string> | ||
| 323 | <string name="clear_shader_cache">ì…°ì´ë” ìºì‹œ 비우기</string> | ||
| 324 | <string name="clear_shader_cache_description">현재 ê²Œìž„ì„ ì‹¤í–‰í•˜ëŠ” ì¤‘ì— ìƒì„±ëœ ëª¨ë“ ì…°ì´ë”를 ì‚ì œí•©ë‹ˆë‹¤.</string> | ||
| 325 | <string name="clear_shader_cache_warning_description">ì…°ì´ë” ìºì‹œê°€ 재ìƒì„±ë˜ì–´ ê²Œìž„ì´ ë²„ë²…ì¼ ìˆ˜ 있습니다.</string> | ||
| 326 | <string name="cleared_shaders_successfully">ì…°ì´ë”를 ë¹„ì› ìŠµë‹ˆë‹¤.</string> | ||
| 327 | <string name="addons_game">ì• ë“œì˜¨: %1$s</string> | ||
| 328 | <string name="save_data">세ì´ë¸Œ ë°ì´í„°</string> | ||
| 329 | <string name="save_data_description">현재 ê²Œìž„ì— ì‚¬ìš©ë˜ëŠ” 세ì´ë¸Œ ë°ì´í„°ë¥¼ 관리합니다.</string> | ||
| 330 | <string name="delete_save_data">세ì´ë¸Œ ë°ì´í„° ì‚ì œí•˜ê¸°</string> | ||
| 331 | <string name="delete_save_data_description">현재 ê²Œìž„ì— ì‚¬ìš©ë˜ëŠ” ëª¨ë“ ì„¸ì´ë¸Œ ë°ì´í„°ë¥¼ ì‚ì œí•©ë‹ˆë‹¤.</string> | ||
| 332 | <string name="delete_save_data_warning_description">ì´ ìž‘ì—…ì€ í˜„ìž¬ ê²Œìž„ì˜ ì„¸ì´ë¸Œ ë°ì´í„°ë¥¼ ëª¨ë‘ ì‚ì œí•˜ê³ ë˜ëŒë¦´ 수 없습니다. 계ì†í•˜ì‹œê² 습니까?</string> | ||
| 333 | <string name="save_data_deleted_successfully">세ì´ë¸Œ ë°ì´í„°ë¥¼ ì‚ì œí–ˆìŠµë‹ˆë‹¤.</string> | ||
| 334 | <string name="select_content_type">콘í…ì¸ í˜•íƒœ</string> | ||
| 335 | <string name="updates_and_dlc">ì—…ë°ì´íЏ ë° DLC</string> | ||
| 336 | <string name="mods_and_cheats">모드 ë° ì¹˜íŠ¸</string> | ||
| 337 | <string name="addon_notice">중요 ì• ë“œì˜¨ 알림</string> | ||
| 338 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 339 | <string name="addon_notice_description">모드와 치트를 ì„¤ì¹˜í•˜ë ¤ë©´ cheats/, romfs/, ë˜ëŠ” exefs/ ë””ë ‰í† ë¦¬ë¥¼ í¬í•¨í•˜ëŠ” í´ë”를 ì„ íƒí•´ì•¼ 합니다. ê²Œìž„ê³¼ì˜ í˜¸í™˜ 여부를 확ì¸í• 수 없기 ë•Œë¬¸ì— ì‹ ì¤‘í•˜ê²Œ ê²°ì •í•˜ì„¸ìš”.</string> | ||
| 340 | <string name="invalid_directory">ìž˜ëª»ëœ ë””ë ‰í† ë¦¬</string> | ||
| 341 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 342 | <string name="invalid_directory_description">ì„ íƒí•œ ë””ë ‰í† ë¦¬ê°€ cheats/, romfs/, ë˜ëŠ” exefs/ í´ë”를 í¬í•¨í•˜ëŠ”ì§€ 확ì¸í•˜ê³ 다시 시ë„하세요.</string> | ||
| 343 | <string name="addon_installed_successfully">ì• ë“œì˜¨ì„ ì„¤ì¹˜í–ˆìŠµë‹ˆë‹¤.</string> | ||
| 344 | <string name="verifying_content">콘í…ì¸ í™•ì¸ ì¤‘...</string> | ||
| 345 | <string name="content_install_notice">콘í…ì¸ ì„¤ì¹˜ 안내</string> | ||
| 346 | <string name="content_install_notice_description">ì„ íƒí•œ 콘í…ì¸ ê°€ 현재 게임과 ì¼ì¹˜í•˜ì§€ 않습니다.\në¬´ì‹œí•˜ê³ ì„¤ì¹˜í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</string> | ||
| 347 | <string name="confirm_uninstall">ì œê±° 확ì¸</string> | ||
| 348 | <string name="confirm_uninstall_description">ì´ ì• ë“œì˜¨ì„ ì œê±°í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</string> | ||
| 205 | 349 | ||
| 206 | <!-- ROM loading errors --> | 350 | <!-- ROM loading errors --> |
| 207 | <string name="loader_error_encrypted">롬 파ì¼ì´ 암호화ë˜ì–´ìžˆìŒ</string> | 351 | <string name="loader_error_encrypted">롬 파ì¼ì´ 암호화ë˜ì–´ìžˆìŒ</string> |
| 352 | <string name="loader_error_encrypted_roms_description"><![CDATA[ê°€ì´ë“œì— ë”°ë¼ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">게임 카트리지</a> ë˜ëŠ” <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">ì„¤ì¹˜ëœ íƒ€ì´í‹€</a>ì„ ë‹¤ì‹œ ë¤í”„하세요.]]></string> | ||
| 208 | <string name="loader_error_encrypted_keys_description"><![CDATA[ê²Œìž„ì„ í•´ë…í• ìˆ˜ 있ë„ë¡ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ì´ 설치ë˜ì–´ 있는지 확ì¸í•˜ì„¸ìš”.]]></string> | 353 | <string name="loader_error_encrypted_keys_description"><![CDATA[ê²Œìž„ì„ í•´ë…í• ìˆ˜ 있ë„ë¡ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ì´ 설치ë˜ì–´ 있는지 확ì¸í•˜ì„¸ìš”.]]></string> |
| 209 | <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string> | 354 | <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string> |
| 210 | <string name="loader_error_video_core_description">ì¼ë°˜ì 으로 ì´ ë¬¸ì œëŠ” 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë 수 있습니다.</string> | 355 | <string name="loader_error_video_core_description">ì¼ë°˜ì 으로 ì´ ë¬¸ì œëŠ” 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë 수 있습니다.</string> |
| @@ -229,6 +374,7 @@ | |||
| 229 | <string name="emulation_pause">ì—ë®¬ë ˆì´ì…˜ ì¼ì‹œ 중지</string> | 374 | <string name="emulation_pause">ì—ë®¬ë ˆì´ì…˜ ì¼ì‹œ 중지</string> |
| 230 | <string name="emulation_unpause">ì—ë®¬ë ˆì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string> | 375 | <string name="emulation_unpause">ì—ë®¬ë ˆì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string> |
| 231 | <string name="emulation_input_overlay">화면 ì˜¤ë²„ë ˆì´ ì„¤ì •</string> | 376 | <string name="emulation_input_overlay">화면 ì˜¤ë²„ë ˆì´ ì„¤ì •</string> |
| 377 | <string name="touchscreen">터치 스í¬ë¦°</string> | ||
| 232 | 378 | ||
| 233 | <string name="load_settings">ì„¤ì • 불러오는 중...</string> | 379 | <string name="load_settings">ì„¤ì • 불러오는 중...</string> |
| 234 | 380 | ||
| @@ -245,6 +391,10 @@ | |||
| 245 | <string name="fatal_error">치명ì 오류</string> | 391 | <string name="fatal_error">치명ì 오류</string> |
| 246 | <string name="fatal_error_message">치명ì 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹ì‹œì˜¤.\nì—ë®¬ë ˆì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí• 수 있습니다.</string> | 392 | <string name="fatal_error_message">치명ì 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹ì‹œì˜¤.\nì—ë®¬ë ˆì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí• 수 있습니다.</string> |
| 247 | <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—ë®¬ë ˆì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ ì €í•˜ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string> | 393 | <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—ë®¬ë ˆì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ ì €í•˜ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string> |
| 394 | <string name="device_memory_inadequate">장치 RAM: %1$s\n권장: %2$s</string> | ||
| 395 | <string name="memory_formatted">%1$s %2$s</string> | ||
| 396 | <string name="no_game_present">실행 가능한 ê²Œìž„ì´ ì—†ìŠµë‹ˆë‹¤!</string> | ||
| 397 | |||
| 248 | <!-- Region Names --> | 398 | <!-- Region Names --> |
| 249 | <string name="region_japan">ì¼ë³¸</string> | 399 | <string name="region_japan">ì¼ë³¸</string> |
| 250 | <string name="region_usa">미êµ</string> | 400 | <string name="region_usa">미êµ</string> |
| @@ -254,7 +404,16 @@ | |||
| 254 | <string name="region_korea">대한민êµ</string> | 404 | <string name="region_korea">대한민êµ</string> |
| 255 | <string name="region_taiwan">대만</string> | 405 | <string name="region_taiwan">대만</string> |
| 256 | 406 | ||
| 407 | <!-- Memory Sizes --> | ||
| 408 | <string name="memory_byte">Byte</string> | ||
| 409 | <string name="memory_byte_shorthand">B</string> | ||
| 410 | <string name="memory_kilobyte">KB</string> | ||
| 411 | <string name="memory_megabyte">MB</string> | ||
| 257 | <string name="memory_gigabyte">ì˜êµ 하계 표준시(GB)</string> | 412 | <string name="memory_gigabyte">ì˜êµ 하계 표준시(GB)</string> |
| 413 | <string name="memory_terabyte">TB</string> | ||
| 414 | <string name="memory_petabyte">PB</string> | ||
| 415 | <string name="memory_exabyte">EB</string> | ||
| 416 | |||
| 258 | <!-- Renderer APIs --> | 417 | <!-- Renderer APIs --> |
| 259 | <string name="renderer_vulkan">Vulcan</string> | 418 | <string name="renderer_vulkan">Vulcan</string> |
| 260 | <string name="renderer_none">ì—†ìŒ</string> | 419 | <string name="renderer_none">ì—†ìŒ</string> |
| @@ -291,7 +450,14 @@ | |||
| 291 | <string name="anti_aliasing_fxaa">FXAA</string> | 450 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 292 | <string name="anti_aliasing_smaa">SMAA</string> | 451 | <string name="anti_aliasing_smaa">SMAA</string> |
| 293 | 452 | ||
| 453 | <!-- Screen Layouts --> | ||
| 294 | <string name="screen_layout_auto">ìžë™</string> | 454 | <string name="screen_layout_auto">ìžë™</string> |
| 455 | <string name="screen_layout_sensor_landscape">가로 ê³ ì • (ë°©í–¥ ê°ì§€)</string> | ||
| 456 | <string name="screen_layout_landscape">가로</string> | ||
| 457 | <string name="screen_layout_reverse_landscape">가로 ê³ ì • (ì—ë°©í–¥ ê³ ì •)</string> | ||
| 458 | <string name="screen_layout_sensor_portrait">세로 ê³ ì • (ë°©í–¥ ê°ì§€)</string> | ||
| 459 | <string name="screen_layout_portrait">세로</string> | ||
| 460 | <string name="screen_layout_reverse_portrait">세로 ê³ ì • (ì—ë°©í–¥ ê³ ì •)</string> | ||
| 295 | 461 | ||
| 296 | <!-- Aspect Ratios --> | 462 | <!-- Aspect Ratios --> |
| 297 | <string name="ratio_default">기본 (16:9)</string> | 463 | <string name="ratio_default">기본 (16:9)</string> |
| @@ -300,6 +466,10 @@ | |||
| 300 | <string name="ratio_force_sixteen_ten">ê°•ì œ 16:10</string> | 466 | <string name="ratio_force_sixteen_ten">ê°•ì œ 16:10</string> |
| 301 | <string name="ratio_stretch">í™”ë©´ì— ë§žì¶¤</string> | 467 | <string name="ratio_stretch">í™”ë©´ì— ë§žì¶¤</string> |
| 302 | 468 | ||
| 469 | <!-- CPU Backend --> | ||
| 470 | <string name="cpu_backend_dynarmic">Dynarmic (ëŠë¦¼)</string> | ||
| 471 | <string name="cpu_backend_nce">네ì´í‹°ë¸Œ 코드 실행 (NCE)</string> | ||
| 472 | |||
| 303 | <!-- CPU Accuracy --> | 473 | <!-- CPU Accuracy --> |
| 304 | <string name="cpu_accuracy_accurate">ì •í™•í•¨</string> | 474 | <string name="cpu_accuracy_accurate">ì •í™•í•¨</string> |
| 305 | <string name="cpu_accuracy_unsafe">최ì í™” (ì•ˆì „í•˜ì§€ 않ìŒ)</string> | 475 | <string name="cpu_accuracy_unsafe">최ì í™” (ì•ˆì „í•˜ì§€ 않ìŒ)</string> |
| @@ -327,14 +497,29 @@ | |||
| 327 | <string name="theme_mode_light">ë¼ì´íЏ 모드</string> | 497 | <string name="theme_mode_light">ë¼ì´íЏ 모드</string> |
| 328 | <string name="theme_mode_dark">ë‹¤í¬ ëª¨ë“œ</string> | 498 | <string name="theme_mode_dark">ë‹¤í¬ ëª¨ë“œ</string> |
| 329 | 499 | ||
| 500 | <!-- Audio output engines --> | ||
| 501 | <string name="oboe">oboe</string> | ||
| 502 | <string name="cubeb">cubeb</string> | ||
| 503 | |||
| 504 | <!-- Anisotropic filtering options --> | ||
| 505 | <string name="multiplier_two">2x</string> | ||
| 506 | <string name="multiplier_four">4x</string> | ||
| 507 | <string name="multiplier_eight">8x</string> | ||
| 508 | <string name="multiplier_sixteen">16x</string> | ||
| 509 | |||
| 330 | <!-- Black backgrounds theme --> | 510 | <!-- Black backgrounds theme --> |
| 331 | <string name="use_black_backgrounds">ê²€ì • ë°°ê²½</string> | 511 | <string name="use_black_backgrounds">ê²€ì • ë°°ê²½</string> |
| 332 | <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마를 ì‚¬ìš©í• ë•ŒëŠ” ê²€ì • ë°°ê²½ì„ ì 용합니다.</string> | 512 | <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마 사용 시 ê²€ì • ë°°ê²½ì„ ì 용합니다.</string> |
| 333 | 513 | ||
| 514 | <!-- Picture-In-Picture --> | ||
| 515 | <string name="picture_in_picture">픽처 ì¸ í”½ì²˜ (Picture-in-Picture)</string> | ||
| 516 | <string name="picture_in_picture_description">ì•±ì„ ë°±ê·¸ë¼ìš´ë“œì—서 ì‹¤í–‰í• ë•Œ ì°½ì„ ìµœì†Œí™”í•©ë‹ˆë‹¤.</string> | ||
| 517 | <string name="pause">ì¼ì‹œì¤‘ì§€</string> | ||
| 518 | <string name="play">재ìƒ</string> | ||
| 334 | <string name="mute">ìŒì†Œê±°</string> | 519 | <string name="mute">ìŒì†Œê±°</string> |
| 335 | <string name="unmute">ìŒì†Œê±° í•´ì œ</string> | 520 | <string name="unmute">ìŒì†Œê±° í•´ì œ</string> |
| 336 | 521 | ||
| 337 | <!-- Licenses screen strings --> | 522 | <!-- Licenses screen strings --> |
| 338 | <string name="licenses">ë¼ì´ì„¼ìФ</string> | 523 | <string name="licenses">ë¼ì´ì„¼ìФ</string> |
| 339 | <string name="license_fidelityfx_fsr_description">AMDì˜ ê³ í’ˆì§ˆ 업스케ì¼ë§</string> | 524 | <string name="license_fidelityfx_fsr_description">AMD ê³ í’ˆì§ˆ 업스케ì¼ë§</string> |
| 340 | </resources> | 525 | </resources> |
diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml index 3162a9d41..e92dc62d9 100644 --- a/src/android/app/src/main/res/values-nb/strings.xml +++ b/src/android/app/src/main/res/values-nb/strings.xml | |||
| @@ -157,7 +157,6 @@ | |||
| 157 | <string name="renderer_reactive_flushing_description">Forbedrer gjengivelsesnøyaktigheten i enkelte spill på bekostning av ytelsen.</string> | 157 | <string name="renderer_reactive_flushing_description">Forbedrer gjengivelsesnøyaktigheten i enkelte spill på bekostning av ytelsen.</string> |
| 158 | <string name="use_disk_shader_cache">Disk shader-hurtigbuffer</string> | 158 | <string name="use_disk_shader_cache">Disk shader-hurtigbuffer</string> |
| 159 | <string name="use_disk_shader_cache_description">Reduserer hakking ved å lagre og laste inn genererte shaders lokalt.</string> | 159 | <string name="use_disk_shader_cache_description">Reduserer hakking ved å lagre og laste inn genererte shaders lokalt.</string> |
| 160 | |||
| 161 | <!-- Debug settings strings --> | 160 | <!-- Debug settings strings --> |
| 162 | <string name="cpu">CPU</string> | 161 | <string name="cpu">CPU</string> |
| 163 | <string name="renderer_api">API</string> | 162 | <string name="renderer_api">API</string> |
| @@ -184,13 +183,16 @@ | |||
| 184 | <string name="string_null">Null</string> | 183 | <string name="string_null">Null</string> |
| 185 | <string name="string_import">Importer</string> | 184 | <string name="string_import">Importer</string> |
| 186 | <string name="export">Eksporter</string> | 185 | <string name="export">Eksporter</string> |
| 186 | <string name="install">Installer</string> | ||
| 187 | <string name="delete">Slett</string> | ||
| 188 | <string name="start">Start</string> | ||
| 189 | <string name="clear">Fjern</string> | ||
| 187 | <!-- GPU driver installation --> | 190 | <!-- GPU driver installation --> |
| 188 | <string name="select_gpu_driver">Velg GPU-driver</string> | 191 | <string name="select_gpu_driver">Velg GPU-driver</string> |
| 189 | <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string> | 192 | <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string> |
| 190 | <string name="select_gpu_driver_install">Installer</string> | 193 | <string name="select_gpu_driver_install">Installer</string> |
| 191 | <string name="select_gpu_driver_default">Standard</string> | 194 | <string name="select_gpu_driver_default">Standard</string> |
| 192 | <string name="select_gpu_driver_use_default">Bruk av standard GPU-driver</string> | 195 | <string name="select_gpu_driver_use_default">Bruk av standard GPU-driver</string> |
| 193 | <string name="select_gpu_driver_error">Ugyldig driver valgt, bruker systemstandard!</string> | ||
| 194 | <string name="system_gpu_driver">Systemets GPU-driver</string> | 196 | <string name="system_gpu_driver">Systemets GPU-driver</string> |
| 195 | <string name="installing_driver">Installerer driver...</string> | 197 | <string name="installing_driver">Installerer driver...</string> |
| 196 | 198 | ||
| @@ -202,7 +204,12 @@ | |||
| 202 | <string name="preferences_audio">Lyd</string> | 204 | <string name="preferences_audio">Lyd</string> |
| 203 | <string name="preferences_theme">Tema og farge</string> | 205 | <string name="preferences_theme">Tema og farge</string> |
| 204 | <string name="preferences_debug">Feilsøk</string> | 206 | <string name="preferences_debug">Feilsøk</string> |
| 205 | 207 | <!-- Game properties --> | |
| 208 | <string name="info">Info</string> | ||
| 209 | <string name="path">Sti</string> | ||
| 210 | <string name="developer">Utvikler</string> | ||
| 211 | <string name="version">Versjon</string> | ||
| 212 | <string name="add_ons">Tilleggsprogrammer</string> | ||
| 206 | <!-- ROM loading errors --> | 213 | <!-- ROM loading errors --> |
| 207 | <string name="loader_error_encrypted">ROM-en din er kryptert</string> | 214 | <string name="loader_error_encrypted">ROM-en din er kryptert</string> |
| 208 | <string name="loader_error_encrypted_keys_description"><![CDATA[Vennligst sørg for at <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> filen er installert slik at spillene kan dekrypteres.]]></string> | 215 | <string name="loader_error_encrypted_keys_description"><![CDATA[Vennligst sørg for at <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> filen er installert slik at spillene kan dekrypteres.]]></string> |
| @@ -229,6 +236,7 @@ | |||
| 229 | <string name="emulation_pause">Pause emulering</string> | 236 | <string name="emulation_pause">Pause emulering</string> |
| 230 | <string name="emulation_unpause">Ta emuleringen ut av pause</string> | 237 | <string name="emulation_unpause">Ta emuleringen ut av pause</string> |
| 231 | <string name="emulation_input_overlay">Overlay-alternativer</string> | 238 | <string name="emulation_input_overlay">Overlay-alternativer</string> |
| 239 | <string name="touchscreen">Touch-skjerm</string> | ||
| 232 | 240 | ||
| 233 | <string name="load_settings">Laster inn innstillinger...</string> | 241 | <string name="load_settings">Laster inn innstillinger...</string> |
| 234 | 242 | ||
| @@ -254,6 +262,7 @@ | |||
| 254 | <string name="region_korea">Korea</string> | 262 | <string name="region_korea">Korea</string> |
| 255 | <string name="region_taiwan">Taiwan</string> | 263 | <string name="region_taiwan">Taiwan</string> |
| 256 | 264 | ||
| 265 | <string name="memory_byte_shorthand">B</string> | ||
| 257 | <string name="memory_gigabyte">GB</string> | 266 | <string name="memory_gigabyte">GB</string> |
| 258 | <!-- Renderer APIs --> | 267 | <!-- Renderer APIs --> |
| 259 | <string name="renderer_vulkan">Vulkan</string> | 268 | <string name="renderer_vulkan">Vulkan</string> |
| @@ -291,8 +300,8 @@ | |||
| 291 | <string name="anti_aliasing_fxaa">FXAA</string> | 300 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 292 | <string name="anti_aliasing_smaa">SMAA</string> | 301 | <string name="anti_aliasing_smaa">SMAA</string> |
| 293 | 302 | ||
| 303 | <!-- Screen Layouts --> | ||
| 294 | <string name="screen_layout_auto">Auto</string> | 304 | <string name="screen_layout_auto">Auto</string> |
| 295 | |||
| 296 | <!-- Aspect Ratios --> | 305 | <!-- Aspect Ratios --> |
| 297 | <string name="ratio_default">Standard (16:9)</string> | 306 | <string name="ratio_default">Standard (16:9)</string> |
| 298 | <string name="ratio_force_four_three">Tving 4:3</string> | 307 | <string name="ratio_force_four_three">Tving 4:3</string> |
| @@ -327,6 +336,12 @@ | |||
| 327 | <string name="theme_mode_light">Lys</string> | 336 | <string name="theme_mode_light">Lys</string> |
| 328 | <string name="theme_mode_dark">Mørk</string> | 337 | <string name="theme_mode_dark">Mørk</string> |
| 329 | 338 | ||
| 339 | <!-- Anisotropic filtering options --> | ||
| 340 | <string name="multiplier_two">2x</string> | ||
| 341 | <string name="multiplier_four">4x</string> | ||
| 342 | <string name="multiplier_eight">8x</string> | ||
| 343 | <string name="multiplier_sixteen">16x</string> | ||
| 344 | |||
| 330 | <!-- Black backgrounds theme --> | 345 | <!-- Black backgrounds theme --> |
| 331 | <string name="use_black_backgrounds">Svart bakgrunn</string> | 346 | <string name="use_black_backgrounds">Svart bakgrunn</string> |
| 332 | <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string> | 347 | <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string> |
diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml index f4d9920c2..fbd0ad7e9 100644 --- a/src/android/app/src/main/res/values-pl/strings.xml +++ b/src/android/app/src/main/res/values-pl/strings.xml | |||
| @@ -157,7 +157,6 @@ | |||
| 157 | <string name="renderer_reactive_flushing_description">Poprawia jakość renderowania w kilku grach, kosztem wydajności.</string> | 157 | <string name="renderer_reactive_flushing_description">Poprawia jakość renderowania w kilku grach, kosztem wydajności.</string> |
| 158 | <string name="use_disk_shader_cache">Pamięć podręczna shaderów</string> | 158 | <string name="use_disk_shader_cache">Pamięć podręczna shaderów</string> |
| 159 | <string name="use_disk_shader_cache_description">Zmniejsza przycięcia przez przechowywanie gotowych wygenerowanych plików oświetlenia w pamięci urządzenia.</string> | 159 | <string name="use_disk_shader_cache_description">Zmniejsza przycięcia przez przechowywanie gotowych wygenerowanych plików oświetlenia w pamięci urządzenia.</string> |
| 160 | |||
| 161 | <!-- Debug settings strings --> | 160 | <!-- Debug settings strings --> |
| 162 | <string name="cpu">CPU</string> | 161 | <string name="cpu">CPU</string> |
| 163 | <string name="renderer_api">Interfejs graficzny</string> | 162 | <string name="renderer_api">Interfejs graficzny</string> |
| @@ -183,13 +182,17 @@ | |||
| 183 | <string name="submit">Zatwierdź</string> | 182 | <string name="submit">Zatwierdź</string> |
| 184 | <string name="string_import">Importuj</string> | 183 | <string name="string_import">Importuj</string> |
| 185 | <string name="export">Eksportuj</string> | 184 | <string name="export">Eksportuj</string> |
| 185 | <string name="install">Zainstaluj</string> | ||
| 186 | <string name="delete">Usuń</string> | ||
| 187 | <string name="start">Start</string> | ||
| 188 | <string name="clear">Wyczyść</string> | ||
| 189 | <string name="custom">Losowy</string> | ||
| 186 | <!-- GPU driver installation --> | 190 | <!-- GPU driver installation --> |
| 187 | <string name="select_gpu_driver">Wybierz sterownik GPU </string> | 191 | <string name="select_gpu_driver">Wybierz sterownik GPU </string> |
| 188 | <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string> | 192 | <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string> |
| 189 | <string name="select_gpu_driver_install">Zainstaluj</string> | 193 | <string name="select_gpu_driver_install">Zainstaluj</string> |
| 190 | <string name="select_gpu_driver_default">Domyślne</string> | 194 | <string name="select_gpu_driver_default">Domyślne</string> |
| 191 | <string name="select_gpu_driver_use_default">Aktywny domyślny sterownik GPU</string> | 195 | <string name="select_gpu_driver_use_default">Aktywny domyślny sterownik GPU</string> |
| 192 | <string name="select_gpu_driver_error">Wybrano błędny sterownik, powrót do domyślnego. </string> | ||
| 193 | <string name="system_gpu_driver">Systemowy sterownik GPU</string> | 196 | <string name="system_gpu_driver">Systemowy sterownik GPU</string> |
| 194 | <string name="installing_driver">Instalowanie sterownika...</string> | 197 | <string name="installing_driver">Instalowanie sterownika...</string> |
| 195 | 198 | ||
| @@ -201,7 +204,12 @@ | |||
| 201 | <string name="preferences_audio">Dźwięk</string> | 204 | <string name="preferences_audio">Dźwięk</string> |
| 202 | <string name="preferences_theme">Motyw i kolor</string> | 205 | <string name="preferences_theme">Motyw i kolor</string> |
| 203 | <string name="preferences_debug">Debug</string> | 206 | <string name="preferences_debug">Debug</string> |
| 204 | 207 | <!-- Game properties --> | |
| 208 | <string name="info">Informacje</string> | ||
| 209 | <string name="path">Ścieżka</string> | ||
| 210 | <string name="developer">Deweloper</string> | ||
| 211 | <string name="version">Wersja</string> | ||
| 212 | <string name="add_ons">Dodatki</string> | ||
| 205 | <!-- ROM loading errors --> | 213 | <!-- ROM loading errors --> |
| 206 | <string name="loader_error_encrypted">Twój ROM jest zakodowany</string> | 214 | <string name="loader_error_encrypted">Twój ROM jest zakodowany</string> |
| 207 | <string name="loader_error_encrypted_keys_description"><![CDATA[Upewnij się że plik kluczy <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> jest zainstalowany aby gry mogły zostać odczytane.]]></string> | 215 | <string name="loader_error_encrypted_keys_description"><![CDATA[Upewnij się że plik kluczy <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> jest zainstalowany aby gry mogły zostać odczytane.]]></string> |
| @@ -228,6 +236,7 @@ | |||
| 228 | <string name="emulation_pause">Wstrzymaj emulacjÄ™</string> | 236 | <string name="emulation_pause">Wstrzymaj emulacjÄ™</string> |
| 229 | <string name="emulation_unpause">Wznów emulację</string> | 237 | <string name="emulation_unpause">Wznów emulację</string> |
| 230 | <string name="emulation_input_overlay">Opcje nakładki</string> | 238 | <string name="emulation_input_overlay">Opcje nakładki</string> |
| 239 | <string name="touchscreen">Ekran dotykowy</string> | ||
| 231 | 240 | ||
| 232 | <string name="load_settings">WczytujÄ™ ustawienia...</string> | 241 | <string name="load_settings">WczytujÄ™ ustawienia...</string> |
| 233 | 242 | ||
| @@ -253,6 +262,7 @@ | |||
| 253 | <string name="region_korea">Korea</string> | 262 | <string name="region_korea">Korea</string> |
| 254 | <string name="region_taiwan">Tajwan</string> | 263 | <string name="region_taiwan">Tajwan</string> |
| 255 | 264 | ||
| 265 | <string name="memory_byte_shorthand">B</string> | ||
| 256 | <string name="memory_gigabyte">GB</string> | 266 | <string name="memory_gigabyte">GB</string> |
| 257 | <!-- Renderer APIs --> | 267 | <!-- Renderer APIs --> |
| 258 | <string name="renderer_vulkan">Vulkan</string> | 268 | <string name="renderer_vulkan">Vulkan</string> |
| @@ -290,8 +300,8 @@ | |||
| 290 | <string name="anti_aliasing_fxaa">FXAA</string> | 300 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 291 | <string name="anti_aliasing_smaa">SMAA</string> | 301 | <string name="anti_aliasing_smaa">SMAA</string> |
| 292 | 302 | ||
| 303 | <!-- Screen Layouts --> | ||
| 293 | <string name="screen_layout_auto">Automatyczny</string> | 304 | <string name="screen_layout_auto">Automatyczny</string> |
| 294 | |||
| 295 | <!-- Aspect Ratios --> | 305 | <!-- Aspect Ratios --> |
| 296 | <string name="ratio_default">Domyślne (16:9)</string> | 306 | <string name="ratio_default">Domyślne (16:9)</string> |
| 297 | <string name="ratio_force_four_three">WymuÅ› 4:3</string> | 307 | <string name="ratio_force_four_three">WymuÅ› 4:3</string> |
| @@ -326,6 +336,12 @@ | |||
| 326 | <string name="theme_mode_light">Jasny</string> | 336 | <string name="theme_mode_light">Jasny</string> |
| 327 | <string name="theme_mode_dark">Ciemny</string> | 337 | <string name="theme_mode_dark">Ciemny</string> |
| 328 | 338 | ||
| 339 | <!-- Anisotropic filtering options --> | ||
| 340 | <string name="multiplier_two">2x</string> | ||
| 341 | <string name="multiplier_four">4x</string> | ||
| 342 | <string name="multiplier_eight">8x</string> | ||
| 343 | <string name="multiplier_sixteen">16x</string> | ||
| 344 | |||
| 329 | <!-- Black backgrounds theme --> | 345 | <!-- Black backgrounds theme --> |
| 330 | <string name="use_black_backgrounds">Czarne tła</string> | 346 | <string name="use_black_backgrounds">Czarne tła</string> |
| 331 | <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string> | 347 | <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string> |
diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml index 8888fc750..a87eb11e4 100644 --- a/src/android/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
| 2 | <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> | 2 | <resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> |
| 3 | 3 | ||
| 4 | <string name="app_disclaimer">Este software executa jogos do console Nintendo Switch. Não estão inclusos nem jogos ou chaves. <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> | 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[<b> prod.keys </b>]]> no armazenamento de seu dispositivo.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Saiba mais</a>]]></string> |
| 5 | <string name="emulation_notification_channel_name">Emulação está Ativa</string> | 5 | <string name="emulation_notification_channel_name">A emulação está Ativa</string> |
| 6 | <string name="emulation_notification_channel_description">Mostra uma notificação permanente enquanto a emulação estiver em andamento.</string> | 6 | <string name="emulation_notification_channel_description">Mostra uma notificação permanente enquanto a emulação estiver em andamento.</string> |
| 7 | <string name="emulation_notification_running">Yuzu está em execução </string> | 7 | <string name="emulation_notification_running">O Yuzu está em execução </string> |
| 8 | <string name="notice_notification_channel_name">Notificações e erros</string> | 8 | <string name="notice_notification_channel_name">Notificações e erros</string> |
| 9 | <string name="notice_notification_channel_description">Mostra notificações quando algo dá errado.</string> | 9 | <string name="notice_notification_channel_description">Mostra notificações quando algo dá errado.</string> |
| 10 | <string name="notification_permission_not_granted">Acesso às notificações não concedido!</string> | 10 | <string name="notification_permission_not_granted">Acesso às notificações não concedido!</string> |
| @@ -17,7 +17,7 @@ | |||
| 17 | <string name="keys_description">Selecione seu arquivo <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">Selecione as Keys</string> | 18 | <string name="select_keys">Selecione as Keys</string> |
| 19 | <string name="games">Jogos</string> | 19 | <string name="games">Jogos</string> |
| 20 | <string name="games_description">Seleciona sua pasta <b>Jogos</b> com o botão abaixo.</string> | 20 | <string name="games_description">Selecione 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.\nAproveite seus jogos!</string> | 22 | <string name="done_description">Tudo pronto.\nAproveite seus jogos!</string> |
| 23 | <string name="text_continue">Continuar</string> | 23 | <string name="text_continue">Continuar</string> |
| @@ -34,61 +34,67 @@ | |||
| 34 | <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> | 34 | <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> |
| 35 | <string name="search_and_filter_games">Procura e filtra jogos.</string> | 35 | <string name="search_and_filter_games">Procura e filtra jogos.</string> |
| 36 | <string name="select_games_folder">Seleciona a pasta de jogos.</string> | 36 | <string name="select_games_folder">Seleciona a pasta de jogos.</string> |
| 37 | <string name="manage_game_folders">Gerencie as pastas de jogos</string> | ||
| 37 | <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> | 38 | <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> |
| 38 | <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> | 39 | <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> |
| 39 | <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> | 40 | <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> |
| 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 41 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| 41 | <string name="home_search_games">Procurar jogos</string> | 42 | <string name="home_search_games">Procurar jogos</string> |
| 42 | <string name="search_settings">Procurar nas definições</string> | 43 | <string name="search_settings">Procurar nas configurações</string> |
| 43 | <string name="games_dir_selected">Pasta de Jogos selecionada</string> | 44 | <string name="games_dir_selected">Pasta de jogos selecionada</string> |
| 44 | <string name="install_prod_keys">Instala prod.keys</string> | 45 | <string name="install_prod_keys">Instalar prod.keys</string> |
| 45 | <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string> | 46 | <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string> |
| 46 | <string name="install_prod_keys_warning">Ignorar a adição de chaves?</string> | 47 | <string name="install_prod_keys_warning">Ignorar a adição de chaves?</string> |
| 47 | <string name="install_prod_keys_warning_description">São necessárias chaves válidas para emular jogos comerciais. Somente aplicativos homebrew funcionarão se você continuar.</string> | 48 | <string name="install_prod_keys_warning_description">São necessárias chaves válidas para emular jogos comerciais. Somente aplicativos homebrew funcionarão se você continuar.</string> |
| 48 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#Guia de introdução</string> | 49 | <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> |
| 49 | <string name="notifications">Notificações</string> | 50 | <string name="notifications">Notificações</string> |
| 50 | <string name="notifications_description">Conceda a permissão de notificação com o botão abaixo.</string> | 51 | <string name="notifications_description">Conceda a permissão de notificação com o botão abaixo.</string> |
| 51 | <string name="give_permission">Conceda permissão</string> | 52 | <string name="give_permission">Conceder permissão</string> |
| 52 | <string name="notification_warning">Saltar a concessão da permissão de notificação?</string> | 53 | <string name="notification_warning">Ignorar a concessão da permissão de notificação?</string> |
| 53 | <string name="notification_warning_description">Yuzu não conseguirá te notificar de informações importantes. </string> | 54 | <string name="notification_warning_description">Yuzu não conseguirá te notificar de informações importantes. </string> |
| 54 | <string name="permission_denied">Permissão negada</string> | 55 | <string name="permission_denied">Permissão negada</string> |
| 55 | <string name="permission_denied_description">Você negou essa permissão muitas vezes e agora precisa concedê-la manualmente nas configurações do sistema.</string> | 56 | <string name="permission_denied_description">Você negou essa permissão muitas vezes e agora precisa concedê-la manualmente nas configurações do sistema.</string> |
| 56 | <string name="about">Sobre</string> | 57 | <string name="about">Sobre</string> |
| 57 | <string name="about_description">Versão de compilação, créditos e mais</string> | 58 | <string name="about_description">Versão de compilação, créditos e mais</string> |
| 58 | <string name="warning_help">Ajuda</string> | 59 | <string name="warning_help">Ajuda</string> |
| 59 | <string name="warning_skip">Saltar</string> | 60 | <string name="warning_skip">Ignorar</string> |
| 60 | <string name="warning_cancel">Cancelar</string> | 61 | <string name="warning_cancel">Cancelar</string> |
| 61 | <string name="install_amiibo_keys">Instala chaves Amiibo</string> | 62 | <string name="install_amiibo_keys">Instalar chaves Amiibo</string> |
| 62 | <string name="install_amiibo_keys_description">Necessário para usares Amiibo no jogo</string> | 63 | <string name="install_amiibo_keys_description">Necessário para usar Amiibos em um jogo</string> |
| 63 | <string name="invalid_keys_file">Ficheiro de chaves inválido</string> | 64 | <string name="invalid_keys_file">Arquivo de chaves selecionado inválido</string> |
| 64 | <string name="install_keys_success">Chaves instaladas com sucesso</string> | 65 | <string name="install_keys_success">Chaves instaladas com sucesso</string> |
| 65 | <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string> | 66 | <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string> |
| 66 | <string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .keys e tente novamente.</string> | 67 | <string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .keys e tente novamente.</string> |
| 67 | <string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .bin e tente novamente.</string> | 68 | <string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .bin e tente novamente.</string> |
| 68 | <string name="invalid_keys_error">Chaves de encriptação inválidas</string> | 69 | <string name="invalid_keys_error">Chaves de encriptação inválidas</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> | 71 | <string name="install_keys_failure_description">O arquivo selecionado está incorreto ou corrompido. Por favor extraia suas chaves novamente.</string> |
| 72 | <string name="gpu_driver_manager">Gerenciador de driver de GPU</string> | ||
| 71 | <string name="install_gpu_driver">Instala driver para GPU</string> | 73 | <string name="install_gpu_driver">Instala driver para GPU</string> |
| 72 | <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> | 74 | <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> |
| 73 | <string name="advanced_settings">Definições avançadas</string> | 75 | <string name="advanced_settings">Configurações avançadas</string> |
| 74 | <string name="advanced_settings_game">Definições avançadas: %1$s</string> | 76 | <string name="advanced_settings_game">Configurações avançadas: %1$s</string> |
| 75 | <string name="settings_description">Configura definições do emulador</string> | 77 | <string name="settings_description">Configure opções do emulador</string> |
| 76 | <string name="search_recently_played">Jogado recentemente</string> | 78 | <string name="search_recently_played">Jogado recentemente</string> |
| 77 | <string name="search_recently_added">Adicionado recentemente</string> | 79 | <string name="search_recently_added">Adicionado recentemente</string> |
| 78 | <string name="search_retail">Jogos comerciais</string> | 80 | <string name="search_retail">Jogos comerciais</string> |
| 79 | <string name="search_homebrew">Homebrew</string> | 81 | <string name="search_homebrew">Homebrew</string> |
| 80 | <string name="open_user_folder">Abre a pasta Yuzu</string> | 82 | <string name="open_user_folder">Abrir a pasta do Yuzu</string> |
| 81 | <string name="open_user_folder_description">Gere os ficheiro internos do Yuzu</string> | 83 | <string name="open_user_folder_description">Gerencie os arquivos internos do Yuzu</string> |
| 82 | <string name="theme_and_color_description">Modifica a aparência da App</string> | 84 | <string name="theme_and_color_description">Altere a aparência do aplicativo</string> |
| 83 | <string name="no_file_manager">Nenhum gestor de ficheiros encontrado</string> | 85 | <string name="no_file_manager">Nenhum gerenciador de arquivos encontrado</string> |
| 84 | <string name="notification_no_directory_link">ImpossÃvel abrir pasta Yuzu</string> | 86 | <string name="notification_no_directory_link">Não foi possÃvel abrir a pasta do Yuzu</string> |
| 85 | <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string> | 87 | <string name="notification_no_directory_link_description">Por favor localize a pasta do usuário com o painel lateral do gerenciador de arquivos manualmente.</string> |
| 86 | <string name="manage_save_data">Gerir dados guardados</string> | 88 | <string name="manage_save_data">Gerenciar os dados salvos dos jogos</string> |
| 87 | <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string> | 89 | <string name="manage_save_data_description">Dados salvos encontrados. Por favor selecione uma opção abaixo.</string> |
| 88 | <string name="import_export_saves_description">Importa ou exporta dados guardados</string> | 90 | <string name="import_save_warning">Importar dados salvos</string> |
| 91 | <string name="import_save_warning_description">Isso irá sobrescrever seus dados salvos com o arquivo selecionado. Você tem certeza que quer continuar?</string> | ||
| 92 | <string name="import_export_saves_description">Importa ou exporta arquivos de dados salvos</string> | ||
| 93 | <string name="save_files_importing">Importando dados salvos...</string> | ||
| 94 | <string name="save_files_exporting">Exportando arquivos de dados salvos...</string> | ||
| 89 | <string name="save_file_imported_success">Importado com sucesso</string> | 95 | <string name="save_file_imported_success">Importado com sucesso</string> |
| 90 | <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string> | 96 | <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados salvos inválida</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> | 97 | <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta deve ser a ID do jogo.</string> |
| 92 | <string name="import_saves">Importar</string> | 98 | <string name="import_saves">Importar</string> |
| 93 | <string name="export_saves">Exportar</string> | 99 | <string name="export_saves">Exportar</string> |
| 94 | <string name="install_firmware">Instalar firmware</string> | 100 | <string name="install_firmware">Instalar firmware</string> |
| @@ -96,55 +102,89 @@ | |||
| 96 | <string name="firmware_installing">Instalando firmware</string> | 102 | <string name="firmware_installing">Instalando firmware</string> |
| 97 | <string name="firmware_installed_success">Firmware instalado com sucesso.</string> | 103 | <string name="firmware_installed_success">Firmware instalado com sucesso.</string> |
| 98 | <string name="firmware_installed_failure">Falha na instalação do firmware</string> | 104 | <string name="firmware_installed_failure">Falha na instalação do firmware</string> |
| 99 | <string name="firmware_installed_failure_description">Cofirma que os ficheiros firmware nca estão no root do finheiro zip e tenta de novo.</string> | 105 | <string name="firmware_installed_failure_description">Verifique se os arquivos nca do firmware estão na raiz do arquivo zip e tente novamente.</string> |
| 100 | <string name="share_log">Compartilhe registros de debug.</string> | 106 | <string name="share_log">Compartilhar registros de debug</string> |
| 101 | <string name="share_log_description">Compartilhe o arquivo de registro do yuzu para obter ajuda com problemas</string> | 107 | <string name="share_log_description">Compartilhe o arquivo de registro do yuzu para obter ajuda com problemas</string> |
| 102 | <string name="share_log_missing">Arquivo de registro não encontrado</string> | 108 | <string name="share_log_missing">Arquivo de registro não encontrado</string> |
| 103 | <string name="install_game_content">Instalar conteúdo de jogos</string> | 109 | <string name="install_game_content">Instalar conteúdo de jogos</string> |
| 104 | <string name="install_game_content_description">Instalar atualizações de jogos ou DLC</string> | 110 | <string name="install_game_content_description">Instala atualizações de jogos ou DLC</string> |
| 105 | <string name="installing_game_content">A instalar conteúdo...</string> | 111 | <string name="installing_game_content">Instalando conteúdo...</string> |
| 106 | <string name="install_game_content_failure">Erro ao instalar ficheiro(s) para NAND</string> | 112 | <string name="install_game_content_failure">Erro ao instalar arquivo(s) na NAND</string> |
| 107 | <string name="install_game_content_failure_description">Por favor confitma que o conteúdo(s) é válido e que as prod.keys estão instaladas.</string> | 113 | <string name="install_game_content_failure_description">Por favor certifique-se de que o(s) conteúdo(s) é (são) válido(s) e que as prod.keys estão instaladas.</string> |
| 108 | <string name="install_game_content_failure_base">A instalação de jogos base não é permitida para evitar possÃveis conflitos.</string> | 114 | <string name="install_game_content_failure_base">A instalação de jogos base não é permitida para evitar possÃveis conflitos.</string> |
| 109 | <string name="install_game_content_failure_file_extension">Sò conteúdos NSP e XCI são suportados. Por favor verifica que o conteúdo(s) do jogo são válidos.</string> | 115 | <string name="install_game_content_failure_file_extension">Somente conteúdos NSP e XCI são suportados. Por favor verifique se o(s) conteúdo(s) do jogo é (são) válido(s).</string> |
| 110 | <string name="install_game_content_failed_count">%1$d erro(s) de instalação</string> | 116 | <string name="install_game_content_failed_count">%1$d erro(s) de instalação</string> |
| 111 | <string name="install_game_content_success">Conteúdo(s) de jogo instalados com sucesso</string> | 117 | <string name="install_game_content_success">Conteúdo(s) de jogo instalado(s) com sucesso</string> |
| 112 | <string name="install_game_content_success_install">%1$d instalado com sucesso</string> | 118 | <string name="install_game_content_success_install">%1$d instalado com sucesso</string> |
| 113 | <string name="install_game_content_success_overwrite">%1$d substituÃda com êxito</string> | 119 | <string name="install_game_content_success_overwrite">%1$d substituÃdo com sucesso</string> |
| 114 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> | 120 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> |
| 115 | <string name="custom_driver_not_supported">Drivers personalizados não suportados</string> | 121 | <string name="custom_driver_not_supported">Drivers personalizados não suportados</string> |
| 116 | <string name="custom_driver_not_supported_description">Carrea«gamento de drivers personalizados não é suportado pr este dispositivo. \nCheck verifica esta opção de futuro para confirmar se o suporte foi adicionado!</string> | 122 | <string name="custom_driver_not_supported_description">Carregamento de drivers personalizados não suportado para este dispositivo no momento.\nVerifique esse opção novamente no futuro para ver se o suporte foi adicionado!</string> |
| 117 | <string name="manage_yuzu_data">Administrar dados yuzu</string> | 123 | <string name="manage_yuzu_data">Administrar dados do yuzu</string> |
| 118 | <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> | 124 | <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> |
| 119 | <string name="share_save_file">Partilha ficheiro duardado</string> | 125 | <string name="share_save_file">Compartilhar arquivo de dados salvos</string> |
| 120 | <string name="export_save_failed">Erro ao exportar dados guardados</string> | 126 | <string name="export_save_failed">Erro ao exportar arquivo de dados salvos</string> |
| 127 | <string name="game_folders">Pastas de jogos</string> | ||
| 128 | <string name="deep_scan">Varredura profunda</string> | ||
| 129 | <string name="add_game_folder">Adicionar pasta de jogo</string> | ||
| 130 | <string name="folder_already_added">Esta pasta já foi adicionada!</string> | ||
| 131 | <string name="game_folder_properties">Propriedades da pasta de jogo</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="one">Falha ao importar dado salvo de %d</item> | ||
| 134 | <item quantity="many">Falha ao importar dados salvos de %d</item> | ||
| 135 | <item quantity="other">Falha ao importar dados salvos de %d</item> | ||
| 136 | </plurals> | ||
| 137 | <plurals name="saves_import_success"> | ||
| 138 | <item quantity="one">Dado salvo de %d importado com sucesso</item> | ||
| 139 | <item quantity="many">Dados salvos de %d importados com sucesso</item> | ||
| 140 | <item quantity="other">Dados salvos de %d importados com sucesso</item> | ||
| 141 | </plurals> | ||
| 142 | <string name="no_save_data_found">Dados salvos não encontrados</string> | ||
| 143 | |||
| 144 | <!-- Applet launcher strings --> | ||
| 145 | <string name="applets">Launcher de miniaplicativos</string> | ||
| 146 | <string name="applets_description">Inicia miniaplicativos do sistema usando o firmware instalado</string> | ||
| 147 | <string name="applets_error_firmware">Firmware não instalado</string> | ||
| 148 | <string name="applets_error_applet">Miniaplicativo não disponÃvel</string> | ||
| 149 | <string name="applets_error_description"><![CDATA[Por favor verifique se o arquivo 1prod.keys1 e o 2firmware2 estão instalados e tente novamente.]]></string> | ||
| 150 | <string name="album_applet">Ãlbum</string> | ||
| 151 | <string name="album_applet_description">Visualize imagens armazenadas na pasta de capturas de telas do usuário com o visualizador de imagens do sistema</string> | ||
| 152 | <string name="mii_edit_applet">Editor de Mii</string> | ||
| 153 | <string name="mii_edit_applet_description">Visualize e edite os Miis com o editor do sistema</string> | ||
| 154 | <string name="cabinet_applet">Arquivo</string> | ||
| 155 | <string name="cabinet_applet_description">Edite e delete dados armazenados nos amiibos</string> | ||
| 156 | <string name="cabinet_launcher">Inicializador do Arquivo</string> | ||
| 157 | <string name="cabinet_nickname_and_owner">Apelido e configurações do proprietário</string> | ||
| 158 | <string name="cabinet_game_data_eraser">Apagar dados de jogo</string> | ||
| 159 | <string name="cabinet_restorer">Restaurar</string> | ||
| 160 | <string name="cabinet_formatter">Formatar</string> | ||
| 121 | 161 | ||
| 122 | <!-- About screen strings --> | 162 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia não é real</string> | 163 | <string name="gaia_is_not_real">Gaia não é real</string> |
| 124 | <string name="copied_to_clipboard">Copiado para a área de transferência</string> | 164 | <string name="copied_to_clipboard">Copiado para a área de transferência</string> |
| 125 | <string name="about_app_description">Um emulador Switch de código aberto</string> | 165 | <string name="about_app_description">Um emulador de Switch de código aberto</string> |
| 126 | <string name="contributors">Contribuidores</string> | 166 | <string name="contributors">Colaboradores</string> |
| 127 | <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string> | 167 | <string name="contributors_description">Feito com \u2764 da equipe do Yuzu</string> |
| 128 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | 168 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> |
| 129 | <string name="licenses_description">Projetos que tornam o yuzu para Android possÃvel</string> | 169 | <string name="licenses_description">Projetos que tornam o yuzu para Android possÃvel</string> |
| 130 | <string name="build">Versão</string> | 170 | <string name="build">Versão</string> |
| 131 | <string name="user_data">Dado de utilizados</string> | 171 | <string name="user_data">Dados do usuário</string> |
| 132 | <string name="user_data_description">Importar/exportar todos dados da aplicação data.\n\n Ao importar dados do utilizados, todos os dados existentes do utilizados serão excluÃdos!</string> | 172 | <string name="user_data_description">Importar/exportar todos os dados do aplicativo.\n\n Ao importar dados de usuário, todos os dados existentes do usuário serão excluÃdos!</string> |
| 133 | <string name="exporting_user_data">A exportar dados de utilizados...</string> | 173 | <string name="exporting_user_data">Exportando dados do usuário...</string> |
| 134 | <string name="importing_user_data">A importar dados de utilizador...</string> | 174 | <string name="importing_user_data">Importando dados do usuário...</string> |
| 135 | <string name="import_user_data">Importar dados de utilizados...</string> | 175 | <string name="import_user_data">Importar dados do usuário</string> |
| 136 | <string name="invalid_yuzu_backup">Backup yuzu inválido</string> | 176 | <string name="invalid_yuzu_backup">Backup do yuzu inválido</string> |
| 137 | <string name="user_data_export_success">Dados de utilizados exportados com sucesso</string> | 177 | <string name="user_data_export_success">Dados de usuário exportados com sucesso</string> |
| 138 | <string name="user_data_import_success">Dados de utilizador importado com sucesso</string> | 178 | <string name="user_data_import_success">Dados de usuário importados com sucesso</string> |
| 139 | <string name="user_data_export_cancelled">Exportação cancelada</string> | 179 | <string name="user_data_export_cancelled">Exportação cancelada</string> |
| 140 | <string name="user_data_import_failed_description">Verifiqua se as pastas de dados do utilizados estão na raiz da pasta zip e contêm um arquivo de configuração em config/config.ini e tenta novamente.</string> | 180 | <string name="user_data_import_failed_description">Verifiqua se as pastas de dados do usuário estão na raiz da pasta zip e contêm um arquivo de configuração em config/config.ini e tente novamente.</string> |
| 141 | <string name="support_link">https://discord.gg/u77vRWY</string> | 181 | <string name="support_link">https://discord.gg/u77vRWY</string> |
| 142 | <string name="website_link">https://yuzu-emu.org/</string> | 182 | <string name="website_link">https://yuzu-emu.org/</string> |
| 143 | <string name="github_link">https://github.com/yuzu-emu</string> | 183 | <string name="github_link">https://github.com/yuzu-emu</string> |
| 144 | 184 | ||
| 145 | <!-- Early access upgrade strings --> | 185 | <!-- Early access upgrade strings --> |
| 146 | <string name="early_access">Acesso antecipado</string> | 186 | <string name="early_access">Acesso Antecipado</string> |
| 147 | <string name="get_early_access">Obtém Acesso Antecipado</string> | 187 | <string name="get_early_access">Obtenha o Acesso Antecipado</string> |
| 148 | <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> | 188 | <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> |
| 149 | <string name="get_early_access_description">Recursos de ponta, acesso antecipado a atualizações e muito mais</string> | 189 | <string name="get_early_access_description">Recursos de ponta, acesso antecipado a atualizações e muito mais</string> |
| 150 | <string name="early_access_benefits">BenefÃcios do Acesso Antecipado</string> | 190 | <string name="early_access_benefits">BenefÃcios do Acesso Antecipado</string> |
| @@ -154,18 +194,19 @@ | |||
| 154 | <string name="prioritized_support">Suporte prioritário</string> | 194 | <string name="prioritized_support">Suporte prioritário</string> |
| 155 | <string name="helping_game_preservation">Ajuda na preservação dos jogos</string> | 195 | <string name="helping_game_preservation">Ajuda na preservação dos jogos</string> |
| 156 | <string name="our_eternal_gratitude">A nossa eterna gratidão</string> | 196 | <string name="our_eternal_gratitude">A nossa eterna gratidão</string> |
| 157 | <string name="are_you_interested">Estás interessado?</string> | 197 | <string name="are_you_interested">Tem interesse?</string> |
| 158 | 198 | ||
| 159 | <!-- General settings strings --> | 199 | <!-- General settings strings --> |
| 160 | <string name="frame_limit_enable">Limite de velocidade</string> | 200 | <string name="frame_limit_enable">Limite de velocidade</string> |
| 161 | <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem especÃfica da velocidade normal.</string> | 201 | <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem especÃfica da velocidade normal.</string> |
| 162 | <string name="frame_limit_slider">Percentagem do limite de velocidade</string> | 202 | <string name="frame_limit_slider">Porcentagem do limite de velocidade</string> |
| 163 | <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> | 203 | <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> |
| 164 | <string name="cpu_accuracy">Precisão do CPU</string> | 204 | <string name="cpu_backend">Backend da CPU</string> |
| 205 | <string name="cpu_accuracy">Precisão da CPU</string> | ||
| 165 | <string name="value_with_units">%1$s%2$s</string> | 206 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 207 | ||
| 167 | <!-- System settings strings --> | 208 | <!-- System settings strings --> |
| 168 | <string name="use_docked_mode">Modo Ancorado</string> | 209 | <string name="use_docked_mode">Modo TV</string> |
| 169 | <string name="use_docked_mode_description">Aumenta a resolução, diminuindo o desempenho. O Modo Portátil é utilizado quando estiver desabilitado, diminuindo a resolução e melhorando o desempenho.</string> | 210 | <string name="use_docked_mode_description">Aumenta a resolução, diminuindo o desempenho. O Modo Portátil é utilizado quando estiver desabilitado, diminuindo a resolução e melhorando o desempenho.</string> |
| 170 | <string name="emulated_region">Região da emulação</string> | 211 | <string name="emulated_region">Região da emulação</string> |
| 171 | <string name="emulated_language">Idioma da emulação</string> | 212 | <string name="emulated_language">Idioma da emulação</string> |
| @@ -177,20 +218,22 @@ | |||
| 177 | 218 | ||
| 178 | <!-- Graphics settings strings --> | 219 | <!-- Graphics settings strings --> |
| 179 | <string name="renderer_accuracy">NÃvel de precisão</string> | 220 | <string name="renderer_accuracy">NÃvel de precisão</string> |
| 180 | <string name="renderer_resolution">Resolução (Portátil/Ancorado)</string> | 221 | <string name="renderer_resolution">Resolução (Portátil/Modo TV)</string> |
| 181 | <string name="renderer_vsync">Modo VSync</string> | 222 | <string name="renderer_vsync">Modo VSync</string> |
| 182 | <string name="renderer_screen_layout">Oriantação</string> | 223 | <string name="renderer_screen_layout">Oriantação</string> |
| 183 | <string name="renderer_aspect_ratio">Proporção da tela</string> | 224 | <string name="renderer_aspect_ratio">Proporção da tela</string> |
| 184 | <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string> | 225 | <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string> |
| 185 | <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string> | 226 | <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string> |
| 186 | <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string> | 227 | <string name="renderer_force_max_clock">Forçar velocidade máxima (somente Adreno)</string> |
| 187 | <string name="renderer_force_max_clock_description">Força o GPU a correr à velocidade máxima (restrições térmicas serão aplicadas)</string> | 228 | <string name="renderer_force_max_clock_description">Força o GPU a rodar na velocidade máxima (restrições térmicas serão aplicadas)</string> |
| 188 | <string name="renderer_asynchronous_shaders">Usa shaders assÃncronos </string> | 229 | <string name="renderer_asynchronous_shaders">Usar shaders assÃncronos </string> |
| 189 | <string name="renderer_asynchronous_shaders_description">Compila os shaders de forma assÃncrona, reduzindo travamentos, mas pode apresentar problemas.</string> | 230 | <string name="renderer_asynchronous_shaders_description">Compila os shaders de forma assÃncrona, reduzindo travamentos, mas pode apresentar problemas.</string> |
| 190 | <string name="renderer_reactive_flushing">Usar flushing reativo</string> | 231 | <string name="renderer_reactive_flushing">Usar flushing reativo</string> |
| 191 | <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> | 232 | <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> |
| 192 | <string name="use_disk_shader_cache">Cache de shaders em disco</string> | 233 | <string name="use_disk_shader_cache">Cache de shaders em disco</string> |
| 193 | <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> | 234 | <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> |
| 235 | <string name="anisotropic_filtering">Filtragem anisotrópica</string> | ||
| 236 | <string name="anisotropic_filtering_description">Melhora a qualidade das texturas quando visualizadas de ângulos oblÃquos</string> | ||
| 194 | 237 | ||
| 195 | <!-- Debug settings strings --> | 238 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 239 | <string name="cpu">CPU</string> |
| @@ -198,28 +241,29 @@ | |||
| 198 | <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string> | 241 | <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string> |
| 199 | <string name="gpu">GPU</string> | 242 | <string name="gpu">GPU</string> |
| 200 | <string name="renderer_api">API</string> | 243 | <string name="renderer_api">API</string> |
| 201 | <string name="renderer_debug">Ativar depuração de gráficos</string> | 244 | <string name="renderer_debug">Depuração de gráficos</string> |
| 202 | <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string> | 245 | <string name="renderer_debug_description">Define a API gráfica para um modo de depuração mais lento.</string> |
| 203 | <string name="fastmem">Fastmem</string> | 246 | <string name="fastmem">Fastmem</string> |
| 204 | 247 | ||
| 205 | <!-- Audio settings strings --> | 248 | <!-- Audio settings strings --> |
| 206 | <string name="audio_output_engine">Motor de saÃda</string> | 249 | <string name="audio_output_engine">Engine de reprodução</string> |
| 207 | <string name="audio_volume">Volume</string> | 250 | <string name="audio_volume">Volume</string> |
| 208 | <string name="audio_volume_description">Especifica o volume de saÃda.</string> | 251 | <string name="audio_volume_description">Especifica o volume de reprodução.</string> |
| 209 | 252 | ||
| 210 | <!-- Miscellaneous --> | 253 | <!-- Miscellaneous --> |
| 211 | <string name="slider_default">Padrão</string> | 254 | <string name="slider_default">Padrão</string> |
| 212 | <string name="ini_saved">Definições guardadas</string> | 255 | <string name="ini_saved">Configurações salvas</string> |
| 213 | <string name="gameid_saved">Definições guardadas para %1$s</string> | 256 | <string name="gameid_saved">Configurações salvas para %1$s</string> |
| 214 | <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string> | 257 | <string name="error_saving">Erro ao salvar %1$s.ini: %2$s</string> |
| 215 | <string name="unimplemented_menu">Menu não implementado</string> | 258 | <string name="unimplemented_menu">Menu não implementado</string> |
| 216 | <string name="loading">A carregar...</string> | 259 | <string name="loading">Carregando...</string> |
| 217 | <string name="shutting_down">A desligar...</string> | 260 | <string name="shutting_down">Encerrando...</string> |
| 218 | <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> | 261 | <string name="reset_setting_confirmation">Deseja reverter esta configuração para os valores padrões?</string> |
| 219 | <string name="reset_to_default">Reverter para padrão</string> | 262 | <string name="reset_to_default">Reverter para o padrão</string> |
| 220 | <string name="reset_all_settings">Redefinir todas as definições?</string> | 263 | <string name="reset_to_default_description">Redefine todas as configurações avançadas</string> |
| 264 | <string name="reset_all_settings">Redefinir todas as configurações?</string> | ||
| 221 | <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> | 265 | <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> |
| 222 | <string name="settings_reset">Redefinir definições</string> | 266 | <string name="settings_reset">Configurações redefinidas</string> |
| 223 | <string name="close">Fechar</string> | 267 | <string name="close">Fechar</string> |
| 224 | <string name="learn_more">Saiba mais</string> | 268 | <string name="learn_more">Saiba mais</string> |
| 225 | <string name="auto">Automático</string> | 269 | <string name="auto">Automático</string> |
| @@ -227,44 +271,95 @@ | |||
| 227 | <string name="string_null">Nenhum (desativado)</string> | 271 | <string name="string_null">Nenhum (desativado)</string> |
| 228 | <string name="string_import">Importar</string> | 272 | <string name="string_import">Importar</string> |
| 229 | <string name="export">Exportar</string> | 273 | <string name="export">Exportar</string> |
| 230 | <string name="export_failed">Exportação falhada</string> | 274 | <string name="export_failed">Falha ao exportar</string> |
| 231 | <string name="import_failed">IMportação falhada</string> | 275 | <string name="import_failed">Falha ao importar</string> |
| 232 | <string name="cancelling">A cancelar</string> | 276 | <string name="cancelling">Cancelando</string> |
| 233 | 277 | <string name="install">Instalar</string> | |
| 278 | <string name="delete">Deletar</string> | ||
| 279 | <string name="edit">Editar</string> | ||
| 280 | <string name="export_success">Exportado com sucesso</string> | ||
| 281 | <string name="start">Start</string> | ||
| 282 | <string name="clear">Limpar</string> | ||
| 283 | <string name="global">Global</string> | ||
| 284 | <string name="custom">Personalizado</string> | ||
| 285 | <string name="notice">Aviso</string> | ||
| 286 | <string name="import_complete">Importação concluÃda</string> | ||
| 234 | <!-- GPU driver installation --> | 287 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">Seleciona a driver para o GPU</string> | 288 | <string name="select_gpu_driver">Selecione o driver para a GPU</string> |
| 236 | <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string> | 289 | <string name="select_gpu_driver_title">Gostaria de substituir o driver atual da GPU? </string> |
| 237 | <string name="select_gpu_driver_install">Instalar</string> | 290 | <string name="select_gpu_driver_install">Instalar</string> |
| 238 | <string name="select_gpu_driver_default">Padrão</string> | 291 | <string name="select_gpu_driver_default">Padrão</string> |
| 239 | <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> | 292 | <string name="select_gpu_driver_use_default">Usar o driver padrão da GPU</string> |
| 240 | <string name="select_gpu_driver_error">Driver selecionado inválido, a usar o padrão do sistema!</string> | 293 | <string name="select_gpu_driver_error">Driver selecionado inválido</string> |
| 241 | <string name="system_gpu_driver">Driver do GPU padrão</string> | 294 | <string name="driver_already_installed">Driver já instalado</string> |
| 242 | <string name="installing_driver">A instalar o Driver...</string> | 295 | <string name="system_gpu_driver">Driver padrão da GPU</string> |
| 296 | <string name="installing_driver">Instalando driver...</string> | ||
| 243 | 297 | ||
| 244 | <!-- Preferences Screen --> | 298 | <!-- Preferences Screen --> |
| 245 | <string name="preferences_settings">Configurações</string> | 299 | <string name="preferences_settings">Configurações</string> |
| 246 | <string name="preferences_general">Geral</string> | 300 | <string name="preferences_general">Geral</string> |
| 247 | <string name="preferences_system">Sistema</string> | 301 | <string name="preferences_system">Sistema</string> |
| 302 | <string name="preferences_system_description">Modo TV, região, idioma</string> | ||
| 248 | <string name="preferences_graphics">Gráficos</string> | 303 | <string name="preferences_graphics">Gráficos</string> |
| 304 | <string name="preferences_graphics_description">NÃvel de precisão, resolução, cache de shader</string> | ||
| 249 | <string name="preferences_audio">Ãudio</string> | 305 | <string name="preferences_audio">Ãudio</string> |
| 250 | <string name="preferences_theme">Cor e tema.</string> | 306 | <string name="preferences_audio_description">Engine de reprodução, volume</string> |
| 307 | <string name="preferences_theme">Tema e cor</string> | ||
| 251 | <string name="preferences_debug">Depuração</string> | 308 | <string name="preferences_debug">Depuração</string> |
| 252 | 309 | <string name="preferences_debug_description">Depuração de CPU/GPU, API gráfica, fastmem</string> | |
| 310 | |||
| 311 | <!-- Game properties --> | ||
| 312 | <string name="info">Informações</string> | ||
| 313 | <string name="info_description">ID do Programa, desenvolvedora, versão</string> | ||
| 314 | <string name="per_game_settings">Configurações por jogo</string> | ||
| 315 | <string name="per_game_settings_description">Edite configurações especÃficas para este jogo</string> | ||
| 316 | <string name="launch_options">Configurações de inicialização</string> | ||
| 317 | <string name="path">Caminho</string> | ||
| 318 | <string name="program_id">ID do Programa</string> | ||
| 319 | <string name="developer">Desenvolvedora</string> | ||
| 320 | <string name="version">Versão</string> | ||
| 321 | <string name="copy_details">Copiar detalhes</string> | ||
| 322 | <string name="add_ons">Adicionais</string> | ||
| 323 | <string name="add_ons_description">Gerencie mods, atualizações e DLC</string> | ||
| 324 | <string name="clear_shader_cache">Excluir cache de shaders</string> | ||
| 325 | <string name="clear_shader_cache_description">Remove todos os shaders compilados durante a execução do jogo</string> | ||
| 326 | <string name="clear_shader_cache_warning_description">Você terá mais travamentos enquanto o cache de shaders for recompilado</string> | ||
| 327 | <string name="cleared_shaders_successfully">Shaders excluÃdos com sucesso</string> | ||
| 328 | <string name="addons_game">Adicionais: %1$s</string> | ||
| 329 | <string name="save_data">Dados salvos</string> | ||
| 330 | <string name="save_data_description">Gerencie dados salvos especÃficos deste jogo</string> | ||
| 331 | <string name="delete_save_data">Deletar dados salvos</string> | ||
| 332 | <string name="delete_save_data_description">Remove todos os dados salvos especÃficos deste jogo</string> | ||
| 333 | <string name="delete_save_data_warning_description">Isso removerá permanentemente todos os dados salvos do jogo. Tem certeza de que quer continuar?</string> | ||
| 334 | <string name="save_data_deleted_successfully">Dados salvos deletados com sucesso </string> | ||
| 335 | <string name="select_content_type">Tipo de conteúdo</string> | ||
| 336 | <string name="updates_and_dlc">Atualizações e DLC</string> | ||
| 337 | <string name="mods_and_cheats">Mods e cheats</string> | ||
| 338 | <string name="addon_notice">Aviso importante sobre os adicionais</string> | ||
| 339 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 340 | <string name="addon_notice_description">Para instalar mods e cheats, você deve selecionar uma pasta que contenha um diretório cheats/, romfs/ ou exefs. Não podemos verificar se eles são compatÃveis com seu jogo, então tenha cuidado!</string> | ||
| 341 | <string name="invalid_directory">Diretório inválido </string> | ||
| 342 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 343 | <string name="invalid_directory_description">Por favor verifique se o diretório selecionado contém uma pasta cheats/, romfs/ ou exefs/ e tente novamente.</string> | ||
| 344 | <string name="addon_installed_successfully">Adicional instalado com sucesso</string> | ||
| 345 | <string name="verifying_content">Verificando conteúdo...</string> | ||
| 346 | <string name="content_install_notice">Aviso sobre conteúdo adicional</string> | ||
| 347 | <string name="content_install_notice_description">O conteúdo que você selecionou não corresponde a este jogo.\nInstalar mesmo assim?</string> | ||
| 253 | <!-- ROM loading errors --> | 348 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">A tua ROM está encriptada</string> | 349 | <string name="loader_error_encrypted">Sua ROM está encriptada</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> | 350 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para extrair novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> ou <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> |
| 256 | <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor confirma que o teu ficheiro <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado para que os jogos possam ser desencriptados.]]></string> | 351 | <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor verifique se o seu arquivo <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado para que os jogos possam ser decriptados.]]></string> |
| 257 | <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vÃdeo.</string> | 352 | <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vÃdeo.</string> |
| 258 | <string name="loader_error_video_core_description">Isto é normalmente causado por um driver de GPU incompatÃvel. Instalar um driver GPU pode resolver este problema.</string> | 353 | <string name="loader_error_video_core_description">Isto é normalmente causado por um driver de GPU incompatÃvel. Instalar um driver de GPU pode resolver este problema.</string> |
| 259 | <string name="loader_error_invalid_format">ImpossÃvel carregar a tua ROM</string> | 354 | <string name="loader_error_invalid_format">ImpossÃvel carregar a ROM</string> |
| 260 | <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string> | 355 | <string name="loader_error_file_not_found">O arquivo ROM não existe</string> |
| 261 | 356 | ||
| 262 | <!-- Emulation Menu --> | 357 | <!-- Emulation Menu --> |
| 263 | <string name="emulation_exit">Parar emulação</string> | 358 | <string name="emulation_exit">Sair da emulação</string> |
| 264 | <string name="emulation_done">Feito</string> | 359 | <string name="emulation_done">Feito</string> |
| 265 | <string name="emulation_fps_counter">Contador de FPS</string> | 360 | <string name="emulation_fps_counter">Contador de FPS</string> |
| 266 | <string name="emulation_toggle_controls">Alterar controles</string> | 361 | <string name="emulation_toggle_controls">Marcar/Desmarcar botões</string> |
| 267 | <string name="emulation_rel_stick_center">Centro Relativo de Analógico</string> | 362 | <string name="emulation_rel_stick_center">Centro Relativo do Analógico</string> |
| 268 | <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string> | 363 | <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string> |
| 269 | <string name="emulation_haptics">Vibração ao tocar</string> | 364 | <string name="emulation_haptics">Vibração ao tocar</string> |
| 270 | <string name="emulation_show_overlay">Mostrar overlay</string> | 365 | <string name="emulation_show_overlay">Mostrar overlay</string> |
| @@ -272,28 +367,29 @@ | |||
| 272 | <string name="emulation_control_adjust">Ajustar overlay</string> | 367 | <string name="emulation_control_adjust">Ajustar overlay</string> |
| 273 | <string name="emulation_control_scale">Escala</string> | 368 | <string name="emulation_control_scale">Escala</string> |
| 274 | <string name="emulation_control_opacity">Opacidade</string> | 369 | <string name="emulation_control_opacity">Opacidade</string> |
| 275 | <string name="emulation_touch_overlay_reset">Restaurar overlay padrão</string> | 370 | <string name="emulation_touch_overlay_reset">Resetar overlay</string> |
| 276 | <string name="emulation_touch_overlay_edit">Editar overlay</string> | 371 | <string name="emulation_touch_overlay_edit">Editar overlay</string> |
| 277 | <string name="emulation_pause">Pausar emulação</string> | 372 | <string name="emulation_pause">Pausar emulação</string> |
| 278 | <string name="emulation_unpause">Retomar emulação</string> | 373 | <string name="emulation_unpause">Retomar a emulação</string> |
| 279 | <string name="emulation_input_overlay">Opções de overlay</string> | 374 | <string name="emulation_input_overlay">Opções de overlay</string> |
| 375 | <string name="touchscreen">Tela de toque</string> | ||
| 280 | 376 | ||
| 281 | <string name="load_settings">Carregando configurações...</string> | 377 | <string name="load_settings">Carregando configurações...</string> |
| 282 | 378 | ||
| 283 | <!-- Software keyboard --> | 379 | <!-- Software keyboard --> |
| 284 | <string name="software_keyboard">Teclado de software</string> | 380 | <string name="software_keyboard">Teclado do software</string> |
| 285 | 381 | ||
| 286 | <!-- Errors and warnings --> | 382 | <!-- Errors and warnings --> |
| 287 | <string name="abort_button">Abortar</string> | 383 | <string name="abort_button">Abortar</string> |
| 288 | <string name="continue_button">Continuar</string> | 384 | <string name="continue_button">Continuar</string> |
| 289 | <string name="system_archive_not_found">Arquivo do sistema não encontrado</string> | 385 | <string name="system_archive_not_found">Arquivo do Sistema Não Encontrado</string> |
| 290 | <string name="system_archive_not_found_message">%s está em falta. Por favor apaga os teus ficheiros de sistema.\nContinuar a emulação pode causar erros.</string> | 386 | <string name="system_archive_not_found_message">%s está faltando. Por favor extraia seus arquivos de sistema.\nContinuar a emulação pode causar travamentos e bugs.</string> |
| 291 | <string name="system_archive_general">Um arquivo do sistema</string> | 387 | <string name="system_archive_general">Um arquivo do sistema</string> |
| 292 | <string name="save_load_error">Erro Guardar/Carregar</string> | 388 | <string name="save_load_error">Erro de Salvamento/Carregamento</string> |
| 293 | <string name="fatal_error">Erro fatal</string> | 389 | <string name="fatal_error">Erro fatal</string> |
| 294 | <string name="fatal_error_message">Ocorreu um erro fatal. Verifica o teu registro para detalhes. \nContinuar a emulação pode causar erros.</string> | 390 | <string name="fatal_error_message">Ocorreu um erro fatal. Verifique o arquivo de registro para detalhes.\nContinuar a emulação pode causar travamentos e bugs.</string> |
| 295 | <string name="performance_warning">Desligar esta configuração irá reduzir a performance da emulação significantemente! Para a melhor experiência é recomendado que deixes esta configuração ativada.</string> | 391 | <string name="performance_warning">Desligar esta configuração irá reduzir a performance da emulação significantemente! Para a melhor experiência é recomendado deixar esta configuração ativada.</string> |
| 296 | <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecommended: %2$s</string> | 392 | <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecomendada: %2$s</string> |
| 297 | <string name="memory_formatted">%1$s %2$s</string> | 393 | <string name="memory_formatted">%1$s %2$s</string> |
| 298 | <string name="no_game_present">Nenhum jogo inicializável presente!</string> | 394 | <string name="no_game_present">Nenhum jogo inicializável presente!</string> |
| 299 | 395 | ||
| @@ -308,6 +404,7 @@ | |||
| 308 | 404 | ||
| 309 | <!-- Memory Sizes --> | 405 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 406 | <string name="memory_byte">Byte</string> |
| 407 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">KB</string> | 408 | <string name="memory_kilobyte">KB</string> |
| 312 | <string name="memory_megabyte">MB</string> | 409 | <string name="memory_megabyte">MB</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 410 | <string name="memory_gigabyte">GB</string> |
| @@ -316,19 +413,19 @@ | |||
| 316 | <string name="memory_exabyte">EB</string> | 413 | <string name="memory_exabyte">EB</string> |
| 317 | 414 | ||
| 318 | <!-- Renderer APIs --> | 415 | <!-- Renderer APIs --> |
| 319 | <string name="renderer_vulkan">Vulcano</string> | 416 | <string name="renderer_vulkan">Vulkan</string> |
| 320 | <string name="renderer_none">Nenhum</string> | 417 | <string name="renderer_none">Nenhum</string> |
| 321 | 418 | ||
| 322 | <!-- Renderer Accuracy --> | 419 | <!-- Renderer Accuracy --> |
| 323 | <string name="renderer_accuracy_normal">Normal</string> | 420 | <string name="renderer_accuracy_normal">Normal</string> |
| 324 | <string name="renderer_accuracy_high">Alto</string> | 421 | <string name="renderer_accuracy_high">Alto</string> |
| 325 | <string name="renderer_accuracy_extreme">Estremo (Lento)</string> | 422 | <string name="renderer_accuracy_extreme">Extremo (Lento)</string> |
| 326 | 423 | ||
| 327 | <!-- Resolutions --> | 424 | <!-- Resolutions --> |
| 328 | <string name="resolution_half">0.5X (360p/540p)</string> | 425 | <string name="resolution_half">0.5X (360p/540p)</string> |
| 329 | <string name="resolution_three_quarter">0.75X (540p/810p)</string> | 426 | <string name="resolution_three_quarter">0.75X (540p/810p)</string> |
| 330 | <string name="resolution_one">1X (720p/1080p)</string> | 427 | <string name="resolution_one">1X (720p/1080p)</string> |
| 331 | <string name="resolution_two">2X (1440p/2160p) (Slow)</string> | 428 | <string name="resolution_two">2X (1440p/2160p) (Lento)</string> |
| 332 | <string name="resolution_three">3X (2160p/3240p) (Lento)</string> | 429 | <string name="resolution_three">3X (2160p/3240p) (Lento)</string> |
| 333 | <string name="resolution_four">4X (2880p/4320p) (Lento)</string> | 430 | <string name="resolution_four">4X (2880p/4320p) (Lento)</string> |
| 334 | 431 | ||
| @@ -352,9 +449,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 449 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 450 | ||
| 354 | <!-- Screen Layouts --> | 451 | <!-- Screen Layouts --> |
| 355 | <string name="screen_layout_landscape">Landscape</string> | 452 | <string name="screen_layout_auto">Automática</string> |
| 356 | <string name="screen_layout_portrait">Portrait</string> | 453 | <string name="screen_layout_sensor_landscape">Paisagem pelo sensor</string> |
| 357 | <string name="screen_layout_auto">Automático</string> | 454 | <string name="screen_layout_landscape">Paisagem</string> |
| 455 | <string name="screen_layout_reverse_landscape">Paisagem invertida</string> | ||
| 456 | <string name="screen_layout_sensor_portrait">Retrato pelo sensor</string> | ||
| 457 | <string name="screen_layout_portrait">Retrato</string> | ||
| 458 | <string name="screen_layout_reverse_portrait">Retrato invertido</string> | ||
| 358 | 459 | ||
| 359 | <!-- Aspect Ratios --> | 460 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">Padrão (16:9)</string> | 461 | <string name="ratio_default">Padrão (16:9)</string> |
| @@ -363,21 +464,25 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">Forçar 16:10</string> | 464 | <string name="ratio_force_sixteen_ten">Forçar 16:10</string> |
| 364 | <string name="ratio_stretch">Esticar à janela</string> | 465 | <string name="ratio_stretch">Esticar à janela</string> |
| 365 | 466 | ||
| 467 | <!-- CPU Backend --> | ||
| 468 | <string name="cpu_backend_dynarmic">Dynarmic (Lento)</string> | ||
| 469 | <string name="cpu_backend_nce">Execução de código nativo (NCE)</string> | ||
| 470 | |||
| 366 | <!-- CPU Accuracy --> | 471 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">Preciso</string> | 472 | <string name="cpu_accuracy_accurate">Preciso</string> |
| 368 | <string name="cpu_accuracy_unsafe">Não seguro</string> | 473 | <string name="cpu_accuracy_unsafe">Não seguro</string> |
| 369 | <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string> | 474 | <string name="cpu_accuracy_paranoid">Paranóico (Lento)</string> |
| 370 | 475 | ||
| 371 | <!-- Gamepad Buttons --> | 476 | <!-- Gamepad Buttons --> |
| 372 | <string name="gamepad_d_pad">Botões Direcionais</string> | 477 | <string name="gamepad_d_pad">Botões Direcionais</string> |
| 373 | <string name="gamepad_left_stick">Analógico esquerdo</string> | 478 | <string name="gamepad_left_stick">Analógico esquerdo</string> |
| 374 | <string name="gamepad_right_stick">Analógico direito</string> | 479 | <string name="gamepad_right_stick">Analógico direito</string> |
| 375 | <string name="gamepad_home">Botão Home</string> | 480 | <string name="gamepad_home">Botão Home</string> |
| 376 | <string name="gamepad_screenshot">Captura de ecrã</string> | 481 | <string name="gamepad_screenshot">Captura de tela</string> |
| 377 | 482 | ||
| 378 | <!-- Disk shader cache --> | 483 | <!-- Disk shader cache --> |
| 379 | <string name="preparing_shaders">A preparar shaders</string> | 484 | <string name="preparing_shaders">Preparando shaders</string> |
| 380 | <string name="building_shaders">A criar shaders</string> | 485 | <string name="building_shaders">Criando shaders</string> |
| 381 | 486 | ||
| 382 | <!-- Theme options --> | 487 | <!-- Theme options --> |
| 383 | <string name="change_app_theme">Mudar o tema do aplicativo</string> | 488 | <string name="change_app_theme">Mudar o tema do aplicativo</string> |
| @@ -391,19 +496,26 @@ | |||
| 391 | <string name="theme_mode_dark">Escuro</string> | 496 | <string name="theme_mode_dark">Escuro</string> |
| 392 | 497 | ||
| 393 | <!-- Audio output engines --> | 498 | <!-- Audio output engines --> |
| 499 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 500 | <string name="cubeb">cubeb</string> |
| 395 | 501 | ||
| 502 | <!-- Anisotropic filtering options --> | ||
| 503 | <string name="multiplier_two">2x</string> | ||
| 504 | <string name="multiplier_four">4x</string> | ||
| 505 | <string name="multiplier_eight">8x</string> | ||
| 506 | <string name="multiplier_sixteen">16x</string> | ||
| 507 | |||
| 396 | <!-- Black backgrounds theme --> | 508 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">Plano de fundo preto</string> | 509 | <string name="use_black_backgrounds">Plano de fundo preto</string> |
| 398 | <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> | 510 | <string name="use_black_backgrounds_description">Quando usar o tema escuro, aplicar fundos pretos</string> |
| 399 | 511 | ||
| 400 | <!-- Picture-In-Picture --> | 512 | <!-- Picture-In-Picture --> |
| 401 | <string name="picture_in_picture">Picture in Picture</string> | 513 | <string name="picture_in_picture">Picture in Picture</string> |
| 402 | <string name="picture_in_picture_description">Minimizar a janela quando colocada em segundo plano</string> | 514 | <string name="picture_in_picture_description">Minimiza a janela quando colocada em segundo plano</string> |
| 403 | <string name="pause">Pausa</string> | 515 | <string name="pause">Pausar</string> |
| 404 | <string name="play">Correr</string> | 516 | <string name="play">Executar</string> |
| 405 | <string name="mute">Mudo</string> | 517 | <string name="mute">Mudo</string> |
| 406 | <string name="unmute">Unmute</string> | 518 | <string name="unmute">Tirar do Mudo</string> |
| 407 | 519 | ||
| 408 | <!-- Licenses screen strings --> | 520 | <!-- Licenses screen strings --> |
| 409 | <string name="licenses">Licenças</string> | 521 | <string name="licenses">Licenças</string> |
diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml index 6afea9b03..684a71616 100644 --- a/src/android/app/src/main/res/values-pt-rPT/strings.xml +++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> | 34 | <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> |
| 35 | <string name="search_and_filter_games">Procura e filtra jogos.</string> | 35 | <string name="search_and_filter_games">Procura e filtra jogos.</string> |
| 36 | <string name="select_games_folder">Seleciona a pasta de jogos.</string> | 36 | <string name="select_games_folder">Seleciona a pasta de jogos.</string> |
| 37 | <string name="manage_game_folders">Gerencie as pastas de jogos</string> | ||
| 37 | <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> | 38 | <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> |
| 38 | <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> | 39 | <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> |
| 39 | <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> | 40 | <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">Chaves de encriptação inválidas</string> | 69 | <string name="invalid_keys_error">Chaves de encriptação inválidas</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> | 71 | <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> |
| 72 | <string name="gpu_driver_manager">Gerenciador de driver de GPU</string> | ||
| 71 | <string name="install_gpu_driver">Instala driver para GPU</string> | 73 | <string name="install_gpu_driver">Instala driver para GPU</string> |
| 72 | <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> | 74 | <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> |
| 73 | <string name="advanced_settings">Configurações avançadas</string> | 75 | <string name="advanced_settings">Configurações avançadas</string> |
| @@ -85,7 +87,11 @@ | |||
| 85 | <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string> | 87 | <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string> |
| 86 | <string name="manage_save_data">Gerir dados guardados</string> | 88 | <string name="manage_save_data">Gerir dados guardados</string> |
| 87 | <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string> | 89 | <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string> |
| 90 | <string name="import_save_warning">Importar dados salvos</string> | ||
| 91 | <string name="import_save_warning_description">Isso irá sobrescrever seus dados salvos com o arquivo selecionado. Você tem certeza que quer continuar?</string> | ||
| 88 | <string name="import_export_saves_description">Importa ou exporta dados guardados</string> | 92 | <string name="import_export_saves_description">Importa ou exporta dados guardados</string> |
| 93 | <string name="save_files_importing">Importando dados salvos...</string> | ||
| 94 | <string name="save_files_exporting">Exportando arquivos de dados salvos...</string> | ||
| 89 | <string name="save_file_imported_success">Importado com sucesso</string> | 95 | <string name="save_file_imported_success">Importado com sucesso</string> |
| 90 | <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string> | 96 | <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> | 97 | <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> |
| @@ -118,6 +124,40 @@ | |||
| 118 | <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> | 124 | <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> |
| 119 | <string name="share_save_file">Partilha ficheiro duardado</string> | 125 | <string name="share_save_file">Partilha ficheiro duardado</string> |
| 120 | <string name="export_save_failed">Erro ao exportar dados guardados</string> | 126 | <string name="export_save_failed">Erro ao exportar dados guardados</string> |
| 127 | <string name="game_folders">Pastas de jogos</string> | ||
| 128 | <string name="deep_scan">Varredura profunda</string> | ||
| 129 | <string name="add_game_folder">Adicionar pasta de jogo</string> | ||
| 130 | <string name="folder_already_added">Esta pasta já foi adicionada!</string> | ||
| 131 | <string name="game_folder_properties">Propriedades da pasta de jogo</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="one">Falha ao importar dado salvo de %d</item> | ||
| 134 | <item quantity="many">Falha ao importar dados salvos de %d</item> | ||
| 135 | <item quantity="other">Falha ao importar dados salvos de %d</item> | ||
| 136 | </plurals> | ||
| 137 | <plurals name="saves_import_success"> | ||
| 138 | <item quantity="one">Dado salvo de %d importado com sucesso</item> | ||
| 139 | <item quantity="many">Dados salvos de %d importados com sucesso</item> | ||
| 140 | <item quantity="other">Dados salvos de %d importados com sucesso</item> | ||
| 141 | </plurals> | ||
| 142 | <string name="no_save_data_found">Dados salvos não encontrados</string> | ||
| 143 | |||
| 144 | <!-- Applet launcher strings --> | ||
| 145 | <string name="applets">Launcher de miniaplicativos</string> | ||
| 146 | <string name="applets_description">Inicie miniaplicativos do sistema usando o firmware instalado</string> | ||
| 147 | <string name="applets_error_firmware">Firmware não instalado</string> | ||
| 148 | <string name="applets_error_applet">Miniaplicativo não disponÃvel</string> | ||
| 149 | <string name="applets_error_description"><![CDATA[Por favor verifique se o arquivo 1prod.keys1 e o 2firmware2 estão instalados e tente novamente.]]></string> | ||
| 150 | <string name="album_applet">Ãlbum</string> | ||
| 151 | <string name="album_applet_description">Visualize imagens armazenadas na pasta de capturas de telas do usuário com o visualizador de imagens do sistema</string> | ||
| 152 | <string name="mii_edit_applet">Editor de Mii</string> | ||
| 153 | <string name="mii_edit_applet_description">Visualize e edite os Miis com o editor do sistema</string> | ||
| 154 | <string name="cabinet_applet">Arquivo</string> | ||
| 155 | <string name="cabinet_applet_description">Edite e delete dados armazenados nos amiibos</string> | ||
| 156 | <string name="cabinet_launcher">Inicializador do Arquivo</string> | ||
| 157 | <string name="cabinet_nickname_and_owner">Apelido e configurações do proprietário</string> | ||
| 158 | <string name="cabinet_game_data_eraser">Apagar dados de jogo</string> | ||
| 159 | <string name="cabinet_restorer">Restaurar</string> | ||
| 160 | <string name="cabinet_formatter">Formatar</string> | ||
| 121 | 161 | ||
| 122 | <!-- About screen strings --> | 162 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia não é real</string> | 163 | <string name="gaia_is_not_real">Gaia não é real</string> |
| @@ -161,6 +201,7 @@ | |||
| 161 | <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem especÃfica da velocidade normal.</string> | 201 | <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem especÃfica da velocidade normal.</string> |
| 162 | <string name="frame_limit_slider">Percentagem do limite de velocidade</string> | 202 | <string name="frame_limit_slider">Percentagem do limite de velocidade</string> |
| 163 | <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> | 203 | <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> |
| 204 | <string name="cpu_backend">Backend da CPU</string> | ||
| 164 | <string name="cpu_accuracy">Precisão do CPU</string> | 205 | <string name="cpu_accuracy">Precisão do CPU</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 206 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 207 | ||
| @@ -191,6 +232,8 @@ | |||
| 191 | <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> | 232 | <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> |
| 192 | <string name="use_disk_shader_cache">Cache de shaders em disco</string> | 233 | <string name="use_disk_shader_cache">Cache de shaders em disco</string> |
| 193 | <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> | 234 | <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> |
| 235 | <string name="anisotropic_filtering">Filtragem anisotrópica</string> | ||
| 236 | <string name="anisotropic_filtering_description">Melhora a qualidade das texturas quando visualizadas de ângulos oblÃquos</string> | ||
| 194 | 237 | ||
| 195 | <!-- Debug settings strings --> | 238 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 239 | <string name="cpu">CPU</string> |
| @@ -217,6 +260,7 @@ | |||
| 217 | <string name="shutting_down">A desligar...</string> | 260 | <string name="shutting_down">A desligar...</string> |
| 218 | <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> | 261 | <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> |
| 219 | <string name="reset_to_default">Reverter para padrão</string> | 262 | <string name="reset_to_default">Reverter para padrão</string> |
| 263 | <string name="reset_to_default_description">Reverte todas as configurações avançadas</string> | ||
| 220 | <string name="reset_all_settings">Redefinir todas as configurações?</string> | 264 | <string name="reset_all_settings">Redefinir todas as configurações?</string> |
| 221 | <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> | 265 | <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> |
| 222 | <string name="settings_reset">Redefinir configurações </string> | 266 | <string name="settings_reset">Redefinir configurações </string> |
| @@ -230,14 +274,24 @@ | |||
| 230 | <string name="export_failed">Exportação falhada</string> | 274 | <string name="export_failed">Exportação falhada</string> |
| 231 | <string name="import_failed">IMportação falhada</string> | 275 | <string name="import_failed">IMportação falhada</string> |
| 232 | <string name="cancelling">A cancelar</string> | 276 | <string name="cancelling">A cancelar</string> |
| 233 | 277 | <string name="install">Instalar</string> | |
| 278 | <string name="delete">Apagar</string> | ||
| 279 | <string name="edit">Editar</string> | ||
| 280 | <string name="export_success">Exportado com sucesso</string> | ||
| 281 | <string name="start">Começar</string> | ||
| 282 | <string name="clear">Limpar</string> | ||
| 283 | <string name="global">Global</string> | ||
| 284 | <string name="custom">Personalizado</string> | ||
| 285 | <string name="notice">Aviso</string> | ||
| 286 | <string name="import_complete">Importação concluÃda</string> | ||
| 234 | <!-- GPU driver installation --> | 287 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">Seleciona a driver para o GPU</string> | 288 | <string name="select_gpu_driver">Seleciona a driver para o GPU</string> |
| 236 | <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string> | 289 | <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string> |
| 237 | <string name="select_gpu_driver_install">Instalar</string> | 290 | <string name="select_gpu_driver_install">Instalar</string> |
| 238 | <string name="select_gpu_driver_default">Padrão</string> | 291 | <string name="select_gpu_driver_default">Padrão</string> |
| 239 | <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> | 292 | <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> |
| 240 | <string name="select_gpu_driver_error">Driver selecionado inválido, a usar o padrão do sistema!</string> | 293 | <string name="select_gpu_driver_error">Driver selecionado inválido</string> |
| 294 | <string name="driver_already_installed">Driver já instalado</string> | ||
| 241 | <string name="system_gpu_driver">Driver do GPU padrão</string> | 295 | <string name="system_gpu_driver">Driver do GPU padrão</string> |
| 242 | <string name="installing_driver">A instalar o Driver...</string> | 296 | <string name="installing_driver">A instalar o Driver...</string> |
| 243 | 297 | ||
| @@ -245,11 +299,52 @@ | |||
| 245 | <string name="preferences_settings">Configurações</string> | 299 | <string name="preferences_settings">Configurações</string> |
| 246 | <string name="preferences_general">Geral</string> | 300 | <string name="preferences_general">Geral</string> |
| 247 | <string name="preferences_system">Sistema</string> | 301 | <string name="preferences_system">Sistema</string> |
| 302 | <string name="preferences_system_description">Modo ancorado, região, idioma</string> | ||
| 248 | <string name="preferences_graphics">Gráficos</string> | 303 | <string name="preferences_graphics">Gráficos</string> |
| 304 | <string name="preferences_graphics_description">NÃvel de precisão, resolução, cache de shader</string> | ||
| 249 | <string name="preferences_audio">Audio</string> | 305 | <string name="preferences_audio">Audio</string> |
| 306 | <string name="preferences_audio_description">Engine de reprodução, volume</string> | ||
| 250 | <string name="preferences_theme">Cor e tema.</string> | 307 | <string name="preferences_theme">Cor e tema.</string> |
| 251 | <string name="preferences_debug">Depurar</string> | 308 | <string name="preferences_debug">Depurar</string> |
| 252 | 309 | <string name="preferences_debug_description">Depuração de CPU/GPU, API gráfica, fastmem</string> | |
| 310 | |||
| 311 | <!-- Game properties --> | ||
| 312 | <string name="info">Informação</string> | ||
| 313 | <string name="info_description">ID do programa, desenvolvedor, versão</string> | ||
| 314 | <string name="per_game_settings">Configurações por jogo</string> | ||
| 315 | <string name="per_game_settings_description">Editar configurações especÃficas para este jogo</string> | ||
| 316 | <string name="launch_options">Iniciar configuração</string> | ||
| 317 | <string name="path">Caminho</string> | ||
| 318 | <string name="program_id">ID do programa</string> | ||
| 319 | <string name="developer">Desenvolvedor</string> | ||
| 320 | <string name="version">Versão</string> | ||
| 321 | <string name="copy_details">Copiar detalhes</string> | ||
| 322 | <string name="add_ons">Add-ons</string> | ||
| 323 | <string name="add_ons_description">Gerencie mods, atualizações e DLC</string> | ||
| 324 | <string name="clear_shader_cache">Limpar cache de shaders</string> | ||
| 325 | <string name="clear_shader_cache_description">Remove todos os shaders compilados enquanto esse jogo era jogado</string> | ||
| 326 | <string name="clear_shader_cache_warning_description">Você terá mais travamentos enquanto o cache de shaders for recompilado</string> | ||
| 327 | <string name="cleared_shaders_successfully">Shaders excluÃdos com sucesso</string> | ||
| 328 | <string name="addons_game">Adicionais: %1$s</string> | ||
| 329 | <string name="save_data">Salvar dados</string> | ||
| 330 | <string name="save_data_description">Gerenciar dados salvos especÃficos deste jogo</string> | ||
| 331 | <string name="delete_save_data">Apagar dados salvos</string> | ||
| 332 | <string name="delete_save_data_description">Remover todos os dados salvos especÃficos deste jogo</string> | ||
| 333 | <string name="delete_save_data_warning_description">Isso removerá permanentemente todos os dados salvos do jogo. Tem certeza de que quer continuar?</string> | ||
| 334 | <string name="save_data_deleted_successfully">Dados salvos removidos com sucesso </string> | ||
| 335 | <string name="select_content_type">Tipo de conteúdo</string> | ||
| 336 | <string name="updates_and_dlc">Atualizações e DLC</string> | ||
| 337 | <string name="mods_and_cheats">Mods e trapaças</string> | ||
| 338 | <string name="addon_notice">Aviso importante sobre os adicionais</string> | ||
| 339 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 340 | <string name="addon_notice_description">Para instalar mods e cheats, você deve selecionar uma pasta que contenha um diretório cheats/, romfs/ ou exefs. Não podemos verificar se eles são compatÃveis com seu jogo, então tenha cuidado!</string> | ||
| 341 | <string name="invalid_directory">Diretório inválido </string> | ||
| 342 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 343 | <string name="invalid_directory_description">Por favor verifique se o diretório selecionado contém uma pasta cheats/, romfs ou exefs e tente novamente.</string> | ||
| 344 | <string name="addon_installed_successfully">Adicional instalado com sucesso</string> | ||
| 345 | <string name="verifying_content">Verificando conteúdo</string> | ||
| 346 | <string name="content_install_notice">Aviso sobre conteúdo adicional</string> | ||
| 347 | <string name="content_install_notice_description">O conteúdo que você selecionou não corresponde a este jogo.\nInstalar mesmo assim?</string> | ||
| 253 | <!-- ROM loading errors --> | 348 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">A tua ROM está encriptada</string> | 349 | <string name="loader_error_encrypted">A tua ROM está encriptada</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> | 350 | <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">tÃtulos instalados</a>.]]></string> |
| @@ -277,6 +372,7 @@ | |||
| 277 | <string name="emulation_pause">Pausar emulação</string> | 372 | <string name="emulation_pause">Pausar emulação</string> |
| 278 | <string name="emulation_unpause">Despausar emulação</string> | 373 | <string name="emulation_unpause">Despausar emulação</string> |
| 279 | <string name="emulation_input_overlay">Opções de overlay</string> | 374 | <string name="emulation_input_overlay">Opções de overlay</string> |
| 375 | <string name="touchscreen">Ecrã Táctil</string> | ||
| 280 | 376 | ||
| 281 | <string name="load_settings">Carregando configurações...</string> | 377 | <string name="load_settings">Carregando configurações...</string> |
| 282 | 378 | ||
| @@ -308,6 +404,7 @@ | |||
| 308 | 404 | ||
| 309 | <!-- Memory Sizes --> | 405 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 406 | <string name="memory_byte">Byte</string> |
| 407 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">KB</string> | 408 | <string name="memory_kilobyte">KB</string> |
| 312 | <string name="memory_megabyte">MB</string> | 409 | <string name="memory_megabyte">MB</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 410 | <string name="memory_gigabyte">GB</string> |
| @@ -352,9 +449,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 449 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 450 | ||
| 354 | <!-- Screen Layouts --> | 451 | <!-- Screen Layouts --> |
| 452 | <string name="screen_layout_auto">Automático</string> | ||
| 453 | <string name="screen_layout_sensor_landscape">Paisagem pelo sensor</string> | ||
| 355 | <string name="screen_layout_landscape">Landscape</string> | 454 | <string name="screen_layout_landscape">Landscape</string> |
| 455 | <string name="screen_layout_reverse_landscape">Paisagem invertida</string> | ||
| 456 | <string name="screen_layout_sensor_portrait">Retrato pelo sensor</string> | ||
| 356 | <string name="screen_layout_portrait">Portrait</string> | 457 | <string name="screen_layout_portrait">Portrait</string> |
| 357 | <string name="screen_layout_auto">Automático</string> | 458 | <string name="screen_layout_reverse_portrait">Retrato invertido</string> |
| 358 | 459 | ||
| 359 | <!-- Aspect Ratios --> | 460 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">Padrão (16:9)</string> | 461 | <string name="ratio_default">Padrão (16:9)</string> |
| @@ -363,6 +464,10 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">Forçar 16:10</string> | 464 | <string name="ratio_force_sixteen_ten">Forçar 16:10</string> |
| 364 | <string name="ratio_stretch">Esticar à janela</string> | 465 | <string name="ratio_stretch">Esticar à janela</string> |
| 365 | 466 | ||
| 467 | <!-- CPU Backend --> | ||
| 468 | <string name="cpu_backend_dynarmic">Dynarmic (Lento)</string> | ||
| 469 | <string name="cpu_backend_nce">Native code execution (NCE)</string> | ||
| 470 | |||
| 366 | <!-- CPU Accuracy --> | 471 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">Preciso</string> | 472 | <string name="cpu_accuracy_accurate">Preciso</string> |
| 368 | <string name="cpu_accuracy_unsafe">Inseguro</string> | 473 | <string name="cpu_accuracy_unsafe">Inseguro</string> |
| @@ -391,8 +496,15 @@ | |||
| 391 | <string name="theme_mode_dark">Escuro</string> | 496 | <string name="theme_mode_dark">Escuro</string> |
| 392 | 497 | ||
| 393 | <!-- Audio output engines --> | 498 | <!-- Audio output engines --> |
| 499 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 500 | <string name="cubeb">cubeb</string> |
| 395 | 501 | ||
| 502 | <!-- Anisotropic filtering options --> | ||
| 503 | <string name="multiplier_two">2x</string> | ||
| 504 | <string name="multiplier_four">4x</string> | ||
| 505 | <string name="multiplier_eight">8x</string> | ||
| 506 | <string name="multiplier_sixteen">16x</string> | ||
| 507 | |||
| 396 | <!-- Black backgrounds theme --> | 508 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">Plano de fundo preto</string> | 509 | <string name="use_black_backgrounds">Plano de fundo preto</string> |
| 398 | <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> | 510 | <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> |
diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml index c614257a8..099b2c9eb 100644 --- a/src/android/app/src/main/res/values-ru/strings.xml +++ b/src/android/app/src/main/res/values-ru/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">Ðе найдены файлы или еще не выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸.</string> | 34 | <string name="empty_gamelist">Ðе найдены файлы или еще не выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸.</string> |
| 35 | <string name="search_and_filter_games">ПоиÑк и Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¸Ð³Ñ€</string> | 35 | <string name="search_and_filter_games">ПоиÑк и Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¸Ð³Ñ€</string> |
| 36 | <string name="select_games_folder">Выберите папку Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string> | 36 | <string name="select_games_folder">Выберите папку Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string> |
| 37 | <string name="manage_game_folders">Управление папками</string> | ||
| 37 | <string name="select_games_folder_description">ПозволÑет yuzu заполнить ÑпиÑок игр</string> | 38 | <string name="select_games_folder_description">ПозволÑет yuzu заполнить ÑпиÑок игр</string> |
| 38 | <string name="add_games_warning">ПропуÑтить выбор папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸?</string> | 39 | <string name="add_games_warning">ПропуÑтить выбор папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸?</string> |
| 39 | <string name="add_games_warning_description">Игры не будут отображатьÑÑ Ð² ÑпиÑке Игры, еÑли папка не выбрана.</string> | 40 | <string name="add_games_warning_description">Игры не будут отображатьÑÑ Ð² ÑпиÑке Игры, еÑли папка не выбрана.</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string> | 69 | <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string> | 71 | <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string> |
| 72 | <string name="gpu_driver_manager">Менеджер драйверов ГП</string> | ||
| 71 | <string name="install_gpu_driver">УÑтановить драйвер ГП</string> | 73 | <string name="install_gpu_driver">УÑтановить драйвер ГП</string> |
| 72 | <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string> | 74 | <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string> |
| 73 | <string name="advanced_settings">РаÑширенные наÑтройки</string> | 75 | <string name="advanced_settings">РаÑширенные наÑтройки</string> |
| @@ -85,7 +87,11 @@ | |||
| 85 | <string name="notification_no_directory_link_description">ПожалуйÑта, найдите папку Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ боковой панели файлового менеджера вручную.</string> | 87 | <string name="notification_no_directory_link_description">ПожалуйÑта, найдите папку Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ боковой панели файлового менеджера вручную.</string> |
| 86 | <string name="manage_save_data">Управление данными Ñохранений</string> | 88 | <string name="manage_save_data">Управление данными Ñохранений</string> |
| 87 | <string name="manage_save_data_description">Ðайдено данные Ñохранений. ПожалуйÑта, выберите вариант ниже.</string> | 89 | <string name="manage_save_data_description">Ðайдено данные Ñохранений. ПожалуйÑта, выберите вариант ниже.</string> |
| 90 | <string name="import_save_warning">Импортировать ÑохранениÑ</string> | ||
| 91 | <string name="import_save_warning_description">Ðто перезапишет вÑе ÑущеÑтвующие данные ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¼ файлом. Ð’Ñ‹ уверены, что хотите продолжить?</string> | ||
| 88 | <string name="import_export_saves_description">Импорт или ÑкÑпорт файлов ÑохранениÑ</string> | 92 | <string name="import_export_saves_description">Импорт или ÑкÑпорт файлов ÑохранениÑ</string> |
| 93 | <string name="save_files_importing">Импорт файлов ÑохранениÑ…</string> | ||
| 94 | <string name="save_files_exporting">ÐкÑпорт файлов ÑохранениÑ…</string> | ||
| 89 | <string name="save_file_imported_success">УÑпешно импортировано</string> | 95 | <string name="save_file_imported_success">УÑпешно импортировано</string> |
| 90 | <string name="save_file_invalid_zip_structure">ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñтруктура папки ÑохранениÑ</string> | 96 | <string name="save_file_invalid_zip_structure">ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñтруктура папки ÑохранениÑ</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string> | 97 | <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string> |
| @@ -119,6 +125,42 @@ | |||
| 119 | <string name="manage_yuzu_data_description">Импортируйте/ÑкÑпортируйте прошивку, ключи, пользовательÑкие данные и многое другое!</string> | 125 | <string name="manage_yuzu_data_description">Импортируйте/ÑкÑпортируйте прошивку, ключи, пользовательÑкие данные и многое другое!</string> |
| 120 | <string name="share_save_file">ПоделитьÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ ÑохранениÑ</string> | 126 | <string name="share_save_file">ПоделитьÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ ÑохранениÑ</string> |
| 121 | <string name="export_save_failed">Ðе удалоÑÑŒ ÑкÑпортировать Ñохранение</string> | 127 | <string name="export_save_failed">Ðе удалоÑÑŒ ÑкÑпортировать Ñохранение</string> |
| 128 | <string name="game_folders">Папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string> | ||
| 129 | <string name="deep_scan">Глубокий анализ</string> | ||
| 130 | <string name="add_game_folder">Добавить папку Ñ Ð¸Ð³Ñ€Ð¾Ð¹</string> | ||
| 131 | <string name="folder_already_added">Ðта папка уже была добавлена!</string> | ||
| 132 | <string name="game_folder_properties">СвойÑтва папки игры</string> | ||
| 133 | <plurals name="saves_import_failed"> | ||
| 134 | <item quantity="one">Ðе удалоÑÑŒ импортировать %d Ñохранение</item> | ||
| 135 | <item quantity="few">Ðе удалоÑÑŒ импортировать %d ÑохранениÑ</item> | ||
| 136 | <item quantity="many">Ðе удалоÑÑŒ импортировать %d Ñохранений</item> | ||
| 137 | <item quantity="other">Ðе удалоÑÑŒ импортировать %d Ñохранений</item> | ||
| 138 | </plurals> | ||
| 139 | <plurals name="saves_import_success"> | ||
| 140 | <item quantity="one">Импортировано %d Ñохранение</item> | ||
| 141 | <item quantity="few">Импортировано %d ÑохранениÑ</item> | ||
| 142 | <item quantity="many">Импортировано %d Ñохранений</item> | ||
| 143 | <item quantity="other">Импортировано %d Ñохранений</item> | ||
| 144 | </plurals> | ||
| 145 | <string name="no_save_data_found">Ðе найдены ÑохраненмиÑ</string> | ||
| 146 | |||
| 147 | <!-- Applet launcher strings --> | ||
| 148 | <string name="applets">ЗапуÑк апплета</string> | ||
| 149 | <string name="applets_description">ЗапуÑк ÑиÑтемных апплетов на уÑтановленной прошивке</string> | ||
| 150 | <string name="applets_error_firmware">Прошивка не уÑтановлена</string> | ||
| 151 | <string name="applets_error_applet">Ðпплет недоÑтупен</string> | ||
| 152 | <string name="applets_error_description"><![CDATA[ПожалуйÑта, убедитеÑÑŒ, что ваш<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> и <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> уÑтановлены и попробуйте еще раз.]]></string> | ||
| 153 | <string name="album_applet">Ðльбом</string> | ||
| 154 | <string name="album_applet_description">ПроÑмотрите изображениÑ, Ñохраненные в папке Ñкриншотов пользователÑ, Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемного проÑмотрщика фотографий.</string> | ||
| 155 | <string name="mii_edit_applet">Mii редактор</string> | ||
| 156 | <string name="mii_edit_applet_description">ПроÑмотр и редактирование Mii Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемного редактора</string> | ||
| 157 | <string name="cabinet_applet">Шкаф</string> | ||
| 158 | <string name="cabinet_applet_description">Редактирование и удаление данных, хранÑщихÑÑ Ð½Ð° amiibo</string> | ||
| 159 | <string name="cabinet_launcher">ЗапуÑк шкафа</string> | ||
| 160 | <string name="cabinet_nickname_and_owner">Ðикнейм и наÑтройки владельца</string> | ||
| 161 | <string name="cabinet_game_data_eraser">Удаление игровых данных</string> | ||
| 162 | <string name="cabinet_restorer">ВоÑÑтановитель</string> | ||
| 163 | <string name="cabinet_formatter">Форматтер</string> | ||
| 122 | 164 | ||
| 123 | <!-- About screen strings --> | 165 | <!-- About screen strings --> |
| 124 | <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string> | 166 | <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string> |
| @@ -162,6 +204,7 @@ | |||
| 162 | <string name="frame_limit_enable_description">Ограничивает ÑкороÑть ÑмулÑции указанным процентом от нормальной ÑкороÑти.</string> | 204 | <string name="frame_limit_enable_description">Ограничивает ÑкороÑть ÑмулÑции указанным процентом от нормальной ÑкороÑти.</string> |
| 163 | <string name="frame_limit_slider">Ограничение процента cкороÑти</string> | 205 | <string name="frame_limit_slider">Ограничение процента cкороÑти</string> |
| 164 | <string name="frame_limit_slider_description">Указывает процент Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. 100% - Ñто Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑкороÑть. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ или меньше увеличивают или уменьшают ограничение ÑкороÑти.</string> | 206 | <string name="frame_limit_slider_description">Указывает процент Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. 100% - Ñто Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑкороÑть. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ или меньше увеличивают или уменьшают ограничение ÑкороÑти.</string> |
| 207 | <string name="cpu_backend">БÑкÑнд ЦП</string> | ||
| 165 | <string name="cpu_accuracy">ТочноÑть ЦП</string> | 208 | <string name="cpu_accuracy">ТочноÑть ЦП</string> |
| 166 | <string name="value_with_units">%1$s%2$s</string> | 209 | <string name="value_with_units">%1$s%2$s</string> |
| 167 | 210 | ||
| @@ -192,6 +235,8 @@ | |||
| 192 | <string name="renderer_reactive_flushing_description">Повышение точноÑти рендеринга в некоторых играх за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string> | 235 | <string name="renderer_reactive_flushing_description">Повышение точноÑти рендеринга в некоторых играх за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string> |
| 193 | <string name="use_disk_shader_cache">КÑш шейдеров на диÑке</string> | 236 | <string name="use_disk_shader_cache">КÑш шейдеров на диÑке</string> |
| 194 | <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров.</string> | 237 | <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров.</string> |
| 238 | <string name="anisotropic_filtering">ÐÐ½Ð¸Ð·Ð¾Ñ‚Ñ€Ð¾Ð¿Ð½Ð°Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ</string> | ||
| 239 | <string name="anisotropic_filtering_description">Улучшает качеÑтво текÑтур под углом</string> | ||
| 195 | 240 | ||
| 196 | <!-- Debug settings strings --> | 241 | <!-- Debug settings strings --> |
| 197 | <string name="cpu">ЦП</string> | 242 | <string name="cpu">ЦП</string> |
| @@ -203,6 +248,8 @@ | |||
| 203 | <string name="renderer_debug_description">Переводит графичеÑкий API в режим медленной отладки.</string> | 248 | <string name="renderer_debug_description">Переводит графичеÑкий API в режим медленной отладки.</string> |
| 204 | <string name="fastmem">Fastmem</string> | 249 | <string name="fastmem">Fastmem</string> |
| 205 | 250 | ||
| 251 | <!-- Audio settings strings --> | ||
| 252 | <string name="audio_output_engine">Движок вывода</string> | ||
| 206 | <string name="audio_volume">ГромкоÑть</string> | 253 | <string name="audio_volume">ГромкоÑть</string> |
| 207 | <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string> | 254 | <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string> |
| 208 | 255 | ||
| @@ -216,6 +263,7 @@ | |||
| 216 | <string name="shutting_down">Выключение…</string> | 263 | <string name="shutting_down">Выключение…</string> |
| 217 | <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string> | 264 | <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string> |
| 218 | <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string> | 265 | <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string> |
| 266 | <string name="reset_to_default_description">СброÑить вÑе раÑширенные наÑтройки</string> | ||
| 219 | <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string> | 267 | <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string> |
| 220 | <string name="reset_all_settings_description">Ð’Ñе дополнительные наÑтройки будут Ñброшены к наÑтройке по умолчанию. Ðто невозможно отменить.</string> | 268 | <string name="reset_all_settings_description">Ð’Ñе дополнительные наÑтройки будут Ñброшены к наÑтройке по умолчанию. Ðто невозможно отменить.</string> |
| 221 | <string name="settings_reset">ÐаÑтройки Ñброшены</string> | 269 | <string name="settings_reset">ÐаÑтройки Ñброшены</string> |
| @@ -229,14 +277,24 @@ | |||
| 229 | <string name="export_failed">Ошибка ÑкÑпорта</string> | 277 | <string name="export_failed">Ошибка ÑкÑпорта</string> |
| 230 | <string name="import_failed">Ошибка импортированиÑ</string> | 278 | <string name="import_failed">Ошибка импортированиÑ</string> |
| 231 | <string name="cancelling">ОтменÑÑŽ</string> | 279 | <string name="cancelling">ОтменÑÑŽ</string> |
| 232 | 280 | <string name="install">УÑтановить</string> | |
| 281 | <string name="delete">Удалить</string> | ||
| 282 | <string name="edit">Редактировать</string> | ||
| 283 | <string name="export_success">ÐкÑпорт уÑпешно выполнен</string> | ||
| 284 | <string name="start">Start</string> | ||
| 285 | <string name="clear">ОчиÑтить</string> | ||
| 286 | <string name="global">Глобальный</string> | ||
| 287 | <string name="custom">Другое</string> | ||
| 288 | <string name="notice">Уведомление</string> | ||
| 289 | <string name="import_complete">Импорт завершен</string> | ||
| 233 | <!-- GPU driver installation --> | 290 | <!-- GPU driver installation --> |
| 234 | <string name="select_gpu_driver">Выбрать драйвер ГП</string> | 291 | <string name="select_gpu_driver">Выбрать драйвер ГП</string> |
| 235 | <string name="select_gpu_driver_title">Хотите заменить текущий драйвер ГП?</string> | 292 | <string name="select_gpu_driver_title">Хотите заменить текущий драйвер ГП?</string> |
| 236 | <string name="select_gpu_driver_install">УÑтановить</string> | 293 | <string name="select_gpu_driver_install">УÑтановить</string> |
| 237 | <string name="select_gpu_driver_default">По умолчанию</string> | 294 | <string name="select_gpu_driver_default">По умолчанию</string> |
| 238 | <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string> | 295 | <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string> |
| 239 | <string name="select_gpu_driver_error">Выбран неверный драйвер, иÑпользуетÑÑ Ñтандартный ÑиÑтемный!</string> | 296 | <string name="select_gpu_driver_error">Выбран неподходÑщий драйвер</string> |
| 297 | <string name="driver_already_installed">Драйвер уже уÑтановлен</string> | ||
| 240 | <string name="system_gpu_driver">СиÑтемный драйвер ГП</string> | 298 | <string name="system_gpu_driver">СиÑтемный драйвер ГП</string> |
| 241 | <string name="installing_driver">УÑтановка драйвера...</string> | 299 | <string name="installing_driver">УÑтановка драйвера...</string> |
| 242 | 300 | ||
| @@ -244,11 +302,52 @@ | |||
| 244 | <string name="preferences_settings">ÐаÑтройки</string> | 302 | <string name="preferences_settings">ÐаÑтройки</string> |
| 245 | <string name="preferences_general">Общие</string> | 303 | <string name="preferences_general">Общие</string> |
| 246 | <string name="preferences_system">СиÑтема</string> | 304 | <string name="preferences_system">СиÑтема</string> |
| 305 | <string name="preferences_system_description">Режим дока, регион, Ñзык</string> | ||
| 247 | <string name="preferences_graphics">Графика</string> | 306 | <string name="preferences_graphics">Графика</string> |
| 307 | <string name="preferences_graphics_description">Уровень точноÑти, разрешение, кÑш шейдеров</string> | ||
| 248 | <string name="preferences_audio">Ðудио</string> | 308 | <string name="preferences_audio">Ðудио</string> |
| 309 | <string name="preferences_audio_description">Движок вывода, громкоÑть</string> | ||
| 249 | <string name="preferences_theme">Тема и цвет</string> | 310 | <string name="preferences_theme">Тема и цвет</string> |
| 250 | <string name="preferences_debug">Отладка</string> | 311 | <string name="preferences_debug">Отладка</string> |
| 251 | 312 | <string name="preferences_debug_description">Отладка ЦП/ГП, графичеÑкий API, fastmem</string> | |
| 313 | |||
| 314 | <!-- Game properties --> | ||
| 315 | <string name="info">ИнформациÑ</string> | ||
| 316 | <string name="info_description">ID программы, Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð², верÑиÑ</string> | ||
| 317 | <string name="per_game_settings">ÐаÑтройки Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ игры</string> | ||
| 318 | <string name="per_game_settings_description">Изменить наÑтройки Ñтой игры</string> | ||
| 319 | <string name="launch_options">ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿ÑƒÑка</string> | ||
| 320 | <string name="path">Путь</string> | ||
| 321 | <string name="program_id">ID программы</string> | ||
| 322 | <string name="developer">Разработчик</string> | ||
| 323 | <string name="version">ВерÑиÑ</string> | ||
| 324 | <string name="copy_details">Копировать детали</string> | ||
| 325 | <string name="add_ons">ДополнениÑ</string> | ||
| 326 | <string name="add_ons_description">Включение модов, обновлений и DLC</string> | ||
| 327 | <string name="clear_shader_cache">ОчиÑтить кÑш шейдеров</string> | ||
| 328 | <string name="clear_shader_cache_description">УдалÑет вÑе шейдеры, Ñозданные во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð³Ñ€Ñ‹.</string> | ||
| 329 | <string name="clear_shader_cache_warning_description">У Ð²Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ больше лагов во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð¹ генерации кÑша шейдеров</string> | ||
| 330 | <string name="cleared_shaders_successfully">УÑпешно очищены шейдеры</string> | ||
| 331 | <string name="addons_game">Ðддоны: %1$s</string> | ||
| 332 | <string name="save_data">Сохранить данные</string> | ||
| 333 | <string name="save_data_description">УправлÑть ÑохранениÑми Ñтой игры.</string> | ||
| 334 | <string name="delete_save_data">Удалить ÑохранениÑ</string> | ||
| 335 | <string name="delete_save_data_description">Удалить вÑе ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñтой игры</string> | ||
| 336 | <string name="delete_save_data_warning_description">Ðто безвозвратно удалÑет вÑе Ñохраненные данные Ñтой игры. Ð’Ñ‹ уверены, что хотите продолжить?</string> | ||
| 337 | <string name="save_data_deleted_successfully">Данные уÑпешно удалены</string> | ||
| 338 | <string name="select_content_type">Тип контента</string> | ||
| 339 | <string name="updates_and_dlc">ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ DLC</string> | ||
| 340 | <string name="mods_and_cheats">Моды и читы</string> | ||
| 341 | <string name="addon_notice">Важное уведомление о дополнении</string> | ||
| 342 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 343 | <string name="addon_notice_description">Ð”Ð»Ñ ÑƒÑтановки модов и читов необходимо выбрать папку, Ñодержащую каталог cheats/, romfs/ или exefs/. Мы не можем гарантировать их ÑовмеÑтимоÑть Ñ Ð²Ð°ÑˆÐµÐ¹ игрой, поÑтому будьте оÑторожны!</string> | ||
| 344 | <string name="invalid_directory">Ðеверный каталог</string> | ||
| 345 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 346 | <string name="invalid_directory_description">ПожалуйÑта, убедитеÑÑŒ, что Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð²Ð°Ð¼Ð¸ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ñодержит папку cheats/, romfs/ или exefs/ и попробуйте Ñнова.</string> | ||
| 347 | <string name="addon_installed_successfully">Ðддон уÑпешно уÑтановлен</string> | ||
| 348 | <string name="verifying_content">Проверка Ñодержимого...</string> | ||
| 349 | <string name="content_install_notice">Уведомление об уÑтановке контента</string> | ||
| 350 | <string name="content_install_notice_description">Содержимое, которое вы выбрали, не ÑоответÑтвует Ñтой игре.\nУÑтановить вÑе равно?</string> | ||
| 252 | <!-- ROM loading errors --> | 351 | <!-- ROM loading errors --> |
| 253 | <string name="loader_error_encrypted">Ваш ROM зашифрованный</string> | 352 | <string name="loader_error_encrypted">Ваш ROM зашифрованный</string> |
| 254 | <string name="loader_error_encrypted_roms_description"><![CDATA[Следуйте инÑтрукциÑм, чтобы пере-дампить игровые картриджи <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\"> или <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\"> уÑтановленные игры</a>.]]></string> | 353 | <string name="loader_error_encrypted_roms_description"><![CDATA[Следуйте инÑтрукциÑм, чтобы пере-дампить игровые картриджи <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\"> или <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\"> уÑтановленные игры</a>.]]></string> |
| @@ -276,6 +375,7 @@ | |||
| 276 | <string name="emulation_pause">Пауза ÑмулÑции</string> | 375 | <string name="emulation_pause">Пауза ÑмулÑции</string> |
| 277 | <string name="emulation_unpause">Возобновить ÑмулÑцию</string> | 376 | <string name="emulation_unpause">Возобновить ÑмулÑцию</string> |
| 278 | <string name="emulation_input_overlay">ÐаÑтройка оверлеÑ</string> | 377 | <string name="emulation_input_overlay">ÐаÑтройка оверлеÑ</string> |
| 378 | <string name="touchscreen">СенÑорный Ñкран</string> | ||
| 279 | 379 | ||
| 280 | <string name="load_settings">Загрузка наÑтроек...</string> | 380 | <string name="load_settings">Загрузка наÑтроек...</string> |
| 281 | 381 | ||
| @@ -307,6 +407,7 @@ | |||
| 307 | 407 | ||
| 308 | <!-- Memory Sizes --> | 408 | <!-- Memory Sizes --> |
| 309 | <string name="memory_byte">Байт</string> | 409 | <string name="memory_byte">Байт</string> |
| 410 | <string name="memory_byte_shorthand">B</string> | ||
| 310 | <string name="memory_kilobyte">КБ</string> | 411 | <string name="memory_kilobyte">КБ</string> |
| 311 | <string name="memory_megabyte">МБ</string> | 412 | <string name="memory_megabyte">МБ</string> |
| 312 | <string name="memory_gigabyte">GB</string> | 413 | <string name="memory_gigabyte">GB</string> |
| @@ -351,9 +452,13 @@ | |||
| 351 | <string name="anti_aliasing_smaa">SMAA</string> | 452 | <string name="anti_aliasing_smaa">SMAA</string> |
| 352 | 453 | ||
| 353 | <!-- Screen Layouts --> | 454 | <!-- Screen Layouts --> |
| 455 | <string name="screen_layout_auto">Ðвто</string> | ||
| 456 | <string name="screen_layout_sensor_landscape">ÐÐ»ÑŒÐ±Ð¾Ð¼Ð½Ð°Ñ (ÑенÑор)</string> | ||
| 354 | <string name="screen_layout_landscape">Пейзаж</string> | 457 | <string name="screen_layout_landscape">Пейзаж</string> |
| 458 | <string name="screen_layout_reverse_landscape">ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ Ð°Ð»ÑŒÐ±Ð¾Ð¼Ð½Ð°Ñ</string> | ||
| 459 | <string name="screen_layout_sensor_portrait">ÐŸÐ¾Ñ€Ñ‚Ñ€ÐµÑ‚Ð½Ð°Ñ (ÑенÑор)</string> | ||
| 355 | <string name="screen_layout_portrait">Портрет</string> | 460 | <string name="screen_layout_portrait">Портрет</string> |
| 356 | <string name="screen_layout_auto">Ðвто</string> | 461 | <string name="screen_layout_reverse_portrait">ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ Ð¿Ð¾Ñ€Ñ‚Ñ€ÐµÑ‚Ð½Ð°Ñ</string> |
| 357 | 462 | ||
| 358 | <!-- Aspect Ratios --> | 463 | <!-- Aspect Ratios --> |
| 359 | <string name="ratio_default">Стандартное (16:9)</string> | 464 | <string name="ratio_default">Стандартное (16:9)</string> |
| @@ -362,6 +467,10 @@ | |||
| 362 | <string name="ratio_force_sixteen_ten">ЗаÑтавить 16:10</string> | 467 | <string name="ratio_force_sixteen_ten">ЗаÑтавить 16:10</string> |
| 363 | <string name="ratio_stretch">РаÑÑ‚Ñнуть до окна</string> | 468 | <string name="ratio_stretch">РаÑÑ‚Ñнуть до окна</string> |
| 364 | 469 | ||
| 470 | <!-- CPU Backend --> | ||
| 471 | <string name="cpu_backend_dynarmic">Dynarmic (Медленно)</string> | ||
| 472 | <string name="cpu_backend_nce">Ðативное выполнение (NCE)</string> | ||
| 473 | |||
| 365 | <!-- CPU Accuracy --> | 474 | <!-- CPU Accuracy --> |
| 366 | <string name="cpu_accuracy_accurate">Точно</string> | 475 | <string name="cpu_accuracy_accurate">Точно</string> |
| 367 | <string name="cpu_accuracy_unsafe">ÐебезопаÑно</string> | 476 | <string name="cpu_accuracy_unsafe">ÐебезопаÑно</string> |
| @@ -390,8 +499,15 @@ | |||
| 390 | <string name="theme_mode_dark">ТемнаÑ</string> | 499 | <string name="theme_mode_dark">ТемнаÑ</string> |
| 391 | 500 | ||
| 392 | <!-- Audio output engines --> | 501 | <!-- Audio output engines --> |
| 502 | <string name="oboe">oboe</string> | ||
| 393 | <string name="cubeb">cubeb</string> | 503 | <string name="cubeb">cubeb</string> |
| 394 | 504 | ||
| 505 | <!-- Anisotropic filtering options --> | ||
| 506 | <string name="multiplier_two">2x</string> | ||
| 507 | <string name="multiplier_four">4x</string> | ||
| 508 | <string name="multiplier_eight">8x</string> | ||
| 509 | <string name="multiplier_sixteen">16x</string> | ||
| 510 | |||
| 395 | <!-- Black backgrounds theme --> | 511 | <!-- Black backgrounds theme --> |
| 396 | <string name="use_black_backgrounds">Чёрный фон</string> | 512 | <string name="use_black_backgrounds">Чёрный фон</string> |
| 397 | <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string> | 513 | <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string> |
diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml index 34809dbb8..361f0b726 100644 --- a/src/android/app/src/main/res/values-uk/strings.xml +++ b/src/android/app/src/main/res/values-uk/strings.xml | |||
| @@ -143,13 +143,16 @@ | |||
| 143 | <string name="string_null">Null</string> | 143 | <string name="string_null">Null</string> |
| 144 | <string name="string_import">Імпорт</string> | 144 | <string name="string_import">Імпорт</string> |
| 145 | <string name="export">ЕкÑпорт</string> | 145 | <string name="export">ЕкÑпорт</string> |
| 146 | <string name="install">Ð’Ñтановити</string> | ||
| 147 | <string name="delete">Видалити</string> | ||
| 148 | <string name="start">Start</string> | ||
| 149 | <string name="clear">ОчиÑтити</string> | ||
| 146 | <!-- GPU driver installation --> | 150 | <!-- GPU driver installation --> |
| 147 | <string name="select_gpu_driver">Вибрати драйвер ГП</string> | 151 | <string name="select_gpu_driver">Вибрати драйвер ГП</string> |
| 148 | <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string> | 152 | <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string> |
| 149 | <string name="select_gpu_driver_install">Ð’Ñтановити</string> | 153 | <string name="select_gpu_driver_install">Ð’Ñтановити</string> |
| 150 | <string name="select_gpu_driver_default">За замовчуваннÑм</string> | 154 | <string name="select_gpu_driver_default">За замовчуваннÑм</string> |
| 151 | <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string> | 155 | <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string> |
| 152 | <string name="select_gpu_driver_error">Обрано неправильний драйвер, викориÑтовуєтьÑÑ Ñтандартний ÑиÑтемний!</string> | ||
| 153 | <string name="system_gpu_driver">СиÑтемний драйвер ГП</string> | 156 | <string name="system_gpu_driver">СиÑтемний драйвер ГП</string> |
| 154 | <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string> | 157 | <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string> |
| 155 | 158 | ||
| @@ -161,7 +164,12 @@ | |||
| 161 | <string name="preferences_audio">Ðудіо</string> | 164 | <string name="preferences_audio">Ðудіо</string> |
| 162 | <string name="preferences_theme">Тема і колір</string> | 165 | <string name="preferences_theme">Тема і колір</string> |
| 163 | <string name="preferences_debug">ÐалагодженнÑ</string> | 166 | <string name="preferences_debug">ÐалагодженнÑ</string> |
| 164 | 167 | <!-- Game properties --> | |
| 168 | <string name="info">ІнформаціÑ</string> | ||
| 169 | <string name="path">ШлÑÑ…</string> | ||
| 170 | <string name="developer">Розробник</string> | ||
| 171 | <string name="version">ВерÑÑ–Ñ</string> | ||
| 172 | <string name="add_ons">ДоповненнÑ</string> | ||
| 165 | <!-- ROM loading errors --> | 173 | <!-- ROM loading errors --> |
| 166 | <string name="loader_error_encrypted">Ваш ROM зашифрований</string> | 174 | <string name="loader_error_encrypted">Ваш ROM зашифрований</string> |
| 167 | <string name="loader_error_encrypted_keys_description"><![CDATA[Будь лаÑка, переконайтеÑÑ, що ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> вÑтановлено, щоб ігри можна було розшифрувати.]]></string> | 175 | <string name="loader_error_encrypted_keys_description"><![CDATA[Будь лаÑка, переконайтеÑÑ, що ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> вÑтановлено, щоб ігри можна було розшифрувати.]]></string> |
| @@ -173,6 +181,8 @@ | |||
| 173 | <string name="emulation_done">Готово</string> | 181 | <string name="emulation_done">Готово</string> |
| 174 | <string name="emulation_control_scale">МаÑштаб</string> | 182 | <string name="emulation_control_scale">МаÑштаб</string> |
| 175 | <string name="emulation_control_opacity">ÐепрозоріÑть</string> | 183 | <string name="emulation_control_opacity">ÐепрозоріÑть</string> |
| 184 | <string name="touchscreen">СенÑорний екран</string> | ||
| 185 | |||
| 176 | <!-- Errors and warnings --> | 186 | <!-- Errors and warnings --> |
| 177 | <string name="abort_button">Перервати</string> | 187 | <string name="abort_button">Перервати</string> |
| 178 | <string name="continue_button">Продовжити</string> | 188 | <string name="continue_button">Продовжити</string> |
| @@ -192,6 +202,7 @@ | |||
| 192 | <string name="region_korea">КореÑ</string> | 202 | <string name="region_korea">КореÑ</string> |
| 193 | <string name="region_taiwan">Тайвань</string> | 203 | <string name="region_taiwan">Тайвань</string> |
| 194 | 204 | ||
| 205 | <string name="memory_byte_shorthand">B</string> | ||
| 195 | <string name="memory_gigabyte">GB</string> | 206 | <string name="memory_gigabyte">GB</string> |
| 196 | <!-- Renderer APIs --> | 207 | <!-- Renderer APIs --> |
| 197 | <string name="renderer_vulkan">Vulkan</string> | 208 | <string name="renderer_vulkan">Vulkan</string> |
| @@ -229,8 +240,8 @@ | |||
| 229 | <string name="anti_aliasing_fxaa">FXAA</string> | 240 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 230 | <string name="anti_aliasing_smaa">SMAA</string> | 241 | <string name="anti_aliasing_smaa">SMAA</string> |
| 231 | 242 | ||
| 243 | <!-- Screen Layouts --> | ||
| 232 | <string name="screen_layout_auto">Ðвто</string> | 244 | <string name="screen_layout_auto">Ðвто</string> |
| 233 | |||
| 234 | <!-- Aspect Ratios --> | 245 | <!-- Aspect Ratios --> |
| 235 | <string name="ratio_default">За замовчуваннÑм (16:9)</string> | 246 | <string name="ratio_default">За замовчуваннÑм (16:9)</string> |
| 236 | <string name="ratio_force_four_three">ЗмуÑити 4:3</string> | 247 | <string name="ratio_force_four_three">ЗмуÑити 4:3</string> |
| @@ -255,6 +266,12 @@ | |||
| 255 | <string name="theme_mode_light">Світла</string> | 266 | <string name="theme_mode_light">Світла</string> |
| 256 | <string name="theme_mode_dark">Темна</string> | 267 | <string name="theme_mode_dark">Темна</string> |
| 257 | 268 | ||
| 269 | <!-- Anisotropic filtering options --> | ||
| 270 | <string name="multiplier_two">2x</string> | ||
| 271 | <string name="multiplier_four">4x</string> | ||
| 272 | <string name="multiplier_eight">8x</string> | ||
| 273 | <string name="multiplier_sixteen">16x</string> | ||
| 274 | |||
| 258 | <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string> | 275 | <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string> |
| 259 | 276 | ||
| 260 | <string name="mute">Вимкнути звук</string> | 277 | <string name="mute">Вимкнути звук</string> |
diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml index f977db3a2..0a722f329 100644 --- a/src/android/app/src/main/res/values-vi/strings.xml +++ b/src/android/app/src/main/res/values-vi/strings.xml | |||
| @@ -157,7 +157,6 @@ | |||
| 157 | <string name="renderer_reactive_flushing_description">Cải thiện độ chÃnh xác kết xuất trong má»™t số game nhưng đồng thá»i giảm hiệu suất.</string> | 157 | <string name="renderer_reactive_flushing_description">Cải thiện độ chÃnh xác kết xuất trong má»™t số game nhưng đồng thá»i giảm hiệu suất.</string> |
| 158 | <string name="use_disk_shader_cache">Lưu bộ nhớ đệm shader trên ổ cứng</string> | 158 | <string name="use_disk_shader_cache">Lưu bộ nhớ đệm shader trên ổ cứng</string> |
| 159 | <string name="use_disk_shader_cache_description">Giảm tình trạng giáºt lag bằng cách lưu trữ và tải các shader được tạo ra ná»™i bá»™.</string> | 159 | <string name="use_disk_shader_cache_description">Giảm tình trạng giáºt lag bằng cách lưu trữ và tải các shader được tạo ra ná»™i bá»™.</string> |
| 160 | |||
| 161 | <!-- Debug settings strings --> | 160 | <!-- Debug settings strings --> |
| 162 | <string name="cpu">CPU</string> | 161 | <string name="cpu">CPU</string> |
| 163 | <string name="renderer_api">API</string> | 162 | <string name="renderer_api">API</string> |
| @@ -184,13 +183,17 @@ | |||
| 184 | <string name="string_null">Null</string> | 183 | <string name="string_null">Null</string> |
| 185 | <string name="string_import">Nháºp</string> | 184 | <string name="string_import">Nháºp</string> |
| 186 | <string name="export">Xuất</string> | 185 | <string name="export">Xuất</string> |
| 186 | <string name="install">Cà i đặt</string> | ||
| 187 | <string name="delete">Xoá</string> | ||
| 188 | <string name="start">Bắt đầu</string> | ||
| 189 | <string name="clear">Xóa</string> | ||
| 190 | <string name="custom">Tùy chỉnh</string> | ||
| 187 | <!-- GPU driver installation --> | 191 | <!-- GPU driver installation --> |
| 188 | <string name="select_gpu_driver">Chá»n driver GPU</string> | 192 | <string name="select_gpu_driver">Chá»n driver GPU</string> |
| 189 | <string name="select_gpu_driver_title">Bạn có muốn thay thế driver GPU hiện tại không?</string> | 193 | <string name="select_gpu_driver_title">Bạn có muốn thay thế driver GPU hiện tại không?</string> |
| 190 | <string name="select_gpu_driver_install">Cà i đặt</string> | 194 | <string name="select_gpu_driver_install">Cà i đặt</string> |
| 191 | <string name="select_gpu_driver_default">Mặc định</string> | 195 | <string name="select_gpu_driver_default">Mặc định</string> |
| 192 | <string name="select_gpu_driver_use_default">Dùng driver GPU mặc định</string> | 196 | <string name="select_gpu_driver_use_default">Dùng driver GPU mặc định</string> |
| 193 | <string name="select_gpu_driver_error">Driver không hợp lệ đã được chá»n, dùng mặc định hệ thống!</string> | ||
| 194 | <string name="system_gpu_driver">Driver GPU hệ thống</string> | 197 | <string name="system_gpu_driver">Driver GPU hệ thống</string> |
| 195 | <string name="installing_driver">Äang cà i đặt driver...</string> | 198 | <string name="installing_driver">Äang cà i đặt driver...</string> |
| 196 | 199 | ||
| @@ -202,7 +205,12 @@ | |||
| 202 | <string name="preferences_audio">Âm thanh</string> | 205 | <string name="preferences_audio">Âm thanh</string> |
| 203 | <string name="preferences_theme">Chủ đỠvà mà u sắc</string> | 206 | <string name="preferences_theme">Chủ đỠvà mà u sắc</string> |
| 204 | <string name="preferences_debug">Gỡ lỗi</string> | 207 | <string name="preferences_debug">Gỡ lỗi</string> |
| 205 | 208 | <!-- Game properties --> | |
| 209 | <string name="info">Thông tin</string> | ||
| 210 | <string name="path">ÄÆ°á»ng dẫn</string> | ||
| 211 | <string name="developer">Nhà phát triển</string> | ||
| 212 | <string name="version">Phiên bản</string> | ||
| 213 | <string name="add_ons">Add-ons</string> | ||
| 206 | <!-- ROM loading errors --> | 214 | <!-- ROM loading errors --> |
| 207 | <string name="loader_error_encrypted">ROM của bạn đã bị mã hoá</string> | 215 | <string name="loader_error_encrypted">ROM của bạn đã bị mã hoá</string> |
| 208 | <string name="loader_error_encrypted_keys_description"><![CDATA[Vui lòng đảm bảo tệp <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> đã được cà i đặt để các game có thể được giải mã.]]></string> | 216 | <string name="loader_error_encrypted_keys_description"><![CDATA[Vui lòng đảm bảo tệp <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> đã được cà i đặt để các game có thể được giải mã.]]></string> |
| @@ -229,6 +237,7 @@ | |||
| 229 | <string name="emulation_pause">Tạm đừng giả láºp</string> | 237 | <string name="emulation_pause">Tạm đừng giả láºp</string> |
| 230 | <string name="emulation_unpause">Tiếp tục giả láºp</string> | 238 | <string name="emulation_unpause">Tiếp tục giả láºp</string> |
| 231 | <string name="emulation_input_overlay">Tuỳ chá»n lá»›p phá»§</string> | 239 | <string name="emulation_input_overlay">Tuỳ chá»n lá»›p phá»§</string> |
| 240 | <string name="touchscreen">Mà n hình cảm ứng</string> | ||
| 232 | 241 | ||
| 233 | <string name="load_settings">Äang tải cà i đặt...</string> | 242 | <string name="load_settings">Äang tải cà i đặt...</string> |
| 234 | 243 | ||
| @@ -254,6 +263,7 @@ | |||
| 254 | <string name="region_korea">Hà n Quốc</string> | 263 | <string name="region_korea">Hà n Quốc</string> |
| 255 | <string name="region_taiwan">ÄÃ i Loan</string> | 264 | <string name="region_taiwan">ÄÃ i Loan</string> |
| 256 | 265 | ||
| 266 | <string name="memory_byte_shorthand">B</string> | ||
| 257 | <string name="memory_gigabyte">GB</string> | 267 | <string name="memory_gigabyte">GB</string> |
| 258 | <!-- Renderer APIs --> | 268 | <!-- Renderer APIs --> |
| 259 | <string name="renderer_vulkan">Vulkan</string> | 269 | <string name="renderer_vulkan">Vulkan</string> |
| @@ -291,8 +301,8 @@ | |||
| 291 | <string name="anti_aliasing_fxaa">FXAA</string> | 301 | <string name="anti_aliasing_fxaa">FXAA</string> |
| 292 | <string name="anti_aliasing_smaa">SMAA</string> | 302 | <string name="anti_aliasing_smaa">SMAA</string> |
| 293 | 303 | ||
| 304 | <!-- Screen Layouts --> | ||
| 294 | <string name="screen_layout_auto">Tự động</string> | 305 | <string name="screen_layout_auto">Tự động</string> |
| 295 | |||
| 296 | <!-- Aspect Ratios --> | 306 | <!-- Aspect Ratios --> |
| 297 | <string name="ratio_default">Mặc định (16:9)</string> | 307 | <string name="ratio_default">Mặc định (16:9)</string> |
| 298 | <string name="ratio_force_four_three">Dùng 4:3</string> | 308 | <string name="ratio_force_four_three">Dùng 4:3</string> |
| @@ -327,6 +337,12 @@ | |||
| 327 | <string name="theme_mode_light">Sáng</string> | 337 | <string name="theme_mode_light">Sáng</string> |
| 328 | <string name="theme_mode_dark">Tối</string> | 338 | <string name="theme_mode_dark">Tối</string> |
| 329 | 339 | ||
| 340 | <!-- Anisotropic filtering options --> | ||
| 341 | <string name="multiplier_two">2x</string> | ||
| 342 | <string name="multiplier_four">4x</string> | ||
| 343 | <string name="multiplier_eight">8x</string> | ||
| 344 | <string name="multiplier_sixteen">16x</string> | ||
| 345 | |||
| 330 | <!-- Black backgrounds theme --> | 346 | <!-- Black backgrounds theme --> |
| 331 | <string name="use_black_backgrounds">Ná»n Ä‘en</string> | 347 | <string name="use_black_backgrounds">Ná»n Ä‘en</string> |
| 332 | <string name="use_black_backgrounds_description">Khi sá» dụng chá»§ đỠtối, hãy áp dụng ná»n Ä‘en.</string> | 348 | <string name="use_black_backgrounds_description">Khi sá» dụng chá»§ đỠtối, hãy áp dụng ná»n Ä‘en.</string> |
diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml index 13455564f..b840591a4 100644 --- a/src/android/app/src/main/res/values-zh-rCN/strings.xml +++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | <string name="empty_gamelist">找ä¸åˆ°æ¸¸æˆï¼Œæˆ–è€…å°šæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ã€‚</string> | 34 | <string name="empty_gamelist">找ä¸åˆ°æ¸¸æˆï¼Œæˆ–è€…å°šæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ã€‚</string> |
| 35 | <string name="search_and_filter_games">æœç´¢æ¸¸æˆ</string> | 35 | <string name="search_and_filter_games">æœç´¢æ¸¸æˆ</string> |
| 36 | <string name="select_games_folder">é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string> | 36 | <string name="select_games_folder">é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string> |
| 37 | <string name="manage_game_folders">ç®¡ç†æ¸¸æˆæ–‡ä»¶å¤¹</string> | ||
| 37 | <string name="select_games_folder_description">å…许 yuzu 填充游æˆåˆ—表</string> | 38 | <string name="select_games_folder_description">å…许 yuzu 填充游æˆåˆ—表</string> |
| 38 | <string name="add_games_warning">è·³è¿‡é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Ÿ</string> | 39 | <string name="add_games_warning">è·³è¿‡é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Ÿ</string> |
| 39 | <string name="add_games_warning_description">å¦‚æžœæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Œæ¸¸æˆå°†ä¸ä¼šæ˜¾ç¤ºåœ¨æ¸¸æˆåˆ—表ä¸ã€‚</string> | 40 | <string name="add_games_warning_description">å¦‚æžœæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Œæ¸¸æˆå°†ä¸ä¼šæ˜¾ç¤ºåœ¨æ¸¸æˆåˆ—表ä¸ã€‚</string> |
| @@ -68,6 +69,7 @@ | |||
| 68 | <string name="invalid_keys_error">æ— æ•ˆçš„åŠ å¯†å¯†é’¥</string> | 69 | <string name="invalid_keys_error">æ— æ•ˆçš„åŠ å¯†å¯†é’¥</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string> | 71 | <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string> |
| 72 | <string name="gpu_driver_manager">GPU 驱动管ç†å™¨</string> | ||
| 71 | <string name="install_gpu_driver">安装 GPU 驱动</string> | 73 | <string name="install_gpu_driver">安装 GPU 驱动</string> |
| 72 | <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string> | 74 | <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string> |
| 73 | <string name="advanced_settings">高级选项</string> | 75 | <string name="advanced_settings">高级选项</string> |
| @@ -85,8 +87,12 @@ | |||
| 85 | <string name="notification_no_directory_link_description">请使用文件管ç†å™¨çš„ä¾§éƒ¨é¢æ¿æ‰‹åŠ¨å®šä½ç”¨æˆ·æ–‡ä»¶å¤¹ã€‚</string> | 87 | <string name="notification_no_directory_link_description">请使用文件管ç†å™¨çš„ä¾§éƒ¨é¢æ¿æ‰‹åŠ¨å®šä½ç”¨æˆ·æ–‡ä»¶å¤¹ã€‚</string> |
| 86 | <string name="manage_save_data">管ç†å˜æ¡£æ•°æ®</string> | 88 | <string name="manage_save_data">管ç†å˜æ¡£æ•°æ®</string> |
| 87 | <string name="manage_save_data_description">å·²æ‰¾åˆ°å˜æ¡£æ•°æ®ï¼Œè¯·é€‰æ‹©ä¸‹æ–¹çš„选项。</string> | 89 | <string name="manage_save_data_description">å·²æ‰¾åˆ°å˜æ¡£æ•°æ®ï¼Œè¯·é€‰æ‹©ä¸‹æ–¹çš„选项。</string> |
| 90 | <string name="import_save_warning">导入ä¿å˜æ•°æ®</string> | ||
| 91 | <string name="import_save_warning_description">这将用您所æä¾›çš„ä¿å˜æ•°æ®è¦†ç›–当剿‰€æœ‰çš„ä¿å˜æ•°æ®ã€‚您确定è¦ç»§ç»å—?</string> | ||
| 88 | <string name="import_export_saves_description">å¯¼å…¥æˆ–å¯¼å‡ºå˜æ¡£</string> | 92 | <string name="import_export_saves_description">å¯¼å…¥æˆ–å¯¼å‡ºå˜æ¡£</string> |
| 89 | <string name="save_file_imported_success">å·²æˆåŠŸå¯¼å…¥å˜æ¡£</string> | 93 | <string name="save_files_importing">æ£åœ¨å¯¼å…¥å˜æ¡£æ–‡ä»¶...</string> |
| 94 | <string name="save_files_exporting">æ£åœ¨å¯¼å‡ºå˜æ¡£æ–‡ä»¶...</string> | ||
| 95 | <string name="save_file_imported_success">导入æˆåŠŸ</string> | ||
| 90 | <string name="save_file_invalid_zip_structure">æ— æ•ˆçš„å˜æ¡£ç›®å½•</string> | 96 | <string name="save_file_invalid_zip_structure">æ— æ•ˆçš„å˜æ¡£ç›®å½•</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªåæ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string> | 97 | <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªåæ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string> |
| 92 | <string name="import_saves">导入</string> | 98 | <string name="import_saves">导入</string> |
| @@ -118,13 +124,43 @@ | |||
| 118 | <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string> | 124 | <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string> |
| 119 | <string name="share_save_file">åˆ†äº«å˜æ¡£æ–‡ä»¶</string> | 125 | <string name="share_save_file">åˆ†äº«å˜æ¡£æ–‡ä»¶</string> |
| 120 | <string name="export_save_failed">å¯¼å‡ºå˜æ¡£æ–‡ä»¶å¤±è´¥</string> | 126 | <string name="export_save_failed">å¯¼å‡ºå˜æ¡£æ–‡ä»¶å¤±è´¥</string> |
| 127 | <string name="game_folders">æ¸¸æˆæ–‡ä»¶å¤¹</string> | ||
| 128 | <string name="deep_scan">深度扫æ</string> | ||
| 129 | <string name="add_game_folder">æ·»åŠ æ¸¸æˆæ–‡ä»¶å¤¹</string> | ||
| 130 | <string name="folder_already_added">这个文件夹先å‰å·²è¢«æ·»åŠ ï¼</string> | ||
| 131 | <string name="game_folder_properties">æ¸¸æˆæ–‡ä»¶å¤¹å±žæ€§</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="other">%d ä¸ªå˜æ¡£å¯¼å…¥å¤±è´¥</item> | ||
| 134 | </plurals> | ||
| 135 | <plurals name="saves_import_success"> | ||
| 136 | <item quantity="other">æˆåŠŸå¯¼å…¥ %d ä¸ªå˜æ¡£</item> | ||
| 137 | </plurals> | ||
| 138 | <string name="no_save_data_found">æœªæ‰¾åˆ°å˜æ¡£æ•°æ®</string> | ||
| 139 | |||
| 140 | <!-- Applet launcher strings --> | ||
| 141 | <string name="applets">å°ç¨‹åºå¯åЍ噍</string> | ||
| 142 | <string name="applets_description">使用已安装的固件å¯åŠ¨ç³»ç»Ÿå°ç¨‹åº</string> | ||
| 143 | <string name="applets_error_firmware">未安装固件</string> | ||
| 144 | <string name="applets_error_applet">å°ç¨‹åºä¸å¯ç”¨</string> | ||
| 145 | <string name="applets_error_description"><![CDATA[è¯·ç¡®ä¿ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 文件和<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">固件</a>已安装,然åŽå†è¯•一次。]]></string> | ||
| 146 | <string name="album_applet">相册</string> | ||
| 147 | <string name="album_applet_description">查看å˜å‚¨åœ¨ç”¨æˆ·å±å¹•截图文件夹ä¸çš„图åƒ</string> | ||
| 148 | <string name="mii_edit_applet">Mii edit</string> | ||
| 149 | <string name="mii_edit_applet_description">查看和编辑 Mii</string> | ||
| 150 | <string name="cabinet_applet">Cabinet</string> | ||
| 151 | <string name="cabinet_applet_description">编辑ã€åˆ 除å˜å‚¨åœ¨ amiibo 上的数æ®</string> | ||
| 152 | <string name="cabinet_launcher">Cabinet å¯åЍ噍</string> | ||
| 153 | <string name="cabinet_nickname_and_owner">昵称和所有者设置</string> | ||
| 154 | <string name="cabinet_game_data_eraser">æ¸¸æˆæ•°æ®æ“¦é™¤å™¨</string> | ||
| 155 | <string name="cabinet_restorer">æ¢å¤å™¨</string> | ||
| 156 | <string name="cabinet_formatter">æ ¼å¼åŒ–程åº</string> | ||
| 121 | 157 | ||
| 122 | <!-- About screen strings --> | 158 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string> | 159 | <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string> |
| 124 | <string name="copied_to_clipboard">å·²å¤åˆ¶åˆ°å‰ªè´´æ¿</string> | 160 | <string name="copied_to_clipboard">å·²å¤åˆ¶åˆ°å‰ªè´´æ¿</string> |
| 125 | <string name="about_app_description">一款开放æºä»£ç çš„ Switch 模拟器</string> | 161 | <string name="about_app_description">一款开放æºä»£ç çš„ Switch 模拟器</string> |
| 126 | <string name="contributors">贡献者</string> | 162 | <string name="contributors">贡献者</string> |
| 127 | <string name="contributors_description">使用æ¥è‡ª yuzu 团队的 \u2764 制作</string> | 163 | <string name="contributors_description">yuzu 团队的用 \u2764 制作</string> |
| 128 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | 164 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> |
| 129 | <string name="licenses_description">Android 版 yuzu 离ä¸å¼€è¿™äº›é¡¹ç›®çš„æ”¯æŒ</string> | 165 | <string name="licenses_description">Android 版 yuzu 离ä¸å¼€è¿™äº›é¡¹ç›®çš„æ”¯æŒ</string> |
| 130 | <string name="build">构建版本</string> | 166 | <string name="build">构建版本</string> |
| @@ -161,6 +197,7 @@ | |||
| 161 | <string name="frame_limit_enable_description">å°†è¿è¡Œé€Ÿåº¦é™åˆ¶ä¸ºæ£å¸¸é€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string> | 197 | <string name="frame_limit_enable_description">å°†è¿è¡Œé€Ÿåº¦é™åˆ¶ä¸ºæ£å¸¸é€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string> |
| 162 | <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> | 198 | <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> |
| 163 | <string name="frame_limit_slider_description">指定é™åˆ¶è¿è¡Œé€Ÿåº¦çš„百分比。100% 为æ£å¸¸é€Ÿåº¦ã€‚æ›´é«˜æˆ–æ›´ä½Žçš„å€¼å°†å¢žåŠ æˆ–é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string> | 199 | <string name="frame_limit_slider_description">指定é™åˆ¶è¿è¡Œé€Ÿåº¦çš„百分比。100% 为æ£å¸¸é€Ÿåº¦ã€‚æ›´é«˜æˆ–æ›´ä½Žçš„å€¼å°†å¢žåŠ æˆ–é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string> |
| 200 | <string name="cpu_backend">CPU åŽç«¯</string> | ||
| 164 | <string name="cpu_accuracy">CPU 精度</string> | 201 | <string name="cpu_accuracy">CPU 精度</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 202 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 203 | ||
| @@ -191,6 +228,8 @@ | |||
| 191 | <string name="renderer_reactive_flushing_description">牺牲性能,æé«˜æŸäº›æ¸¸æˆçš„æ¸²æŸ“精度。</string> | 228 | <string name="renderer_reactive_flushing_description">牺牲性能,æé«˜æŸäº›æ¸¸æˆçš„æ¸²æŸ“精度。</string> |
| 192 | <string name="use_disk_shader_cache">ç£ç›˜ç€è‰²å™¨ç¼“å˜</string> | 229 | <string name="use_disk_shader_cache">ç£ç›˜ç€è‰²å™¨ç¼“å˜</string> |
| 193 | <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“å˜äºŽç£ç›˜ä¸å¹¶è¿›è¡Œè¯»å–,以å‡å°‘å¡é¡¿ã€‚</string> | 230 | <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“å˜äºŽç£ç›˜ä¸å¹¶è¿›è¡Œè¯»å–,以å‡å°‘å¡é¡¿ã€‚</string> |
| 231 | <string name="anisotropic_filtering">å„å‘异性过滤</string> | ||
| 232 | <string name="anisotropic_filtering_description">æé«˜æ–œè§’的纹ç†è´¨é‡</string> | ||
| 194 | 233 | ||
| 195 | <!-- Debug settings strings --> | 234 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 235 | <string name="cpu">CPU</string> |
| @@ -217,6 +256,7 @@ | |||
| 217 | <string name="shutting_down">æ£åœ¨å…³é—…</string> | 256 | <string name="shutting_down">æ£åœ¨å…³é—…</string> |
| 218 | <string name="reset_setting_confirmation">您è¦å°†æ¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string> | 257 | <string name="reset_setting_confirmation">您è¦å°†æ¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string> |
| 219 | <string name="reset_to_default">æ¢å¤é»˜è®¤</string> | 258 | <string name="reset_to_default">æ¢å¤é»˜è®¤</string> |
| 259 | <string name="reset_to_default_description">é‡ç½®æ‰€æœ‰é«˜çº§é€‰é¡¹</string> | ||
| 220 | <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string> | 260 | <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string> |
| 221 | <string name="reset_all_settings_description">所有高级选项都将被é‡è®¾ï¼Œæ¤åŠ¨ä½œæ— æ³•è¿˜åŽŸã€‚</string> | 261 | <string name="reset_all_settings_description">所有高级选项都将被é‡è®¾ï¼Œæ¤åŠ¨ä½œæ— æ³•è¿˜åŽŸã€‚</string> |
| 222 | <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string> | 262 | <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string> |
| @@ -230,6 +270,18 @@ | |||
| 230 | <string name="export_failed">导出失败</string> | 270 | <string name="export_failed">导出失败</string> |
| 231 | <string name="import_failed">导入失败</string> | 271 | <string name="import_failed">导入失败</string> |
| 232 | <string name="cancelling">å–æ¶ˆä¸</string> | 272 | <string name="cancelling">å–æ¶ˆä¸</string> |
| 273 | <string name="install">安装</string> | ||
| 274 | <string name="delete">åˆ é™¤</string> | ||
| 275 | <string name="edit">编辑</string> | ||
| 276 | <string name="export_success">导出æˆåŠŸ</string> | ||
| 277 | <string name="start">开始</string> | ||
| 278 | <string name="clear">清除</string> | ||
| 279 | <string name="global">全局</string> | ||
| 280 | <string name="custom">自定义</string> | ||
| 281 | <string name="notice">æé†’</string> | ||
| 282 | <string name="import_complete">导入完æˆ</string> | ||
| 283 | <string name="more_options">更多选项</string> | ||
| 284 | <string name="use_global_setting">使用全局设置</string> | ||
| 233 | 285 | ||
| 234 | <!-- GPU driver installation --> | 286 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">选择 GPU 驱动程åº</string> | 287 | <string name="select_gpu_driver">选择 GPU 驱动程åº</string> |
| @@ -237,7 +289,8 @@ | |||
| 237 | <string name="select_gpu_driver_install">安装</string> | 289 | <string name="select_gpu_driver_install">安装</string> |
| 238 | <string name="select_gpu_driver_default">系统默认</string> | 290 | <string name="select_gpu_driver_default">系统默认</string> |
| 239 | <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string> | 291 | <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string> |
| 240 | <string name="select_gpu_driver_error">é€‰æ‹©çš„é©±åŠ¨ç¨‹åºæ— 效,将使用系统默认的驱动程åºï¼</string> | 292 | <string name="select_gpu_driver_error">é€‰æ‹©çš„é©±åŠ¨æ— æ•ˆ</string> |
| 293 | <string name="driver_already_installed">驱动已安装</string> | ||
| 241 | <string name="system_gpu_driver">系统 GPU 驱动程åº</string> | 294 | <string name="system_gpu_driver">系统 GPU 驱动程åº</string> |
| 242 | <string name="installing_driver">æ£åœ¨å®‰è£…驱动程åºâ€¦</string> | 295 | <string name="installing_driver">æ£åœ¨å®‰è£…驱动程åºâ€¦</string> |
| 243 | 296 | ||
| @@ -245,10 +298,54 @@ | |||
| 245 | <string name="preferences_settings">设置</string> | 298 | <string name="preferences_settings">设置</string> |
| 246 | <string name="preferences_general">通用</string> | 299 | <string name="preferences_general">通用</string> |
| 247 | <string name="preferences_system">系统</string> | 300 | <string name="preferences_system">系统</string> |
| 301 | <string name="preferences_system_description">主机è¿è¡Œæ¨¡å¼ã€åŒºåŸŸåŠè¯è¨€</string> | ||
| 248 | <string name="preferences_graphics">图形</string> | 302 | <string name="preferences_graphics">图形</string> |
| 303 | <string name="preferences_graphics_description">精度ç‰çº§ã€åˆ†è¾¨çއåŠç€è‰²å™¨ç¼“å˜</string> | ||
| 249 | <string name="preferences_audio">声音</string> | 304 | <string name="preferences_audio">声音</string> |
| 305 | <string name="preferences_audio_description">输出引擎åŠéŸ³é‡</string> | ||
| 250 | <string name="preferences_theme">主题和色彩</string> | 306 | <string name="preferences_theme">主题和色彩</string> |
| 251 | <string name="preferences_debug">调试</string> | 307 | <string name="preferences_debug">调试</string> |
| 308 | <string name="preferences_debug_description">CPU/GPU 调试ã€å›¾å½¢ API åŠ fastmem 内å˜è®¿é—®</string> | ||
| 309 | |||
| 310 | <!-- Game properties --> | ||
| 311 | <string name="info">ä¿¡æ¯</string> | ||
| 312 | <string name="info_description">æ¸¸æˆ IDã€å¼€å‘者åŠç‰ˆæœ¬ä¿¡æ¯</string> | ||
| 313 | <string name="per_game_settings">游æˆå•独设置</string> | ||
| 314 | <string name="per_game_settings_description">ç¼–è¾‘æ¤æ¸¸æˆçš„å•独设置项</string> | ||
| 315 | <string name="launch_options">载入é…ç½®</string> | ||
| 316 | <string name="path">路径</string> | ||
| 317 | <string name="program_id">æ¸¸æˆ ID</string> | ||
| 318 | <string name="developer">å¼€å‘商</string> | ||
| 319 | <string name="version">版本</string> | ||
| 320 | <string name="copy_details">å¤åˆ¶æ˜Žç»†</string> | ||
| 321 | <string name="add_ons">é™„åŠ é¡¹</string> | ||
| 322 | <string name="add_ons_description">ç®¡ç† modã€æ¸¸æˆæ›´æ–°åŠ DLC</string> | ||
| 323 | <string name="clear_shader_cache">清除ç€è‰²å™¨ç¼“å˜</string> | ||
| 324 | <string name="clear_shader_cache_description">åˆ é™¤æ¤æ¸¸æˆçš„æ‰€æœ‰ç€è‰²å™¨ç¼“å˜</string> | ||
| 325 | <string name="clear_shader_cache_warning_description">由于ç€è‰²å™¨ç¼“å˜çš„釿–°ç”Ÿæˆï¼Œæ‚¨å°†é釿›´å¤šå¡é¡¿</string> | ||
| 326 | <string name="cleared_shaders_successfully">ç€è‰²å™¨ç¼“å˜æ¸…除æˆåŠŸ</string> | ||
| 327 | <string name="addons_game">é™„åŠ é¡¹: %1$s</string> | ||
| 328 | <string name="save_data">ä¿å˜æ•°æ®</string> | ||
| 329 | <string name="save_data_description">ç®¡ç†æ¤æ¸¸æˆçš„ä¿å˜æ•°æ®</string> | ||
| 330 | <string name="delete_save_data">åˆ é™¤ä¿å˜æ•°æ®</string> | ||
| 331 | <string name="delete_save_data_description">åˆ é™¤æ¤æ¸¸æˆçš„æ‰€æœ‰ä¿å˜æ•°æ®</string> | ||
| 332 | <string name="delete_save_data_warning_description">è¿™å°†åˆ é™¤æ¤æ¸¸æˆçš„æ‰€æœ‰ä¿å˜æ•°æ®ä¸”ä¸å¯æ’¤é”€ã€‚您确定è¦ç»§ç»å—?</string> | ||
| 333 | <string name="save_data_deleted_successfully">ä¿å˜æ•°æ®åˆ 除æˆåŠŸ</string> | ||
| 334 | <string name="select_content_type">内容类型</string> | ||
| 335 | <string name="updates_and_dlc">æ¸¸æˆæ›´æ–°å’Œ DLC</string> | ||
| 336 | <string name="mods_and_cheats">Mod 和金手指</string> | ||
| 337 | <string name="addon_notice">é™„åŠ é¡¹é‡è¦æé†’</string> | ||
| 338 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 339 | <string name="addon_notice_description">为了安装 mod å’Œé‡‘æ‰‹æŒ‡ï¼Œæ‚¨å¿…é¡»é€‰æ‹©ä¸€ä¸ªåŒ…å« cheats/ã€romfs/ 或 exefs/ ç›®å½•çš„æ–‡ä»¶å¤¹ã€‚æˆ‘ä»¬æ— æ³•éªŒè¯è¿™äº›å†…容是å¦ä¸Žæ‚¨çš„æ¸¸æˆå…¼å®¹ï¼Œæ‰€ä»¥è¯·å°å¿ƒä½¿ç”¨ï¼</string> | ||
| 340 | <string name="invalid_directory">æ— æ•ˆç›®å½•</string> | ||
| 341 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 342 | <string name="invalid_directory_description">è¯·ç¡®ä¿æ‚¨é€‰æ‹©çš„ç›®å½•ä¸‹åŒ…å« cheats/ã€romfs/ 或 exefs/ 文件夹然åŽé‡è¯•。</string> | ||
| 343 | <string name="addon_installed_successfully">é™„åŠ é¡¹å®‰è£…æˆåŠŸ</string> | ||
| 344 | <string name="verifying_content">验è¯å®‰è£…内容...</string> | ||
| 345 | <string name="content_install_notice">安装æé†’</string> | ||
| 346 | <string name="content_install_notice_description">æ‚¨é€‰æ‹©å®‰è£…çš„å†…å®¹ä¸Žæ¤æ¸¸æˆä¸åŒ¹é…。\nç»§ç»å®‰è£…?</string> | ||
| 347 | <string name="confirm_uninstall">å¸è½½ç¡®è®¤</string> | ||
| 348 | <string name="confirm_uninstall_description">您确定è¦å¸è½½æ¤é™„åŠ é¡¹å—?</string> | ||
| 252 | 349 | ||
| 253 | <!-- ROM loading errors --> | 350 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">您的 ROM å·²åŠ å¯†</string> | 351 | <string name="loader_error_encrypted">您的 ROM å·²åŠ å¯†</string> |
| @@ -277,6 +374,7 @@ | |||
| 277 | <string name="emulation_pause">æš‚åœæ¨¡æ‹Ÿ</string> | 374 | <string name="emulation_pause">æš‚åœæ¨¡æ‹Ÿ</string> |
| 278 | <string name="emulation_unpause">ç»§ç»æ¨¡æ‹Ÿ</string> | 375 | <string name="emulation_unpause">ç»§ç»æ¨¡æ‹Ÿ</string> |
| 279 | <string name="emulation_input_overlay">虚拟按键选项</string> | 376 | <string name="emulation_input_overlay">虚拟按键选项</string> |
| 377 | <string name="touchscreen">触摸å±</string> | ||
| 280 | 378 | ||
| 281 | <string name="load_settings">æ£åœ¨è½½å…¥è®¾å®šâ€¦</string> | 379 | <string name="load_settings">æ£åœ¨è½½å…¥è®¾å®šâ€¦</string> |
| 282 | 380 | ||
| @@ -308,6 +406,7 @@ | |||
| 308 | 406 | ||
| 309 | <!-- Memory Sizes --> | 407 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 408 | <string name="memory_byte">Byte</string> |
| 409 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">KB</string> | 410 | <string name="memory_kilobyte">KB</string> |
| 312 | <string name="memory_megabyte">MB</string> | 411 | <string name="memory_megabyte">MB</string> |
| 313 | <string name="memory_gigabyte">GB</string> | 412 | <string name="memory_gigabyte">GB</string> |
| @@ -352,9 +451,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">ååƒç´ å½¢æ€å¦æŠ—锯齿</string> | 451 | <string name="anti_aliasing_smaa">ååƒç´ å½¢æ€å¦æŠ—锯齿</string> |
| 353 | 452 | ||
| 354 | <!-- Screen Layouts --> | 453 | <!-- Screen Layouts --> |
| 355 | <string name="screen_layout_landscape">横å‘大å±</string> | ||
| 356 | <string name="screen_layout_portrait">纵å‘å±å¹•</string> | ||
| 357 | <string name="screen_layout_auto">自动</string> | 454 | <string name="screen_layout_auto">自动</string> |
| 455 | <string name="screen_layout_sensor_landscape">ä¼ æ„Ÿå™¨æ–¹å‘æ¨ªå±</string> | ||
| 456 | <string name="screen_layout_landscape">横å±</string> | ||
| 457 | <string name="screen_layout_reverse_landscape">å呿¨ªå±</string> | ||
| 458 | <string name="screen_layout_sensor_portrait">ä¼ æ„Ÿå™¨æ–¹å‘ç«–å±</string> | ||
| 459 | <string name="screen_layout_portrait">ç«–å±</string> | ||
| 460 | <string name="screen_layout_reverse_portrait">åå‘ç«–å±</string> | ||
| 358 | 461 | ||
| 359 | <!-- Aspect Ratios --> | 462 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">默认 (16:9)</string> | 463 | <string name="ratio_default">默认 (16:9)</string> |
| @@ -363,6 +466,10 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">强制 16:10</string> | 466 | <string name="ratio_force_sixteen_ten">强制 16:10</string> |
| 364 | <string name="ratio_stretch">拉伸窗å£</string> | 467 | <string name="ratio_stretch">拉伸窗å£</string> |
| 365 | 468 | ||
| 469 | <!-- CPU Backend --> | ||
| 470 | <string name="cpu_backend_dynarmic">动æ€ç¼–译 (慢速)</string> | ||
| 471 | <string name="cpu_backend_nce">æœ¬æœºä»£ç æ‰§è¡Œ (NCE)</string> | ||
| 472 | |||
| 366 | <!-- CPU Accuracy --> | 473 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">高精度</string> | 474 | <string name="cpu_accuracy_accurate">高精度</string> |
| 368 | <string name="cpu_accuracy_unsafe">低精度</string> | 475 | <string name="cpu_accuracy_unsafe">低精度</string> |
| @@ -391,8 +498,15 @@ | |||
| 391 | <string name="theme_mode_dark">深色</string> | 498 | <string name="theme_mode_dark">深色</string> |
| 392 | 499 | ||
| 393 | <!-- Audio output engines --> | 500 | <!-- Audio output engines --> |
| 501 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 502 | <string name="cubeb">cubeb</string> |
| 395 | 503 | ||
| 504 | <!-- Anisotropic filtering options --> | ||
| 505 | <string name="multiplier_two">2x</string> | ||
| 506 | <string name="multiplier_four">4x</string> | ||
| 507 | <string name="multiplier_eight">8x</string> | ||
| 508 | <string name="multiplier_sixteen">16x</string> | ||
| 509 | |||
| 396 | <!-- Black backgrounds theme --> | 510 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">使用黑色背景</string> | 511 | <string name="use_black_backgrounds">使用黑色背景</string> |
| 398 | <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string> | 512 | <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string> |
diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml index b8f468c68..d39255714 100644 --- a/src/android/app/src/main/res/values-zh-rTW/strings.xml +++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml | |||
| @@ -34,12 +34,13 @@ | |||
| 34 | <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string> | 34 | <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string> |
| 35 | <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string> | 35 | <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string> |
| 36 | <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string> | 36 | <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string> |
| 37 | <string name="manage_game_folders">管ç†éŠæˆ²è³‡æ–™å¤¾</string> | ||
| 37 | <string name="select_games_folder_description">å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</string> | 38 | <string name="select_games_folder_description">å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</string> |
| 38 | <string name="add_games_warning">è·³éŽé¸å–éŠæˆ²è³‡æ–™å¤¾ï¼Ÿ</string> | 39 | <string name="add_games_warning">è·³éŽé¸å–éŠæˆ²è³‡æ–™å¤¾ï¼Ÿ</string> |
| 39 | <string name="add_games_warning_description">如果資料夾未é¸å–ï¼ŒéŠæˆ²å°‡ä¸æœƒé¡¯ç¤ºåœ¨éŠæˆ²æ¸…單。</string> | 40 | <string name="add_games_warning_description">如果資料夾未é¸å–ï¼ŒéŠæˆ²å°‡ä¸æœƒé¡¯ç¤ºåœ¨éŠæˆ²æ¸…單。</string> |
| 40 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> | 41 | <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> |
| 41 | <string name="home_search_games">æœå°‹éŠæˆ²</string> | 42 | <string name="home_search_games">æœå°‹éŠæˆ²</string> |
| 42 | <string name="search_settings">æœç´¢è®¾ç½®</string> | 43 | <string name="search_settings">æœå°‹è¨å®š</string> |
| 43 | <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string> | 44 | <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string> |
| 44 | <string name="install_prod_keys">å®‰è£ prod.keys</string> | 45 | <string name="install_prod_keys">å®‰è£ prod.keys</string> |
| 45 | <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string> | 46 | <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string> |
| @@ -68,10 +69,11 @@ | |||
| 68 | <string name="invalid_keys_error">ç„¡æ•ˆçš„åŠ å¯†é‡‘é‘°</string> | 69 | <string name="invalid_keys_error">ç„¡æ•ˆçš„åŠ å¯†é‡‘é‘°</string> |
| 69 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> | 70 | <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> |
| 70 | <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string> | 71 | <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string> |
| 72 | <string name="gpu_driver_manager">GPU 驅動程å¼ç®¡ç†å“¡</string> | ||
| 71 | <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string> | 73 | <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string> |
| 72 | <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string> | 74 | <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string> |
| 73 | <string name="advanced_settings">進階è¨å®š</string> | 75 | <string name="advanced_settings">進階è¨å®š</string> |
| 74 | <string name="advanced_settings_game">高级选项: %1$s</string> | 76 | <string name="advanced_settings_game">進階è¨å®šï¼š%1$s</string> |
| 75 | <string name="settings_description">進行模擬器è¨å®š</string> | 77 | <string name="settings_description">進行模擬器è¨å®š</string> |
| 76 | <string name="search_recently_played">最近éŠçŽ©</string> | 78 | <string name="search_recently_played">最近éŠçŽ©</string> |
| 77 | <string name="search_recently_added">最近新增</string> | 79 | <string name="search_recently_added">最近新增</string> |
| @@ -85,7 +87,11 @@ | |||
| 85 | <string name="notification_no_directory_link_description">請使用檔案管ç†å“¡çš„å´é‚Šé¢æ¿æ‰‹å‹•定ä½åˆ°ä½¿ç”¨è€…資料夾。</string> | 87 | <string name="notification_no_directory_link_description">請使用檔案管ç†å“¡çš„å´é‚Šé¢æ¿æ‰‹å‹•定ä½åˆ°ä½¿ç”¨è€…資料夾。</string> |
| 86 | <string name="manage_save_data">管ç†å„²å˜è³‡æ–™</string> | 88 | <string name="manage_save_data">管ç†å„²å˜è³‡æ–™</string> |
| 87 | <string name="manage_save_data_description">已找到儲å˜è³‡æ–™ï¼Œè«‹é¸å–下方的é¸é …。</string> | 89 | <string name="manage_save_data_description">已找到儲å˜è³‡æ–™ï¼Œè«‹é¸å–下方的é¸é …。</string> |
| 90 | <string name="import_save_warning">匯入儲å˜è³‡æ–™</string> | ||
| 91 | <string name="import_save_warning_description">這將會以æä¾›çš„æª”æ¡ˆè¦†å¯«æ‰€æœ‰ç¾æœ‰çš„儲å˜è³‡æ–™ï¼Œæ‚¨ç¢ºå®šè¦ç¹¼çºŒå—Žï¼Ÿ</string> | ||
| 88 | <string name="import_export_saves_description">åŒ¯å…¥æˆ–åŒ¯å‡ºå„²å˜æª”案</string> | 92 | <string name="import_export_saves_description">åŒ¯å…¥æˆ–åŒ¯å‡ºå„²å˜æª”案</string> |
| 93 | <string name="save_files_importing">æ£åœ¨åŒ¯å…¥å„²å˜æª”案…</string> | ||
| 94 | <string name="save_files_exporting">æ£åœ¨åŒ¯å‡ºå„²å˜æª”案…</string> | ||
| 89 | <string name="save_file_imported_success">å·²æˆåŠŸåŒ¯å…¥</string> | 95 | <string name="save_file_imported_success">å·²æˆåŠŸåŒ¯å…¥</string> |
| 90 | <string name="save_file_invalid_zip_structure">無效的儲å˜ç›®éŒ„çµæ§‹</string> | 96 | <string name="save_file_invalid_zip_structure">無效的儲å˜ç›®éŒ„çµæ§‹</string> |
| 91 | <string name="save_file_invalid_zip_structure_description">首個å資料夾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string> | 97 | <string name="save_file_invalid_zip_structure_description">首個å資料夾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string> |
| @@ -96,28 +102,58 @@ | |||
| 96 | <string name="firmware_installing">æ£åœ¨å®‰è£éŸŒé«”</string> | 102 | <string name="firmware_installing">æ£åœ¨å®‰è£éŸŒé«”</string> |
| 97 | <string name="firmware_installed_success">韌體已æˆåŠŸå®‰è£</string> | 103 | <string name="firmware_installed_success">韌體已æˆåŠŸå®‰è£</string> |
| 98 | <string name="firmware_installed_failure">韌體安è£å¤±æ•—</string> | 104 | <string name="firmware_installed_failure">韌體安è£å¤±æ•—</string> |
| 99 | <string name="firmware_installed_failure_description">请确ä¿å›ºä»¶ nca 文件ä½äºŽ zip åŽ‹ç¼©åŒ…çš„æ ¹ç›®å½•ï¼Œç„¶åŽé‡è¯•。</string> | 105 | <string name="firmware_installed_failure_description">請確ä¿éŸŒé«” nca æª”æ¡ˆä½æ–¼ zip å£“ç¸®æª”çš„æ ¹ç›®éŒ„ï¼Œç„¶å¾Œå†è©¦ä¸€æ¬¡ã€‚</string> |
| 100 | <string name="share_log">分享åµéŒ¯è¨˜éŒ„</string> | 106 | <string name="share_log">分享åµéŒ¯è¨˜éŒ„</string> |
| 101 | <string name="share_log_description">分享 yuzu 的記錄檔以便å°ç›¸é—œå•題進行åµéŒ¯</string> | 107 | <string name="share_log_description">分享 yuzu 的記錄檔以便å°ç›¸é—œå•題進行åµéŒ¯</string> |
| 102 | <string name="share_log_missing">找ä¸åˆ°è¨˜éŒ„檔</string> | 108 | <string name="share_log_missing">找ä¸åˆ°è¨˜éŒ„檔</string> |
| 103 | <string name="install_game_content">安è£éŠæˆ²å…§å®¹</string> | 109 | <string name="install_game_content">安è£éŠæˆ²å…§å®¹</string> |
| 104 | <string name="install_game_content_description">安è£éŠæˆ²æ›´æ–°æˆ– DLC</string> | 110 | <string name="install_game_content_description">安è£éŠæˆ²æ›´æ–°æˆ– DLC</string> |
| 105 | <string name="installing_game_content">安装ä¸...</string> | 111 | <string name="installing_game_content">æ£åœ¨å®‰è£å…§å®¹â€¦</string> |
| 106 | <string name="install_game_content_failure">å‘ NAND 安装文件时失败</string> | 112 | <string name="install_game_content_failure">å®‰è£æª”案至 NAND 時發生錯誤</string> |
| 107 | <string name="install_game_content_failure_description">请确ä¿é™„åŠ å†…å®¹çš„æœ‰æ•ˆæ€§ï¼Œå¹¶ä¸” prod.keys 密钥文件已安装。</string> | 113 | <string name="install_game_content_failure_description">請確ä¿å…§å®¹æœ‰æ•ˆä¸¦ä¸” prod.keys 檔案已安è£ã€‚</string> |
| 108 | <string name="install_game_content_failure_base">为é¿å…产生冲çªï¼Œæ¤åŠŸèƒ½ä¸èƒ½ç”¨äºŽå®‰è£…æ¸¸æˆæœ¬ä½“。</string> | 114 | <string name="install_game_content_failure_base">為é¿å…å¯èƒ½çš„è¡çªï¼Œä¸å…許安è£åŸºç¤ŽéŠæˆ²ã€‚</string> |
| 109 | <string name="install_game_content_failure_file_extension">åªæœ‰ NSP 或 XCI æ ¼å¼çš„é™„åŠ å†…å®¹å¯ä»¥å®‰è£…ã€‚è¯·ç¡®ä¿æ‚¨çš„æ¸¸æˆé™„åŠ å†…å®¹æ˜¯æœ‰æ•ˆçš„ã€‚</string> | 115 | <string name="install_game_content_failure_file_extension">åƒ…æ”¯æ´ NSP å’Œ XCI 內容,請驗è‰éŠæˆ²å…§å®¹æ˜¯å¦æœ‰æ•ˆã€‚</string> |
| 110 | <string name="install_game_content_failed_count">%1$d 安装出错</string> | 116 | <string name="install_game_content_failed_count">%1$d 安è£éŒ¯èª¤</string> |
| 111 | <string name="install_game_content_success">游æˆé™„åŠ å†…å®¹å·²æˆåŠŸå®‰è£…</string> | 117 | <string name="install_game_content_success">éŠæˆ²å…§å®¹å·²æˆåŠŸå®‰è£</string> |
| 112 | <string name="install_game_content_success_install">%1$d 安装æˆåŠŸ</string> | 118 | <string name="install_game_content_success_install">%1$d å®‰è£æˆåŠŸ</string> |
| 113 | <string name="install_game_content_success_overwrite">%1$d 覆盖安装æˆåŠŸ</string> | 119 | <string name="install_game_content_success_overwrite">%1$d 覆寫æˆåŠŸ</string> |
| 114 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> | 120 | <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> |
| 115 | <string name="custom_driver_not_supported">䏿”¯æŒè‡ªå®šä¹‰é©±åЍ</string> | 121 | <string name="custom_driver_not_supported">䏿”¯æ´è‡ªè¨‚的驅動程å¼</string> |
| 116 | <string name="custom_driver_not_supported_description">æ¤è®¾å¤‡ä¸æ”¯æŒè‡ªå®šä¹‰é©±åŠ¨ã€‚\n请之åŽå†è®¿é—®æ¤é¡¹ï¼ŒæŸ¥çœ‹æ˜¯å¦å·²ä¸ºæ¤è®¾å¤‡æ·»åŠ æ”¯æŒã€‚</string> | 122 | <string name="custom_driver_not_supported_description">æ¤è£ç½®ä¸æ”¯æ´è‡ªè¨‚的驅動程å¼ã€‚\n請以後å†ä¾†æŸ¥çœ‹æ˜¯å¦å·²æ–°å¢žæ”¯æ´ï¼</string> |
| 117 | <string name="manage_yuzu_data">ç®¡ç† yuzu æ•°æ®</string> | 123 | <string name="manage_yuzu_data">ç®¡ç† yuzu 資料</string> |
| 118 | <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string> | 124 | <string name="manage_yuzu_data_description">匯入/匯出韌體ã€é‡‘é‘°ã€ä½¿ç”¨è€…資料åŠå…¶ä»–é …ç›®ï¼</string> |
| 119 | <string name="share_save_file">åˆ†äº«å˜æ¡£æ–‡ä»¶</string> | 125 | <string name="share_save_file">åˆ†äº«å„²å˜æª”案</string> |
| 120 | <string name="export_save_failed">å¯¼å‡ºå˜æ¡£æ–‡ä»¶å¤±è´¥</string> | 126 | <string name="export_save_failed">ç„¡æ³•åŒ¯å‡ºå„²å˜æª”案</string> |
| 127 | <string name="game_folders">éŠæˆ²è³‡æ–™å¤¾</string> | ||
| 128 | <string name="deep_scan">深度掃æ</string> | ||
| 129 | <string name="add_game_folder">æ–°å¢žéŠæˆ²è³‡æ–™å¤¾</string> | ||
| 130 | <string name="folder_already_added">這個資料夾已經新增éŽäº†ï¼</string> | ||
| 131 | <string name="game_folder_properties">éŠæˆ²è³‡æ–™å¤¾å±¬æ€§</string> | ||
| 132 | <plurals name="saves_import_failed"> | ||
| 133 | <item quantity="other">%d ä¸ªå˜æ¡£å¯¼å…¥å¤±è´¥</item> | ||
| 134 | </plurals> | ||
| 135 | <plurals name="saves_import_success"> | ||
| 136 | <item quantity="other">æˆåŠŸå¯¼å…¥ %d ä¸ªå˜æ¡£</item> | ||
| 137 | </plurals> | ||
| 138 | <string name="no_save_data_found">æœªæ‰¾åˆ°å˜æ¡£æ•°æ®</string> | ||
| 139 | |||
| 140 | <!-- Applet launcher strings --> | ||
| 141 | <string name="applets">å°ç¨‹å¼å•Ÿå‹•器</string> | ||
| 142 | <string name="applets_description">使用已安è£çš„韌體啟動系統å°ç¨‹å¼</string> | ||
| 143 | <string name="applets_error_firmware">未安è£éŸŒé«”</string> | ||
| 144 | <string name="applets_error_applet">無法使用å°ç¨‹å¼</string> | ||
| 145 | <string name="applets_error_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案和<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">韌體</a>已安è£ï¼Œç„¶å¾Œå†è©¦ä¸€æ¬¡ã€‚]]></string> | ||
| 146 | <string name="album_applet">相簿</string> | ||
| 147 | <string name="album_applet_description">使用系統相片檢視器查看儲å˜åœ¨ä½¿ç”¨è€…螢幕截圖資料夾ä¸çš„å½±åƒ</string> | ||
| 148 | <string name="mii_edit_applet">Mii 編輯</string> | ||
| 149 | <string name="mii_edit_applet_description">使用系統編輯器來檢視並編輯 Mii</string> | ||
| 150 | <string name="cabinet_applet">Cabinet</string> | ||
| 151 | <string name="cabinet_applet_description">編輯ã€åˆªé™¤å„²å˜åœ¨ amiibo 上的資料</string> | ||
| 152 | <string name="cabinet_launcher">Cabinet 啟動器</string> | ||
| 153 | <string name="cabinet_nickname_and_owner">æš±ç¨±å’Œæ“æœ‰è€…è¨å®š</string> | ||
| 154 | <string name="cabinet_game_data_eraser">éŠæˆ²è³‡æ–™æ©¡ç𮿓¦</string> | ||
| 155 | <string name="cabinet_restorer">還原程å¼</string> | ||
| 156 | <string name="cabinet_formatter">æ ¼å¼å™¨</string> | ||
| 121 | 157 | ||
| 122 | <!-- About screen strings --> | 158 | <!-- About screen strings --> |
| 123 | <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string> | 159 | <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string> |
| @@ -128,16 +164,16 @@ | |||
| 128 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> | 164 | <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> |
| 129 | <string name="licenses_description">這些專案使 yuzu Android 版æˆç‚ºå¯èƒ½</string> | 165 | <string name="licenses_description">這些專案使 yuzu Android 版æˆç‚ºå¯èƒ½</string> |
| 130 | <string name="build">組建</string> | 166 | <string name="build">組建</string> |
| 131 | <string name="user_data">用户数æ®</string> | 167 | <string name="user_data">使用者資料</string> |
| 132 | <string name="user_data_description">导入/å¯¼å‡ºåº”ç”¨ç¨‹åºæ‰€æœ‰æ•°æ®ã€‚\n\nå¯¼å…¥ç”¨æˆ·æ•°æ®æ—¶ï¼Œå°†åˆ 除当剿‰€æœ‰çš„用户数æ®ï¼</string> | 168 | <string name="user_data_description">匯入/匯出所有應用程å¼è³‡æ–™ã€‚\n\nåŒ¯å…¥ä½¿ç”¨è€…è³‡æ–™æ™‚ï¼Œç¾æœ‰çš„使用者資料將被刪除ï¼</string> |
| 133 | <string name="exporting_user_data">æ£åœ¨å¯¼å‡ºç”¨æˆ·æ•°æ®...</string> | 169 | <string name="exporting_user_data">æ£åœ¨åŒ¯å‡ºä½¿ç”¨è€…資料…</string> |
| 134 | <string name="importing_user_data">æ£åœ¨å¯¼å…¥ç”¨æˆ·æ•°æ®...</string> | 170 | <string name="importing_user_data">æ£åœ¨åŒ¯å…¥ä½¿ç”¨è€…資料…</string> |
| 135 | <string name="import_user_data">导入用户数æ®</string> | 171 | <string name="import_user_data">匯入使用者資料</string> |
| 136 | <string name="invalid_yuzu_backup">æ— æ•ˆçš„ yuzu 备份</string> | 172 | <string name="invalid_yuzu_backup">無效的 yuzu 備份</string> |
| 137 | <string name="user_data_export_success">å¯¼å‡ºç”¨æˆ·æ•°æ®æˆåŠŸ</string> | 173 | <string name="user_data_export_success">使用者資料匯出æˆåŠŸ</string> |
| 138 | <string name="user_data_import_success">å¯¼å…¥ç”¨æˆ·æ•°æ®æˆåŠŸ</string> | 174 | <string name="user_data_import_success">使用者資料匯入æˆåŠŸ</string> |
| 139 | <string name="user_data_export_cancelled">已喿¶ˆå¯¼å‡ºæ•°æ®</string> | 175 | <string name="user_data_export_cancelled">åŒ¯å‡ºå·²å–æ¶ˆ</string> |
| 140 | <string name="user_data_import_failed_description">请确ä¿ç”¨æˆ·æ•°æ®æ–‡ä»¶å¤¹ä½äºŽ zip åŽ‹ç¼©åŒ…çš„æ ¹ç›®å½•ï¼Œå¹¶åœ¨ config/config.ini 路径ä¸åŒ…å«é…置文件,然åŽé‡è¯•。</string> | 176 | <string name="user_data_import_failed_description">請確ä¿ä½¿ç”¨è€…è³‡æ–™å¤¾ä½æ–¼ zip å£“ç¸®æª”çš„æ ¹ç›®éŒ„ï¼Œä¸¦åœ¨ config/config.ini 路徑ä¸åŒ…å«çµ„態檔案,並å†è©¦ä¸€æ¬¡ã€‚</string> |
| 141 | <string name="support_link">https://discord.gg/u77vRWY</string> | 177 | <string name="support_link">https://discord.gg/u77vRWY</string> |
| 142 | <string name="website_link">https://yuzu-emu.org/</string> | 178 | <string name="website_link">https://yuzu-emu.org/</string> |
| 143 | <string name="github_link">https://github.com/yuzu-emu</string> | 179 | <string name="github_link">https://github.com/yuzu-emu</string> |
| @@ -161,6 +197,7 @@ | |||
| 161 | <string name="frame_limit_enable_description">將模擬速度é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string> | 197 | <string name="frame_limit_enable_description">將模擬速度é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string> |
| 162 | <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> | 198 | <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> |
| 163 | <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。100% ç‚ºæ¨™æº–é€Ÿåº¦ï¼Œæ›´é«˜æˆ–æ›´ä½Žçš„å€¼å°‡æœƒå¢žåŠ æˆ–æ¸›å°‘é€Ÿåº¦é™åˆ¶ã€‚</string> | 199 | <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。100% ç‚ºæ¨™æº–é€Ÿåº¦ï¼Œæ›´é«˜æˆ–æ›´ä½Žçš„å€¼å°‡æœƒå¢žåŠ æˆ–æ¸›å°‘é€Ÿåº¦é™åˆ¶ã€‚</string> |
| 200 | <string name="cpu_backend">CPU 後端</string> | ||
| 164 | <string name="cpu_accuracy">CPU 準確度</string> | 201 | <string name="cpu_accuracy">CPU 準確度</string> |
| 165 | <string name="value_with_units">%1$s%2$s</string> | 202 | <string name="value_with_units">%1$s%2$s</string> |
| 166 | 203 | ||
| @@ -179,7 +216,7 @@ | |||
| 179 | <string name="renderer_accuracy">準確度層級</string> | 216 | <string name="renderer_accuracy">準確度層級</string> |
| 180 | <string name="renderer_resolution">è§£æžåº¦ (手æ/底座)</string> | 217 | <string name="renderer_resolution">è§£æžåº¦ (手æ/底座)</string> |
| 181 | <string name="renderer_vsync">VSync 模å¼</string> | 218 | <string name="renderer_vsync">VSync 模å¼</string> |
| 182 | <string name="renderer_screen_layout">å±å¹•æ–¹å‘</string> | 219 | <string name="renderer_screen_layout">æ–¹å‘</string> |
| 183 | <string name="renderer_aspect_ratio">長寬比</string> | 220 | <string name="renderer_aspect_ratio">長寬比</string> |
| 184 | <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string> | 221 | <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string> |
| 185 | <string name="renderer_anti_aliasing">消除鋸齒方法</string> | 222 | <string name="renderer_anti_aliasing">消除鋸齒方法</string> |
| @@ -191,11 +228,13 @@ | |||
| 191 | <string name="renderer_reactive_flushing_description">çŠ§ç‰²æ•ˆèƒ½ï¼Œä»¥æ”¹å–„éƒ¨åˆ†éŠæˆ²çš„è½‰è¯æº–確度。</string> | 228 | <string name="renderer_reactive_flushing_description">çŠ§ç‰²æ•ˆèƒ½ï¼Œä»¥æ”¹å–„éƒ¨åˆ†éŠæˆ²çš„è½‰è¯æº–確度。</string> |
| 192 | <string name="use_disk_shader_cache">ç£ç¢Ÿè‘—色器快å–</string> | 229 | <string name="use_disk_shader_cache">ç£ç¢Ÿè‘—色器快å–</string> |
| 193 | <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲å˜ä¸¦è¼‰å…¥è‡³ç£ç¢Ÿï¼Œæ¸›å°‘䏿–·ã€‚</string> | 230 | <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲å˜ä¸¦è¼‰å…¥è‡³ç£ç¢Ÿï¼Œæ¸›å°‘䏿–·ã€‚</string> |
| 231 | <string name="anisotropic_filtering">éžç‰å‘æ€§éŽæ¿¾</string> | ||
| 232 | <string name="anisotropic_filtering_description">改善斜角檢視時的紋ç†å“質</string> | ||
| 194 | 233 | ||
| 195 | <!-- Debug settings strings --> | 234 | <!-- Debug settings strings --> |
| 196 | <string name="cpu">CPU</string> | 235 | <string name="cpu">CPU</string> |
| 197 | <string name="cpu_debug_mode">CPU 调试</string> | 236 | <string name="cpu_debug_mode">CPU åµéŒ¯</string> |
| 198 | <string name="cpu_debug_mode_description">å°† CPU 设置为较慢的调试模å¼ã€‚</string> | 237 | <string name="cpu_debug_mode_description">å°‡ CPU è¨å®šç‚ºæ…¢é€ŸåµéŒ¯æ¨¡å¼ã€‚</string> |
| 199 | <string name="gpu">GPU</string> | 238 | <string name="gpu">GPU</string> |
| 200 | <string name="renderer_api">API</string> | 239 | <string name="renderer_api">API</string> |
| 201 | <string name="renderer_debug">圖形åµéŒ¯</string> | 240 | <string name="renderer_debug">圖形åµéŒ¯</string> |
| @@ -203,7 +242,7 @@ | |||
| 203 | <string name="fastmem">Fastmem</string> | 242 | <string name="fastmem">Fastmem</string> |
| 204 | 243 | ||
| 205 | <!-- Audio settings strings --> | 244 | <!-- Audio settings strings --> |
| 206 | <string name="audio_output_engine">输出引擎</string> | 245 | <string name="audio_output_engine">輸出引擎</string> |
| 207 | <string name="audio_volume">音é‡</string> | 246 | <string name="audio_volume">音é‡</string> |
| 208 | <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string> | 247 | <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string> |
| 209 | 248 | ||
| @@ -212,11 +251,12 @@ | |||
| 212 | <string name="ini_saved">已儲å˜è¨å®š</string> | 251 | <string name="ini_saved">已儲å˜è¨å®š</string> |
| 213 | <string name="gameid_saved">å·²å„²å˜ %1$s è¨å®š</string> | 252 | <string name="gameid_saved">å·²å„²å˜ %1$s è¨å®š</string> |
| 214 | <string name="error_saving">å„²å˜ %1$s 時發生錯誤 ini: %2$s</string> | 253 | <string name="error_saving">å„²å˜ %1$s 時發生錯誤 ini: %2$s</string> |
| 215 | <string name="unimplemented_menu">未生效èœå•</string> | 254 | <string name="unimplemented_menu">未實作的é¸å–®</string> |
| 216 | <string name="loading">æ£åœ¨è¼‰å…¥â€¦</string> | 255 | <string name="loading">æ£åœ¨è¼‰å…¥â€¦</string> |
| 217 | <string name="shutting_down">æ£åœ¨å…³é—…</string> | 256 | <string name="shutting_down">æ£åœ¨é—œé–‰â€¦</string> |
| 218 | <string name="reset_setting_confirmation">è¦å°‡æ¤è¨å®šé‡è¨å›žé è¨å€¼å—Žï¼Ÿ</string> | 257 | <string name="reset_setting_confirmation">è¦å°‡æ¤è¨å®šé‡è¨å›žé è¨å€¼å—Žï¼Ÿ</string> |
| 219 | <string name="reset_to_default">é‡è¨ç‚ºé è¨å€¼</string> | 258 | <string name="reset_to_default">é‡è¨ç‚ºé è¨å€¼</string> |
| 259 | <string name="reset_to_default_description">é‡è¨æ‰€æœ‰é€²éšŽè¨å®š</string> | ||
| 220 | <string name="reset_all_settings">é‡è¨æ‰€æœ‰è¨å®šï¼Ÿ</string> | 260 | <string name="reset_all_settings">é‡è¨æ‰€æœ‰è¨å®šï¼Ÿ</string> |
| 221 | <string name="reset_all_settings_description">所有進階è¨å®šå°‡è¢«é‡è¨ç‚ºé è¨çµ„態,æ¤å‹•作無法復原。</string> | 261 | <string name="reset_all_settings_description">所有進階è¨å®šå°‡è¢«é‡è¨ç‚ºé è¨çµ„態,æ¤å‹•作無法復原。</string> |
| 222 | <string name="settings_reset">è¨å®šå·²é‡è¨</string> | 262 | <string name="settings_reset">è¨å®šå·²é‡è¨</string> |
| @@ -227,9 +267,21 @@ | |||
| 227 | <string name="string_null">ç„¡</string> | 267 | <string name="string_null">ç„¡</string> |
| 228 | <string name="string_import">匯入</string> | 268 | <string name="string_import">匯入</string> |
| 229 | <string name="export">匯出</string> | 269 | <string name="export">匯出</string> |
| 230 | <string name="export_failed">导出失败</string> | 270 | <string name="export_failed">匯出失敗</string> |
| 231 | <string name="import_failed">导入失败</string> | 271 | <string name="import_failed">匯入失敗</string> |
| 232 | <string name="cancelling">å–æ¶ˆä¸</string> | 272 | <string name="cancelling">æ£åœ¨å–消</string> |
| 273 | <string name="install">安è£</string> | ||
| 274 | <string name="delete">刪除</string> | ||
| 275 | <string name="edit">編輯</string> | ||
| 276 | <string name="export_success">å·²æˆåŠŸåŒ¯å‡º</string> | ||
| 277 | <string name="start">é–‹å§‹</string> | ||
| 278 | <string name="clear">清除</string> | ||
| 279 | <string name="global">全域</string> | ||
| 280 | <string name="custom">自定义</string> | ||
| 281 | <string name="notice">通知</string> | ||
| 282 | <string name="import_complete">导入完æˆ</string> | ||
| 283 | <string name="more_options">更多选项</string> | ||
| 284 | <string name="use_global_setting">使用全局设置</string> | ||
| 233 | 285 | ||
| 234 | <!-- GPU driver installation --> | 286 | <!-- GPU driver installation --> |
| 235 | <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string> | 287 | <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string> |
| @@ -237,7 +289,8 @@ | |||
| 237 | <string name="select_gpu_driver_install">安è£</string> | 289 | <string name="select_gpu_driver_install">安è£</string> |
| 238 | <string name="select_gpu_driver_default">é è¨</string> | 290 | <string name="select_gpu_driver_default">é è¨</string> |
| 239 | <string name="select_gpu_driver_use_default">使用é è¨ GPU 驅動程å¼</string> | 291 | <string name="select_gpu_driver_use_default">使用é è¨ GPU 驅動程å¼</string> |
| 240 | <string name="select_gpu_driver_error">é¸å–的驅動程å¼ç„¡æ•ˆï¼Œå°‡ä½¿ç”¨ç³»çµ±é è¨é©…動程å¼ï¼</string> | 292 | <string name="select_gpu_driver_error">é¸å–的驅動程å¼ç„¡æ•ˆ</string> |
| 293 | <string name="driver_already_installed">驅動程å¼å·²å®‰è£</string> | ||
| 241 | <string name="system_gpu_driver">系統 GPU 驅動程å¼</string> | 294 | <string name="system_gpu_driver">系統 GPU 驅動程å¼</string> |
| 242 | <string name="installing_driver">æ£åœ¨å®‰è£é©…動程å¼â€¦</string> | 295 | <string name="installing_driver">æ£åœ¨å®‰è£é©…動程å¼â€¦</string> |
| 243 | 296 | ||
| @@ -245,14 +298,58 @@ | |||
| 245 | <string name="preferences_settings">è¨å®š</string> | 298 | <string name="preferences_settings">è¨å®š</string> |
| 246 | <string name="preferences_general">一般</string> | 299 | <string name="preferences_general">一般</string> |
| 247 | <string name="preferences_system">系統</string> | 300 | <string name="preferences_system">系統</string> |
| 301 | <string name="preferences_system_description">底座模å¼ã€å€åŸŸåŠèªžè¨€</string> | ||
| 248 | <string name="preferences_graphics">圖形</string> | 302 | <string name="preferences_graphics">圖形</string> |
| 303 | <string name="preferences_graphics_description">準確度層級ã€è§£æžåº¦åŠè‘—色器快å–</string> | ||
| 249 | <string name="preferences_audio">音訊</string> | 304 | <string name="preferences_audio">音訊</string> |
| 305 | <string name="preferences_audio_description">輸出引擎åŠéŸ³é‡</string> | ||
| 250 | <string name="preferences_theme">主題和色彩</string> | 306 | <string name="preferences_theme">主題和色彩</string> |
| 251 | <string name="preferences_debug">åµéŒ¯</string> | 307 | <string name="preferences_debug">åµéŒ¯</string> |
| 308 | <string name="preferences_debug_description">CPU/GPU åµéŒ¯ã€åœ–å½¢ API åŠ fastmem</string> | ||
| 309 | |||
| 310 | <!-- Game properties --> | ||
| 311 | <string name="info">資訊</string> | ||
| 312 | <string name="info_description">ç¨‹å¼ IDã€é–‹ç™¼äººå“¡åŠç‰ˆæœ¬è³‡è¨Š</string> | ||
| 313 | <string name="per_game_settings">å€‹åˆ¥éŠæˆ²è¨å®š</string> | ||
| 314 | <string name="per_game_settings_description">編輯æ¤éŠæˆ²çš„特定è¨å®š</string> | ||
| 315 | <string name="launch_options">啟動組態</string> | ||
| 316 | <string name="path">路徑</string> | ||
| 317 | <string name="program_id">ç¨‹å¼ ID</string> | ||
| 318 | <string name="developer">出版商</string> | ||
| 319 | <string name="version">版本</string> | ||
| 320 | <string name="copy_details">複製詳細資料</string> | ||
| 321 | <string name="add_ons">延伸模組</string> | ||
| 322 | <string name="add_ons_description">åˆ‡æ›æ¨¡çµ„ã€æ›´æ–°åŠ DLC</string> | ||
| 323 | <string name="clear_shader_cache">清除著色器快å–</string> | ||
| 324 | <string name="clear_shader_cache_description">éŠçŽ©æ¤éŠæˆ²æ™‚移除所有著色器組建</string> | ||
| 325 | <string name="clear_shader_cache_warning_description">由於著色器快å–çš„é‡æ–°ç”¢ç”Ÿï¼Œæ‚¨å¯èƒ½æœƒæ„Ÿåˆ°ä¸å¤ªé †æš¢</string> | ||
| 326 | <string name="cleared_shaders_successfully">著色器快å–å·²æˆåŠŸæ¸…é™¤</string> | ||
| 327 | <string name="addons_game">é™„åŠ å…ƒä»¶ï¼š%1$s</string> | ||
| 328 | <string name="save_data">儲å˜è³‡æ–™</string> | ||
| 329 | <string name="save_data_description">ç®¡ç†æ¤éŠæˆ²ç‰¹å®šçš„儲å˜è³‡æ–™</string> | ||
| 330 | <string name="delete_save_data">刪除儲å˜è³‡æ–™</string> | ||
| 331 | <string name="delete_save_data_description">移除æ¤éŠæˆ²ç‰¹å®šçš„æ‰€æœ‰å„²å˜è³‡æ–™</string> | ||
| 332 | <string name="delete_save_data_warning_description">這將會移除æ¤éŠæˆ²çš„æ‰€æœ‰å„²å˜è³‡æ–™ï¼Œä¸”無法復原,您確定è¦ç¹¼çºŒå—Žï¼Ÿ</string> | ||
| 333 | <string name="save_data_deleted_successfully">儲å˜è³‡æ–™å·²æˆåŠŸåˆªé™¤</string> | ||
| 334 | <string name="select_content_type">內容類型</string> | ||
| 335 | <string name="updates_and_dlc">æ›´æ–°åŠ DLC</string> | ||
| 336 | <string name="mods_and_cheats">模組åŠå¯†æŠ€</string> | ||
| 337 | <string name="addon_notice">é‡è¦çš„Ë™é™„åŠ å…ƒä»¶é€šçŸ¥</string> | ||
| 338 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 339 | <string name="addon_notice_description">è‹¥è¦å®‰è£æ¨¡çµ„åŠå¯†æŠ€ï¼Œæ‚¨å¿…é ˆé¸å–ä¸€å€‹åŒ…å« cheats/ã€romfs/ 或 exefs/ 的目錄。我們無法驗è‰é€™äº›å…§å®¹æ˜¯å¦èˆ‡æ‚¨çš„éŠæˆ²ç›¸å®¹ï¼Œæ‰€ä»¥è«‹å°å¿ƒä½œæ¥ï¼</string> | ||
| 340 | <string name="invalid_directory">無效的目錄</string> | ||
| 341 | <!-- "cheats/" "romfs/" and "exefs/ should not be translated --> | ||
| 342 | <string name="invalid_directory_description">è«‹ç¢ºä¿æ‚¨é¸å–çš„ç›®éŒ„åŒ…å« cheats/ã€romfs/ 或 exefs/ 資料夾,然後å†è©¦ä¸€æ¬¡ã€‚</string> | ||
| 343 | <string name="addon_installed_successfully">é™„åŠ å…ƒä»¶å·²æˆåŠŸå®‰è£</string> | ||
| 344 | <string name="verifying_content">æ£åœ¨é©—è‰å…§å®¹â€¦</string> | ||
| 345 | <string name="content_install_notice">內容安è£é€šçŸ¥</string> | ||
| 346 | <string name="content_install_notice_description">您é¸å–的內容與æ¤éŠæˆ²ä¸ç›¸ç¬¦ã€‚\nä»è¦ç¹¼çºŒå®‰è£å—Žï¼Ÿ</string> | ||
| 347 | <string name="confirm_uninstall">确认å¸è½½</string> | ||
| 348 | <string name="confirm_uninstall_description">您确定è¦å¸è½½æ¤é™„åŠ é¡¹å—?</string> | ||
| 252 | 349 | ||
| 253 | <!-- ROM loading errors --> | 350 | <!-- ROM loading errors --> |
| 254 | <string name="loader_error_encrypted">您的 ROM å·²åŠ å¯†</string> | 351 | <string name="loader_error_encrypted">您的 ROM å·²åŠ å¯†</string> |
| 255 | <string name="loader_error_encrypted_roms_description"><![CDATA[请按照指å—釿–°è½¬å‚¨æ‚¨çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">游æˆå¡å¸¦</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">已安装的游æˆ</a>。]]></string> | 352 | <string name="loader_error_encrypted_roms_description"><![CDATA[è«‹ä¾å¾ªæŒ‡å—釿–°å‚¾å°æ‚¨çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">éŠæˆ²å¡åŒ£</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">已安è£çš„éŠæˆ²</a>。]]></string> |
| 256 | <string name="loader_error_encrypted_keys_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案已安è£ï¼Œè®“éŠæˆ²å¯ä»¥è§£å¯†ã€‚]]></string> | 353 | <string name="loader_error_encrypted_keys_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案已安è£ï¼Œè®“éŠæˆ²å¯ä»¥è§£å¯†ã€‚]]></string> |
| 257 | <string name="loader_error_video_core">åˆå§‹åŒ–è¦–è¨Šæ ¸å¿ƒæ™‚ç™¼ç”ŸéŒ¯èª¤</string> | 354 | <string name="loader_error_video_core">åˆå§‹åŒ–è¦–è¨Šæ ¸å¿ƒæ™‚ç™¼ç”ŸéŒ¯èª¤</string> |
| 258 | <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ¤å•題。</string> | 355 | <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ¤å•題。</string> |
| @@ -277,6 +374,7 @@ | |||
| 277 | <string name="emulation_pause">æš«åœæ¨¡æ“¬</string> | 374 | <string name="emulation_pause">æš«åœæ¨¡æ“¬</string> |
| 278 | <string name="emulation_unpause">å–æ¶ˆæš«åœæ¨¡æ“¬</string> | 375 | <string name="emulation_unpause">å–æ¶ˆæš«åœæ¨¡æ“¬</string> |
| 279 | <string name="emulation_input_overlay">覆疊é¸é …</string> | 376 | <string name="emulation_input_overlay">覆疊é¸é …</string> |
| 377 | <string name="touchscreen">觸控螢幕</string> | ||
| 280 | 378 | ||
| 281 | <string name="load_settings">æ£åœ¨è¼‰å…¥è¨å®šâ€¦</string> | 379 | <string name="load_settings">æ£åœ¨è¼‰å…¥è¨å®šâ€¦</string> |
| 282 | 380 | ||
| @@ -293,9 +391,9 @@ | |||
| 293 | <string name="fatal_error">åš´é‡éŒ¯èª¤</string> | 391 | <string name="fatal_error">åš´é‡éŒ¯èª¤</string> |
| 294 | <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string> | 392 | <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string> |
| 295 | <string name="performance_warning">關閉æ¤è¨å®šæœƒé¡¯è‘—é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè°æ‚¨å°‡æ¤è¨å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string> | 393 | <string name="performance_warning">關閉æ¤è¨å®šæœƒé¡¯è‘—é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè°æ‚¨å°‡æ¤è¨å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string> |
| 296 | <string name="device_memory_inadequate">设备 RAM: %1$s\n推è RAM: %2$s</string> | 394 | <string name="device_memory_inadequate">è£ç½® RAM: %1$s\nå»ºè° RAM: %2$s</string> |
| 297 | <string name="memory_formatted">%1$s%2$s</string> | 395 | <string name="memory_formatted">%1$s%2$s</string> |
| 298 | <string name="no_game_present">当剿²¡æœ‰å¯å¯åŠ¨çš„æ¸¸æˆï¼</string> | 396 | <string name="no_game_present">ç›®å‰æ²’有å¯å•Ÿå‹•çš„éŠæˆ²ï¼</string> |
| 299 | 397 | ||
| 300 | <!-- Region Names --> | 398 | <!-- Region Names --> |
| 301 | <string name="region_japan">日本</string> | 399 | <string name="region_japan">日本</string> |
| @@ -308,9 +406,10 @@ | |||
| 308 | 406 | ||
| 309 | <!-- Memory Sizes --> | 407 | <!-- Memory Sizes --> |
| 310 | <string name="memory_byte">Byte</string> | 408 | <string name="memory_byte">Byte</string> |
| 409 | <string name="memory_byte_shorthand">B</string> | ||
| 311 | <string name="memory_kilobyte">KB</string> | 410 | <string name="memory_kilobyte">KB</string> |
| 312 | <string name="memory_megabyte">MB</string> | 411 | <string name="memory_megabyte">MB</string> |
| 313 | <string name="memory_gigabyte">英國</string> | 412 | <string name="memory_gigabyte">GB</string> |
| 314 | <string name="memory_terabyte">TB</string> | 413 | <string name="memory_terabyte">TB</string> |
| 315 | <string name="memory_petabyte">PB</string> | 414 | <string name="memory_petabyte">PB</string> |
| 316 | <string name="memory_exabyte">EB</string> | 415 | <string name="memory_exabyte">EB</string> |
| @@ -352,9 +451,13 @@ | |||
| 352 | <string name="anti_aliasing_smaa">SMAA</string> | 451 | <string name="anti_aliasing_smaa">SMAA</string> |
| 353 | 452 | ||
| 354 | <!-- Screen Layouts --> | 453 | <!-- Screen Layouts --> |
| 355 | <string name="screen_layout_landscape">横å‘大å±</string> | ||
| 356 | <string name="screen_layout_portrait">纵å‘å±å¹•</string> | ||
| 357 | <string name="screen_layout_auto">自動</string> | 454 | <string name="screen_layout_auto">自動</string> |
| 455 | <string name="screen_layout_sensor_landscape">感應器橫å‘螢幕</string> | ||
| 456 | <string name="screen_layout_landscape">æ©«å‘</string> | ||
| 457 | <string name="screen_layout_reverse_landscape">å轉橫å‘螢幕</string> | ||
| 458 | <string name="screen_layout_sensor_portrait">感應器直å‘螢幕</string> | ||
| 459 | <string name="screen_layout_portrait">ç›´å‘</string> | ||
| 460 | <string name="screen_layout_reverse_portrait">å轉直å‘螢幕</string> | ||
| 358 | 461 | ||
| 359 | <!-- Aspect Ratios --> | 462 | <!-- Aspect Ratios --> |
| 360 | <string name="ratio_default">é è¨ (16:9)</string> | 463 | <string name="ratio_default">é è¨ (16:9)</string> |
| @@ -363,6 +466,10 @@ | |||
| 363 | <string name="ratio_force_sixteen_ten">強制 16:10</string> | 466 | <string name="ratio_force_sixteen_ten">強制 16:10</string> |
| 364 | <string name="ratio_stretch">延展視窗</string> | 467 | <string name="ratio_stretch">延展視窗</string> |
| 365 | 468 | ||
| 469 | <!-- CPU Backend --> | ||
| 470 | <string name="cpu_backend_dynarmic">å‹•æ…‹ (æ…¢)</string> | ||
| 471 | <string name="cpu_backend_nce">機器碼執行 (NCE)</string> | ||
| 472 | |||
| 366 | <!-- CPU Accuracy --> | 473 | <!-- CPU Accuracy --> |
| 367 | <string name="cpu_accuracy_accurate">高精度</string> | 474 | <string name="cpu_accuracy_accurate">高精度</string> |
| 368 | <string name="cpu_accuracy_unsafe">低精度</string> | 475 | <string name="cpu_accuracy_unsafe">低精度</string> |
| @@ -391,17 +498,24 @@ | |||
| 391 | <string name="theme_mode_dark">深色</string> | 498 | <string name="theme_mode_dark">深色</string> |
| 392 | 499 | ||
| 393 | <!-- Audio output engines --> | 500 | <!-- Audio output engines --> |
| 501 | <string name="oboe">oboe</string> | ||
| 394 | <string name="cubeb">cubeb</string> | 502 | <string name="cubeb">cubeb</string> |
| 395 | 503 | ||
| 504 | <!-- Anisotropic filtering options --> | ||
| 505 | <string name="multiplier_two">2x</string> | ||
| 506 | <string name="multiplier_four">4x</string> | ||
| 507 | <string name="multiplier_eight">8x</string> | ||
| 508 | <string name="multiplier_sixteen">16x</string> | ||
| 509 | |||
| 396 | <!-- Black backgrounds theme --> | 510 | <!-- Black backgrounds theme --> |
| 397 | <string name="use_black_backgrounds">黑色背景</string> | 511 | <string name="use_black_backgrounds">黑色背景</string> |
| 398 | <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string> | 512 | <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string> |
| 399 | 513 | ||
| 400 | <!-- Picture-In-Picture --> | 514 | <!-- Picture-In-Picture --> |
| 401 | <string name="picture_in_picture">ç”»ä¸ç”»</string> | 515 | <string name="picture_in_picture">åæ¯ç•«é¢</string> |
| 402 | <string name="picture_in_picture_description">模拟器ä½äºŽåŽå°æ—¶æœ€å°åŒ–窗å£</string> | 516 | <string name="picture_in_picture_description">使–¼èƒŒæ™¯æ™‚最å°åŒ–視窗</string> |
| 403 | <string name="pause">æš‚åœ</string> | 517 | <string name="pause">æš«åœ</string> |
| 404 | <string name="play">开始</string> | 518 | <string name="play">開始</string> |
| 405 | <string name="mute">éœéŸ³</string> | 519 | <string name="mute">éœéŸ³</string> |
| 406 | <string name="unmute">å–æ¶ˆéœéŸ³</string> | 520 | <string name="unmute">å–æ¶ˆéœéŸ³</string> |
| 407 | 521 | ||
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 547752bda..779eb36a8 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
| @@ -142,6 +142,8 @@ | |||
| 142 | <item quantity="other">Successfully imported %d saves</item> | 142 | <item quantity="other">Successfully imported %d saves</item> |
| 143 | </plurals> | 143 | </plurals> |
| 144 | <string name="no_save_data_found">No save data found</string> | 144 | <string name="no_save_data_found">No save data found</string> |
| 145 | <string name="verify_installed_content">Verify installed content</string> | ||
| 146 | <string name="verify_installed_content_description">Checks all installed content for corruption</string> | ||
| 145 | 147 | ||
| 146 | <!-- Applet launcher strings --> | 148 | <!-- Applet launcher strings --> |
| 147 | <string name="applets">Applet launcher</string> | 149 | <string name="applets">Applet launcher</string> |
| @@ -286,6 +288,9 @@ | |||
| 286 | <string name="custom">Custom</string> | 288 | <string name="custom">Custom</string> |
| 287 | <string name="notice">Notice</string> | 289 | <string name="notice">Notice</string> |
| 288 | <string name="import_complete">Import complete</string> | 290 | <string name="import_complete">Import complete</string> |
| 291 | <string name="more_options">More options</string> | ||
| 292 | <string name="use_global_setting">Use global setting</string> | ||
| 293 | <string name="operation_completed_successfully">The operation completed successfully</string> | ||
| 289 | 294 | ||
| 290 | <!-- GPU driver installation --> | 295 | <!-- GPU driver installation --> |
| 291 | <string name="select_gpu_driver">Select GPU driver</string> | 296 | <string name="select_gpu_driver">Select GPU driver</string> |
| @@ -348,6 +353,16 @@ | |||
| 348 | <string name="verifying_content">Verifying content…</string> | 353 | <string name="verifying_content">Verifying content…</string> |
| 349 | <string name="content_install_notice">Content install notice</string> | 354 | <string name="content_install_notice">Content install notice</string> |
| 350 | <string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string> | 355 | <string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string> |
| 356 | <string name="confirm_uninstall">Confirm uninstall</string> | ||
| 357 | <string name="confirm_uninstall_description">Are you sure you want to uninstall this addon?</string> | ||
| 358 | <string name="verify_integrity">Verify integrity</string> | ||
| 359 | <string name="verifying">Verifying…</string> | ||
| 360 | <string name="verify_success">Integrity verification succeeded!</string> | ||
| 361 | <string name="verify_failure">Integrity verification failed!</string> | ||
| 362 | <string name="verify_failure_description">File contents may be corrupt</string> | ||
| 363 | <string name="verify_no_result">Integrity verification couldn\'t be performed</string> | ||
| 364 | <string name="verify_no_result_description">File contents were not checked for validity</string> | ||
| 365 | <string name="verification_failed_for">Verification failed for the following files:\n%1$s</string> | ||
| 351 | 366 | ||
| 352 | <!-- ROM loading errors --> | 367 | <!-- ROM loading errors --> |
| 353 | <string name="loader_error_encrypted">Your ROM is encrypted</string> | 368 | <string name="loader_error_encrypted">Your ROM is encrypted</string> |
| @@ -377,6 +392,8 @@ | |||
| 377 | <string name="emulation_unpause">Unpause emulation</string> | 392 | <string name="emulation_unpause">Unpause emulation</string> |
| 378 | <string name="emulation_input_overlay">Overlay options</string> | 393 | <string name="emulation_input_overlay">Overlay options</string> |
| 379 | <string name="touchscreen">Touchscreen</string> | 394 | <string name="touchscreen">Touchscreen</string> |
| 395 | <string name="lock_drawer">Lock drawer</string> | ||
| 396 | <string name="unlock_drawer">Unlock drawer</string> | ||
| 380 | 397 | ||
| 381 | <string name="load_settings">Loading settings…</string> | 398 | <string name="load_settings">Loading settings…</string> |
| 382 | 399 | ||
diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp index 3c214ec00..2a1ae1bb3 100644 --- a/src/audio_core/device/device_session.cpp +++ b/src/audio_core/device/device_session.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "audio_core/sink/sink_stream.h" | 8 | #include "audio_core/sink/sink_stream.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 11 | #include "core/guest_memory.h" | ||
| 11 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 12 | 13 | ||
| 13 | #include "core/hle/kernel/k_process.h" | 14 | #include "core/hle/kernel/k_process.h" |
diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp index 911dae3c1..905613a5a 100644 --- a/src/audio_core/renderer/command/data_source/decode.cpp +++ b/src/audio_core/renderer/command/data_source/decode.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/fixed_point.h" | 9 | #include "common/fixed_point.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/scratch_buffer.h" | 11 | #include "common/scratch_buffer.h" |
| 12 | #include "core/guest_memory.h" | ||
| 12 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 13 | 14 | ||
| 14 | namespace AudioCore::Renderer { | 15 | namespace AudioCore::Renderer { |
diff --git a/src/common/common_types.h b/src/common/common_types.h index 0fc225aff..ae04c4d60 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h | |||
| @@ -45,6 +45,7 @@ using f32 = float; ///< 32-bit floating point | |||
| 45 | using f64 = double; ///< 64-bit floating point | 45 | using f64 = double; ///< 64-bit floating point |
| 46 | 46 | ||
| 47 | using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. | 47 | using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. |
| 48 | using DAddr = u64; ///< Represents a pointer in the device specific virtual address space. | ||
| 48 | using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. | 49 | using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. |
| 49 | using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space. | 50 | using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space. |
| 50 | 51 | ||
diff --git a/src/common/fs/file.h b/src/common/fs/file.h index 167c4d826..2e2396075 100644 --- a/src/common/fs/file.h +++ b/src/common/fs/file.h | |||
| @@ -37,7 +37,7 @@ void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path, | |||
| 37 | template <typename FileStream, typename Path> | 37 | template <typename FileStream, typename Path> |
| 38 | void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::openmode open_mode) { | 38 | void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::openmode open_mode) { |
| 39 | if constexpr (IsChar<typename Path::value_type>) { | 39 | if constexpr (IsChar<typename Path::value_type>) { |
| 40 | file_stream.open(ToU8String(path), open_mode); | 40 | file_stream.open(std::filesystem::path{ToU8String(path)}, open_mode); |
| 41 | } else { | 41 | } else { |
| 42 | file_stream.open(std::filesystem::path{path}, open_mode); | 42 | file_stream.open(std::filesystem::path{path}, open_mode); |
| 43 | } | 43 | } |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a630c257f..f75b5e10a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -37,6 +37,8 @@ add_library(core STATIC | |||
| 37 | debugger/gdbstub_arch.h | 37 | debugger/gdbstub_arch.h |
| 38 | debugger/gdbstub.cpp | 38 | debugger/gdbstub.cpp |
| 39 | debugger/gdbstub.h | 39 | debugger/gdbstub.h |
| 40 | device_memory_manager.h | ||
| 41 | device_memory_manager.inc | ||
| 40 | device_memory.cpp | 42 | device_memory.cpp |
| 41 | device_memory.h | 43 | device_memory.h |
| 42 | file_sys/fssystem/fs_i_storage.h | 44 | file_sys/fssystem/fs_i_storage.h |
| @@ -627,6 +629,8 @@ add_library(core STATIC | |||
| 627 | hle/service/ns/pdm_qry.h | 629 | hle/service/ns/pdm_qry.h |
| 628 | hle/service/nvdrv/core/container.cpp | 630 | hle/service/nvdrv/core/container.cpp |
| 629 | hle/service/nvdrv/core/container.h | 631 | hle/service/nvdrv/core/container.h |
| 632 | hle/service/nvdrv/core/heap_mapper.cpp | ||
| 633 | hle/service/nvdrv/core/heap_mapper.h | ||
| 630 | hle/service/nvdrv/core/nvmap.cpp | 634 | hle/service/nvdrv/core/nvmap.cpp |
| 631 | hle/service/nvdrv/core/nvmap.h | 635 | hle/service/nvdrv/core/nvmap.h |
| 632 | hle/service/nvdrv/core/syncpoint_manager.cpp | 636 | hle/service/nvdrv/core/syncpoint_manager.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 33afc6049..dd9de948c 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "core/file_sys/savedata_factory.h" | 28 | #include "core/file_sys/savedata_factory.h" |
| 29 | #include "core/file_sys/vfs_concat.h" | 29 | #include "core/file_sys/vfs_concat.h" |
| 30 | #include "core/file_sys/vfs_real.h" | 30 | #include "core/file_sys/vfs_real.h" |
| 31 | #include "core/gpu_dirty_memory_manager.h" | ||
| 31 | #include "core/hle/kernel/k_memory_manager.h" | 32 | #include "core/hle/kernel/k_memory_manager.h" |
| 32 | #include "core/hle/kernel/k_process.h" | 33 | #include "core/hle/kernel/k_process.h" |
| 33 | #include "core/hle/kernel/k_resource_limit.h" | 34 | #include "core/hle/kernel/k_resource_limit.h" |
| @@ -606,6 +607,9 @@ struct System::Impl { | |||
| 606 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | 607 | std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; |
| 607 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; | 608 | std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; |
| 608 | 609 | ||
| 610 | std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> | ||
| 611 | gpu_dirty_memory_managers; | ||
| 612 | |||
| 609 | std::deque<std::vector<u8>> user_channel; | 613 | std::deque<std::vector<u8>> user_channel; |
| 610 | }; | 614 | }; |
| 611 | 615 | ||
| @@ -692,8 +696,14 @@ size_t System::GetCurrentHostThreadID() const { | |||
| 692 | return impl->kernel.GetCurrentHostThreadID(); | 696 | return impl->kernel.GetCurrentHostThreadID(); |
| 693 | } | 697 | } |
| 694 | 698 | ||
| 695 | void System::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) { | 699 | std::span<GPUDirtyMemoryManager> System::GetGPUDirtyMemoryManager() { |
| 696 | return this->ApplicationProcess()->GatherGPUDirtyMemory(callback); | 700 | return impl->gpu_dirty_memory_managers; |
| 701 | } | ||
| 702 | |||
| 703 | void System::GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback) { | ||
| 704 | for (auto& manager : impl->gpu_dirty_memory_managers) { | ||
| 705 | manager.Gather(callback); | ||
| 706 | } | ||
| 697 | } | 707 | } |
| 698 | 708 | ||
| 699 | PerfStatsResults System::GetAndResetPerfStats() { | 709 | PerfStatsResults System::GetAndResetPerfStats() { |
diff --git a/src/core/core.h b/src/core/core.h index 7d49e5028..183410602 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <functional> | 8 | #include <functional> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | #include <mutex> | 10 | #include <mutex> |
| 11 | #include <span> | ||
| 11 | #include <string> | 12 | #include <string> |
| 12 | #include <vector> | 13 | #include <vector> |
| 13 | 14 | ||
| @@ -112,6 +113,7 @@ class CpuManager; | |||
| 112 | class Debugger; | 113 | class Debugger; |
| 113 | class DeviceMemory; | 114 | class DeviceMemory; |
| 114 | class ExclusiveMonitor; | 115 | class ExclusiveMonitor; |
| 116 | class GPUDirtyMemoryManager; | ||
| 115 | class PerfStats; | 117 | class PerfStats; |
| 116 | class Reporter; | 118 | class Reporter; |
| 117 | class SpeedLimiter; | 119 | class SpeedLimiter; |
| @@ -220,7 +222,9 @@ public: | |||
| 220 | /// Prepare the core emulation for a reschedule | 222 | /// Prepare the core emulation for a reschedule |
| 221 | void PrepareReschedule(u32 core_index); | 223 | void PrepareReschedule(u32 core_index); |
| 222 | 224 | ||
| 223 | void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback); | 225 | std::span<GPUDirtyMemoryManager> GetGPUDirtyMemoryManager(); |
| 226 | |||
| 227 | void GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback); | ||
| 224 | 228 | ||
| 225 | [[nodiscard]] size_t GetCurrentHostThreadID() const; | 229 | [[nodiscard]] size_t GetCurrentHostThreadID() const; |
| 226 | 230 | ||
diff --git a/src/core/device_memory.h b/src/core/device_memory.h index 13388b73e..11bf0e326 100644 --- a/src/core/device_memory.h +++ b/src/core/device_memory.h | |||
| @@ -32,6 +32,12 @@ public: | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | template <typename T> | 34 | template <typename T> |
| 35 | PAddr GetRawPhysicalAddr(const T* ptr) const { | ||
| 36 | return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - | ||
| 37 | reinterpret_cast<uintptr_t>(buffer.BackingBasePointer())); | ||
| 38 | } | ||
| 39 | |||
| 40 | template <typename T> | ||
| 35 | T* GetPointer(Common::PhysicalAddress addr) { | 41 | T* GetPointer(Common::PhysicalAddress addr) { |
| 36 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + | 42 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + |
| 37 | (GetInteger(addr) - DramMemoryMap::Base)); | 43 | (GetInteger(addr) - DramMemoryMap::Base)); |
| @@ -43,6 +49,16 @@ public: | |||
| 43 | (GetInteger(addr) - DramMemoryMap::Base)); | 49 | (GetInteger(addr) - DramMemoryMap::Base)); |
| 44 | } | 50 | } |
| 45 | 51 | ||
| 52 | template <typename T> | ||
| 53 | T* GetPointerFromRaw(PAddr addr) { | ||
| 54 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr); | ||
| 55 | } | ||
| 56 | |||
| 57 | template <typename T> | ||
| 58 | const T* GetPointerFromRaw(PAddr addr) const { | ||
| 59 | return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr); | ||
| 60 | } | ||
| 61 | |||
| 46 | Common::HostMemory buffer; | 62 | Common::HostMemory buffer; |
| 47 | }; | 63 | }; |
| 48 | 64 | ||
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h new file mode 100644 index 000000000..ffeed46cc --- /dev/null +++ b/src/core/device_memory_manager.h | |||
| @@ -0,0 +1,211 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <atomic> | ||
| 8 | #include <deque> | ||
| 9 | #include <memory> | ||
| 10 | #include <mutex> | ||
| 11 | |||
| 12 | #include "common/common_types.h" | ||
| 13 | #include "common/scratch_buffer.h" | ||
| 14 | #include "common/virtual_buffer.h" | ||
| 15 | |||
| 16 | namespace Core { | ||
| 17 | |||
| 18 | constexpr size_t DEVICE_PAGEBITS = 12ULL; | ||
| 19 | constexpr size_t DEVICE_PAGESIZE = 1ULL << DEVICE_PAGEBITS; | ||
| 20 | constexpr size_t DEVICE_PAGEMASK = DEVICE_PAGESIZE - 1ULL; | ||
| 21 | |||
| 22 | class DeviceMemory; | ||
| 23 | |||
| 24 | namespace Memory { | ||
| 25 | class Memory; | ||
| 26 | } | ||
| 27 | |||
| 28 | template <typename DTraits> | ||
| 29 | struct DeviceMemoryManagerAllocator; | ||
| 30 | |||
| 31 | struct Asid { | ||
| 32 | size_t id; | ||
| 33 | }; | ||
| 34 | |||
| 35 | template <typename Traits> | ||
| 36 | class DeviceMemoryManager { | ||
| 37 | using DeviceInterface = typename Traits::DeviceInterface; | ||
| 38 | using DeviceMethods = typename Traits::DeviceMethods; | ||
| 39 | |||
| 40 | public: | ||
| 41 | DeviceMemoryManager(const DeviceMemory& device_memory); | ||
| 42 | ~DeviceMemoryManager(); | ||
| 43 | |||
| 44 | void BindInterface(DeviceInterface* device_inter); | ||
| 45 | |||
| 46 | DAddr Allocate(size_t size); | ||
| 47 | void AllocateFixed(DAddr start, size_t size); | ||
| 48 | void Free(DAddr start, size_t size); | ||
| 49 | |||
| 50 | void Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, bool track = false); | ||
| 51 | |||
| 52 | void Unmap(DAddr address, size_t size); | ||
| 53 | |||
| 54 | void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, Asid asid); | ||
| 55 | void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, Asid asid) { | ||
| 56 | std::scoped_lock lk(mapping_guard); | ||
| 57 | TrackContinuityImpl(address, virtual_address, size, asid); | ||
| 58 | } | ||
| 59 | |||
| 60 | // Write / Read | ||
| 61 | template <typename T> | ||
| 62 | T* GetPointer(DAddr address); | ||
| 63 | |||
| 64 | template <typename T> | ||
| 65 | const T* GetPointer(DAddr address) const; | ||
| 66 | |||
| 67 | template <typename Func> | ||
| 68 | void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) { | ||
| 69 | DAddr subbits = static_cast<DAddr>(address & page_mask); | ||
| 70 | const u32 base = compressed_device_addr[(address >> page_bits)]; | ||
| 71 | if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] { | ||
| 72 | const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits; | ||
| 73 | operation(d_address); | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | InnerGatherDeviceAddresses(buffer, address); | ||
| 77 | for (u32 value : buffer) { | ||
| 78 | operation((static_cast<DAddr>(value) << page_bits) + subbits); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | template <typename Func> | ||
| 83 | void ApplyOpOnPointer(const u8* p, Common::ScratchBuffer<u32>& buffer, Func&& operation) { | ||
| 84 | PAddr address = GetRawPhysicalAddr<u8>(p); | ||
| 85 | ApplyOpOnPAddr(address, buffer, operation); | ||
| 86 | } | ||
| 87 | |||
| 88 | PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const { | ||
| 89 | PAddr subbits = static_cast<PAddr>(address & page_mask); | ||
| 90 | auto paddr = compressed_physical_ptr[(address >> page_bits)]; | ||
| 91 | if (paddr == 0) { | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits; | ||
| 95 | } | ||
| 96 | |||
| 97 | template <typename T> | ||
| 98 | void Write(DAddr address, T value); | ||
| 99 | |||
| 100 | template <typename T> | ||
| 101 | T Read(DAddr address) const; | ||
| 102 | |||
| 103 | u8* GetSpan(const DAddr src_addr, const std::size_t size); | ||
| 104 | const u8* GetSpan(const DAddr src_addr, const std::size_t size) const; | ||
| 105 | |||
| 106 | void ReadBlock(DAddr address, void* dest_pointer, size_t size); | ||
| 107 | void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size); | ||
| 108 | void WriteBlock(DAddr address, const void* src_pointer, size_t size); | ||
| 109 | void WriteBlockUnsafe(DAddr address, const void* src_pointer, size_t size); | ||
| 110 | |||
| 111 | Asid RegisterProcess(Memory::Memory* memory); | ||
| 112 | void UnregisterProcess(Asid id); | ||
| 113 | |||
| 114 | void UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta); | ||
| 115 | |||
| 116 | static constexpr size_t AS_BITS = Traits::device_virtual_bits; | ||
| 117 | |||
| 118 | private: | ||
| 119 | static constexpr size_t device_virtual_bits = Traits::device_virtual_bits; | ||
| 120 | static constexpr size_t device_as_size = 1ULL << device_virtual_bits; | ||
| 121 | static constexpr size_t physical_min_bits = 32; | ||
| 122 | static constexpr size_t physical_max_bits = 33; | ||
| 123 | static constexpr size_t page_bits = 12; | ||
| 124 | static constexpr size_t page_size = 1ULL << page_bits; | ||
| 125 | static constexpr size_t page_mask = page_size - 1ULL; | ||
| 126 | static constexpr u32 physical_address_base = 1U << page_bits; | ||
| 127 | static constexpr u32 MULTI_FLAG_BITS = 31; | ||
| 128 | static constexpr u32 MULTI_FLAG = 1U << MULTI_FLAG_BITS; | ||
| 129 | static constexpr u32 MULTI_MASK = ~MULTI_FLAG; | ||
| 130 | |||
| 131 | template <typename T> | ||
| 132 | T* GetPointerFromRaw(PAddr addr) { | ||
| 133 | return reinterpret_cast<T*>(physical_base + addr); | ||
| 134 | } | ||
| 135 | |||
| 136 | template <typename T> | ||
| 137 | const T* GetPointerFromRaw(PAddr addr) const { | ||
| 138 | return reinterpret_cast<T*>(physical_base + addr); | ||
| 139 | } | ||
| 140 | |||
| 141 | template <typename T> | ||
| 142 | PAddr GetRawPhysicalAddr(const T* ptr) const { | ||
| 143 | return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - physical_base); | ||
| 144 | } | ||
| 145 | |||
| 146 | void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory, | ||
| 147 | auto increment); | ||
| 148 | |||
| 149 | void InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, PAddr address); | ||
| 150 | |||
| 151 | std::unique_ptr<DeviceMemoryManagerAllocator<Traits>> impl; | ||
| 152 | |||
| 153 | const uintptr_t physical_base; | ||
| 154 | DeviceInterface* device_inter; | ||
| 155 | Common::VirtualBuffer<u32> compressed_physical_ptr; | ||
| 156 | Common::VirtualBuffer<u32> compressed_device_addr; | ||
| 157 | Common::VirtualBuffer<u32> continuity_tracker; | ||
| 158 | |||
| 159 | // Process memory interfaces | ||
| 160 | |||
| 161 | std::deque<size_t> id_pool; | ||
| 162 | std::deque<Memory::Memory*> registered_processes; | ||
| 163 | |||
| 164 | // Memory protection management | ||
| 165 | |||
| 166 | static constexpr size_t guest_max_as_bits = 39; | ||
| 167 | static constexpr size_t guest_as_size = 1ULL << guest_max_as_bits; | ||
| 168 | static constexpr size_t guest_mask = guest_as_size - 1ULL; | ||
| 169 | static constexpr size_t asid_start_bit = guest_max_as_bits; | ||
| 170 | |||
| 171 | std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) { | ||
| 172 | auto content = cpu_backing_address[page_index]; | ||
| 173 | const VAddr address = content & guest_mask; | ||
| 174 | const Asid asid{static_cast<size_t>(content >> asid_start_bit)}; | ||
| 175 | return std::make_pair(asid, address); | ||
| 176 | } | ||
| 177 | |||
| 178 | void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) { | ||
| 179 | cpu_backing_address[page_index] = address | (asid.id << asid_start_bit); | ||
| 180 | } | ||
| 181 | |||
| 182 | Common::VirtualBuffer<VAddr> cpu_backing_address; | ||
| 183 | static constexpr size_t subentries = 8 / sizeof(u8); | ||
| 184 | static constexpr size_t subentries_mask = subentries - 1; | ||
| 185 | class CounterEntry final { | ||
| 186 | public: | ||
| 187 | CounterEntry() = default; | ||
| 188 | |||
| 189 | std::atomic_uint8_t& Count(std::size_t page) { | ||
| 190 | return values[page & subentries_mask]; | ||
| 191 | } | ||
| 192 | |||
| 193 | const std::atomic_uint8_t& Count(std::size_t page) const { | ||
| 194 | return values[page & subentries_mask]; | ||
| 195 | } | ||
| 196 | |||
| 197 | private: | ||
| 198 | std::array<std::atomic_uint8_t, subentries> values{}; | ||
| 199 | }; | ||
| 200 | static_assert(sizeof(CounterEntry) == subentries * sizeof(u8), | ||
| 201 | "CounterEntry should be 8 bytes!"); | ||
| 202 | |||
| 203 | static constexpr size_t num_counter_entries = | ||
| 204 | (1ULL << (device_virtual_bits - page_bits)) / subentries; | ||
| 205 | using CachedPages = std::array<CounterEntry, num_counter_entries>; | ||
| 206 | std::unique_ptr<CachedPages> cached_pages; | ||
| 207 | std::mutex counter_guard; | ||
| 208 | std::mutex mapping_guard; | ||
| 209 | }; | ||
| 210 | |||
| 211 | } // namespace Core | ||
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc new file mode 100644 index 000000000..eab8a2731 --- /dev/null +++ b/src/core/device_memory_manager.inc | |||
| @@ -0,0 +1,581 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <atomic> | ||
| 5 | #include <limits> | ||
| 6 | #include <memory> | ||
| 7 | #include <type_traits> | ||
| 8 | |||
| 9 | #include "common/address_space.h" | ||
| 10 | #include "common/address_space.inc" | ||
| 11 | #include "common/alignment.h" | ||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/div_ceil.h" | ||
| 14 | #include "common/scope_exit.h" | ||
| 15 | #include "common/settings.h" | ||
| 16 | #include "core/device_memory.h" | ||
| 17 | #include "core/device_memory_manager.h" | ||
| 18 | #include "core/memory.h" | ||
| 19 | |||
| 20 | namespace Core { | ||
| 21 | |||
| 22 | namespace { | ||
| 23 | |||
| 24 | class MultiAddressContainer { | ||
| 25 | public: | ||
| 26 | MultiAddressContainer() = default; | ||
| 27 | ~MultiAddressContainer() = default; | ||
| 28 | |||
| 29 | void GatherValues(u32 start_entry, Common::ScratchBuffer<u32>& buffer) { | ||
| 30 | buffer.resize(8); | ||
| 31 | buffer.resize(0); | ||
| 32 | size_t index = 0; | ||
| 33 | const auto add_value = [&](u32 value) { | ||
| 34 | buffer.resize(index + 1); | ||
| 35 | buffer[index++] = value; | ||
| 36 | }; | ||
| 37 | |||
| 38 | u32 iter_entry = start_entry; | ||
| 39 | Entry* current = &storage[iter_entry - 1]; | ||
| 40 | add_value(current->value); | ||
| 41 | while (current->next_entry != 0) { | ||
| 42 | iter_entry = current->next_entry; | ||
| 43 | current = &storage[iter_entry - 1]; | ||
| 44 | add_value(current->value); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | u32 Register(u32 value) { | ||
| 49 | return RegisterImplementation(value); | ||
| 50 | } | ||
| 51 | |||
| 52 | void Register(u32 value, u32 start_entry) { | ||
| 53 | auto entry_id = RegisterImplementation(value); | ||
| 54 | u32 iter_entry = start_entry; | ||
| 55 | Entry* current = &storage[iter_entry - 1]; | ||
| 56 | while (current->next_entry != 0) { | ||
| 57 | iter_entry = current->next_entry; | ||
| 58 | current = &storage[iter_entry - 1]; | ||
| 59 | } | ||
| 60 | current->next_entry = entry_id; | ||
| 61 | } | ||
| 62 | |||
| 63 | std::pair<bool, u32> Unregister(u32 value, u32 start_entry) { | ||
| 64 | u32 iter_entry = start_entry; | ||
| 65 | Entry* previous{}; | ||
| 66 | Entry* current = &storage[iter_entry - 1]; | ||
| 67 | Entry* next{}; | ||
| 68 | bool more_than_one_remaining = false; | ||
| 69 | u32 result_start{start_entry}; | ||
| 70 | size_t count = 0; | ||
| 71 | while (current->value != value) { | ||
| 72 | count++; | ||
| 73 | previous = current; | ||
| 74 | iter_entry = current->next_entry; | ||
| 75 | current = &storage[iter_entry - 1]; | ||
| 76 | } | ||
| 77 | // Find next | ||
| 78 | u32 next_entry = current->next_entry; | ||
| 79 | if (next_entry != 0) { | ||
| 80 | next = &storage[next_entry - 1]; | ||
| 81 | more_than_one_remaining = next->next_entry != 0 || previous != nullptr; | ||
| 82 | } | ||
| 83 | if (previous) { | ||
| 84 | previous->next_entry = next_entry; | ||
| 85 | } else { | ||
| 86 | result_start = next_entry; | ||
| 87 | } | ||
| 88 | free_entries.emplace_back(iter_entry); | ||
| 89 | return std::make_pair(more_than_one_remaining || count > 1, result_start); | ||
| 90 | } | ||
| 91 | |||
| 92 | u32 ReleaseEntry(u32 start_entry) { | ||
| 93 | Entry* current = &storage[start_entry - 1]; | ||
| 94 | free_entries.emplace_back(start_entry); | ||
| 95 | return current->value; | ||
| 96 | } | ||
| 97 | |||
| 98 | private: | ||
| 99 | u32 RegisterImplementation(u32 value) { | ||
| 100 | auto entry_id = GetNewEntry(); | ||
| 101 | auto& entry = storage[entry_id - 1]; | ||
| 102 | entry.next_entry = 0; | ||
| 103 | entry.value = value; | ||
| 104 | return entry_id; | ||
| 105 | } | ||
| 106 | u32 GetNewEntry() { | ||
| 107 | if (!free_entries.empty()) { | ||
| 108 | u32 result = free_entries.front(); | ||
| 109 | free_entries.pop_front(); | ||
| 110 | return result; | ||
| 111 | } | ||
| 112 | storage.emplace_back(); | ||
| 113 | u32 new_entry = static_cast<u32>(storage.size()); | ||
| 114 | return new_entry; | ||
| 115 | } | ||
| 116 | |||
| 117 | struct Entry { | ||
| 118 | u32 next_entry{}; | ||
| 119 | u32 value{}; | ||
| 120 | }; | ||
| 121 | |||
| 122 | std::deque<Entry> storage; | ||
| 123 | std::deque<u32> free_entries; | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct EmptyAllocator { | ||
| 127 | EmptyAllocator([[maybe_unused]] DAddr address) {} | ||
| 128 | }; | ||
| 129 | |||
| 130 | } // namespace | ||
| 131 | |||
| 132 | template <typename DTraits> | ||
| 133 | struct DeviceMemoryManagerAllocator { | ||
| 134 | static constexpr size_t device_virtual_bits = DTraits::device_virtual_bits; | ||
| 135 | static constexpr DAddr first_address = 1ULL << Memory::YUZU_PAGEBITS; | ||
| 136 | static constexpr DAddr max_device_area = 1ULL << device_virtual_bits; | ||
| 137 | |||
| 138 | DeviceMemoryManagerAllocator() : main_allocator(first_address) {} | ||
| 139 | |||
| 140 | Common::FlatAllocator<DAddr, 0, device_virtual_bits> main_allocator; | ||
| 141 | MultiAddressContainer multi_dev_address; | ||
| 142 | |||
| 143 | /// Returns true when vaddr -> vaddr+size is fully contained in the buffer | ||
| 144 | template <bool pin_area> | ||
| 145 | [[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept { | ||
| 146 | return addr >= 0 && addr + size <= max_device_area; | ||
| 147 | } | ||
| 148 | |||
| 149 | DAddr Allocate(size_t size) { | ||
| 150 | return main_allocator.Allocate(size); | ||
| 151 | } | ||
| 152 | |||
| 153 | void AllocateFixed(DAddr b_address, size_t b_size) { | ||
| 154 | main_allocator.AllocateFixed(b_address, b_size); | ||
| 155 | } | ||
| 156 | |||
| 157 | void Free(DAddr b_address, size_t b_size) { | ||
| 158 | main_allocator.Free(b_address, b_size); | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | |||
| 162 | template <typename Traits> | ||
| 163 | DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_) | ||
| 164 | : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())}, | ||
| 165 | device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS), | ||
| 166 | compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() == | ||
| 167 | Settings::MemoryLayout::Memory_4Gb | ||
| 168 | ? physical_min_bits | ||
| 169 | : physical_max_bits) - | ||
| 170 | Memory::YUZU_PAGEBITS)), | ||
| 171 | continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS), | ||
| 172 | cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) { | ||
| 173 | impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>(); | ||
| 174 | cached_pages = std::make_unique<CachedPages>(); | ||
| 175 | |||
| 176 | const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS; | ||
| 177 | for (size_t i = 0; i < total_virtual; i++) { | ||
| 178 | compressed_physical_ptr[i] = 0; | ||
| 179 | continuity_tracker[i] = 1; | ||
| 180 | cpu_backing_address[i] = 0; | ||
| 181 | } | ||
| 182 | const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() == | ||
| 183 | Settings::MemoryLayout::Memory_4Gb | ||
| 184 | ? physical_min_bits | ||
| 185 | : physical_max_bits) - | ||
| 186 | Memory::YUZU_PAGEBITS); | ||
| 187 | for (size_t i = 0; i < total_phys; i++) { | ||
| 188 | compressed_device_addr[i] = 0; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | template <typename Traits> | ||
| 193 | DeviceMemoryManager<Traits>::~DeviceMemoryManager() = default; | ||
| 194 | |||
| 195 | template <typename Traits> | ||
| 196 | void DeviceMemoryManager<Traits>::BindInterface(DeviceInterface* device_inter_) { | ||
| 197 | device_inter = device_inter_; | ||
| 198 | } | ||
| 199 | |||
| 200 | template <typename Traits> | ||
| 201 | DAddr DeviceMemoryManager<Traits>::Allocate(size_t size) { | ||
| 202 | return impl->Allocate(size); | ||
| 203 | } | ||
| 204 | |||
| 205 | template <typename Traits> | ||
| 206 | void DeviceMemoryManager<Traits>::AllocateFixed(DAddr start, size_t size) { | ||
| 207 | return impl->AllocateFixed(start, size); | ||
| 208 | } | ||
| 209 | |||
| 210 | template <typename Traits> | ||
| 211 | void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) { | ||
| 212 | impl->Free(start, size); | ||
| 213 | } | ||
| 214 | |||
| 215 | template <typename Traits> | ||
| 216 | void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, | ||
| 217 | Asid asid, bool track) { | ||
| 218 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; | ||
| 219 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 220 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 221 | std::scoped_lock lk(mapping_guard); | ||
| 222 | for (size_t i = 0; i < num_pages; i++) { | ||
| 223 | const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE; | ||
| 224 | auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)); | ||
| 225 | if (ptr == nullptr) [[unlikely]] { | ||
| 226 | compressed_physical_ptr[start_page_d + i] = 0; | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U; | ||
| 230 | compressed_physical_ptr[start_page_d + i] = phys_addr; | ||
| 231 | InsertCPUBacking(start_page_d + i, new_vaddress, asid); | ||
| 232 | const u32 base_dev = compressed_device_addr[phys_addr - 1U]; | ||
| 233 | const u32 new_dev = static_cast<u32>(start_page_d + i); | ||
| 234 | if (base_dev == 0) [[likely]] { | ||
| 235 | compressed_device_addr[phys_addr - 1U] = new_dev; | ||
| 236 | continue; | ||
| 237 | } | ||
| 238 | u32 start_id = base_dev & MULTI_MASK; | ||
| 239 | if ((base_dev >> MULTI_FLAG_BITS) == 0) { | ||
| 240 | start_id = impl->multi_dev_address.Register(base_dev); | ||
| 241 | compressed_device_addr[phys_addr - 1U] = MULTI_FLAG | start_id; | ||
| 242 | } | ||
| 243 | impl->multi_dev_address.Register(new_dev, start_id); | ||
| 244 | } | ||
| 245 | if (track) { | ||
| 246 | TrackContinuityImpl(address, virtual_address, size, asid); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | template <typename Traits> | ||
| 251 | void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { | ||
| 252 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 253 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 254 | device_inter->InvalidateRegion(address, size); | ||
| 255 | std::scoped_lock lk(mapping_guard); | ||
| 256 | for (size_t i = 0; i < num_pages; i++) { | ||
| 257 | auto phys_addr = compressed_physical_ptr[start_page_d + i]; | ||
| 258 | compressed_physical_ptr[start_page_d + i] = 0; | ||
| 259 | cpu_backing_address[start_page_d + i] = 0; | ||
| 260 | if (phys_addr != 0) [[likely]] { | ||
| 261 | const u32 base_dev = compressed_device_addr[phys_addr - 1U]; | ||
| 262 | if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] { | ||
| 263 | compressed_device_addr[phys_addr - 1] = 0; | ||
| 264 | continue; | ||
| 265 | } | ||
| 266 | const auto [more_entries, new_start] = impl->multi_dev_address.Unregister( | ||
| 267 | static_cast<u32>(start_page_d + i), base_dev & MULTI_MASK); | ||
| 268 | if (!more_entries) { | ||
| 269 | compressed_device_addr[phys_addr - 1] = | ||
| 270 | impl->multi_dev_address.ReleaseEntry(new_start); | ||
| 271 | continue; | ||
| 272 | } | ||
| 273 | compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | } | ||
| 277 | template <typename Traits> | ||
| 278 | void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address, | ||
| 279 | size_t size, Asid asid) { | ||
| 280 | Core::Memory::Memory* process_memory = registered_processes[asid.id]; | ||
| 281 | size_t start_page_d = address >> Memory::YUZU_PAGEBITS; | ||
| 282 | size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; | ||
| 283 | uintptr_t last_ptr = 0; | ||
| 284 | size_t page_count = 1; | ||
| 285 | for (size_t i = num_pages; i > 0; i--) { | ||
| 286 | size_t index = i - 1; | ||
| 287 | const VAddr new_vaddress = virtual_address + index * Memory::YUZU_PAGESIZE; | ||
| 288 | const uintptr_t new_ptr = reinterpret_cast<uintptr_t>( | ||
| 289 | process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress))); | ||
| 290 | if (new_ptr + page_size == last_ptr) { | ||
| 291 | page_count++; | ||
| 292 | } else { | ||
| 293 | page_count = 1; | ||
| 294 | } | ||
| 295 | last_ptr = new_ptr; | ||
| 296 | continuity_tracker[start_page_d + index] = static_cast<u32>(page_count); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | template <typename Traits> | ||
| 300 | u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) { | ||
| 301 | size_t page_index = src_addr >> page_bits; | ||
| 302 | size_t subbits = src_addr & page_mask; | ||
| 303 | if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) { | ||
| 304 | return GetPointer<u8>(src_addr); | ||
| 305 | } | ||
| 306 | return nullptr; | ||
| 307 | } | ||
| 308 | |||
| 309 | template <typename Traits> | ||
| 310 | const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const { | ||
| 311 | size_t page_index = src_addr >> page_bits; | ||
| 312 | size_t subbits = src_addr & page_mask; | ||
| 313 | if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) { | ||
| 314 | return GetPointer<u8>(src_addr); | ||
| 315 | } | ||
| 316 | return nullptr; | ||
| 317 | } | ||
| 318 | |||
| 319 | template <typename Traits> | ||
| 320 | void DeviceMemoryManager<Traits>::InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, | ||
| 321 | PAddr address) { | ||
| 322 | size_t phys_addr = address >> page_bits; | ||
| 323 | std::scoped_lock lk(mapping_guard); | ||
| 324 | u32 backing = compressed_device_addr[phys_addr]; | ||
| 325 | if ((backing >> MULTI_FLAG_BITS) != 0) { | ||
| 326 | impl->multi_dev_address.GatherValues(backing & MULTI_MASK, buffer); | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | buffer.resize(1); | ||
| 330 | buffer[0] = backing; | ||
| 331 | } | ||
| 332 | |||
| 333 | template <typename Traits> | ||
| 334 | template <typename T> | ||
| 335 | T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) { | ||
| 336 | const size_t index = address >> Memory::YUZU_PAGEBITS; | ||
| 337 | const size_t offset = address & Memory::YUZU_PAGEMASK; | ||
| 338 | auto phys_addr = compressed_physical_ptr[index]; | ||
| 339 | if (phys_addr == 0) [[unlikely]] { | ||
| 340 | return nullptr; | ||
| 341 | } | ||
| 342 | return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + | ||
| 343 | offset); | ||
| 344 | } | ||
| 345 | |||
| 346 | template <typename Traits> | ||
| 347 | template <typename T> | ||
| 348 | const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const { | ||
| 349 | const size_t index = address >> Memory::YUZU_PAGEBITS; | ||
| 350 | const size_t offset = address & Memory::YUZU_PAGEMASK; | ||
| 351 | auto phys_addr = compressed_physical_ptr[index]; | ||
| 352 | if (phys_addr == 0) [[unlikely]] { | ||
| 353 | return nullptr; | ||
| 354 | } | ||
| 355 | return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + | ||
| 356 | offset); | ||
| 357 | } | ||
| 358 | |||
| 359 | template <typename Traits> | ||
| 360 | template <typename T> | ||
| 361 | void DeviceMemoryManager<Traits>::Write(DAddr address, T value) { | ||
| 362 | T* ptr = GetPointer<T>(address); | ||
| 363 | if (!ptr) [[unlikely]] { | ||
| 364 | return; | ||
| 365 | } | ||
| 366 | std::memcpy(ptr, &value, sizeof(T)); | ||
| 367 | } | ||
| 368 | |||
| 369 | template <typename Traits> | ||
| 370 | template <typename T> | ||
| 371 | T DeviceMemoryManager<Traits>::Read(DAddr address) const { | ||
| 372 | const T* ptr = GetPointer<T>(address); | ||
| 373 | T result{}; | ||
| 374 | if (!ptr) [[unlikely]] { | ||
| 375 | return result; | ||
| 376 | } | ||
| 377 | std::memcpy(&result, ptr, sizeof(T)); | ||
| 378 | return result; | ||
| 379 | } | ||
| 380 | |||
| 381 | template <typename Traits> | ||
| 382 | void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped, | ||
| 383 | auto on_memory, auto increment) { | ||
| 384 | std::size_t remaining_size = size; | ||
| 385 | std::size_t page_index = addr >> Memory::YUZU_PAGEBITS; | ||
| 386 | std::size_t page_offset = addr & Memory::YUZU_PAGEMASK; | ||
| 387 | |||
| 388 | while (remaining_size) { | ||
| 389 | const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]); | ||
| 390 | const std::size_t copy_amount = | ||
| 391 | std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size); | ||
| 392 | const auto current_vaddr = | ||
| 393 | static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset); | ||
| 394 | SCOPE_EXIT({ | ||
| 395 | page_index += next_pages; | ||
| 396 | page_offset = 0; | ||
| 397 | increment(copy_amount); | ||
| 398 | remaining_size -= copy_amount; | ||
| 399 | }); | ||
| 400 | |||
| 401 | auto phys_addr = compressed_physical_ptr[page_index]; | ||
| 402 | if (phys_addr == 0) { | ||
| 403 | on_unmapped(copy_amount, current_vaddr); | ||
| 404 | continue; | ||
| 405 | } | ||
| 406 | auto* mem_ptr = GetPointerFromRaw<u8>( | ||
| 407 | (static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset); | ||
| 408 | on_memory(copy_amount, mem_ptr); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | template <typename Traits> | ||
| 413 | void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) { | ||
| 414 | device_inter->FlushRegion(address, size); | ||
| 415 | WalkBlock( | ||
| 416 | address, size, | ||
| 417 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 418 | LOG_ERROR( | ||
| 419 | HW_Memory, | ||
| 420 | "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 421 | current_vaddr, address, size); | ||
| 422 | std::memset(dest_pointer, 0, copy_amount); | ||
| 423 | }, | ||
| 424 | [&](size_t copy_amount, const u8* const src_ptr) { | ||
| 425 | std::memcpy(dest_pointer, src_ptr, copy_amount); | ||
| 426 | }, | ||
| 427 | [&](const std::size_t copy_amount) { | ||
| 428 | dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount; | ||
| 429 | }); | ||
| 430 | } | ||
| 431 | |||
| 432 | template <typename Traits> | ||
| 433 | void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_pointer, size_t size) { | ||
| 434 | WalkBlock( | ||
| 435 | address, size, | ||
| 436 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 437 | LOG_ERROR( | ||
| 438 | HW_Memory, | ||
| 439 | "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 440 | current_vaddr, address, size); | ||
| 441 | }, | ||
| 442 | [&](size_t copy_amount, u8* const dst_ptr) { | ||
| 443 | std::memcpy(dst_ptr, src_pointer, copy_amount); | ||
| 444 | }, | ||
| 445 | [&](const std::size_t copy_amount) { | ||
| 446 | src_pointer = static_cast<const u8*>(src_pointer) + copy_amount; | ||
| 447 | }); | ||
| 448 | device_inter->InvalidateRegion(address, size); | ||
| 449 | } | ||
| 450 | |||
| 451 | template <typename Traits> | ||
| 452 | void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) { | ||
| 453 | WalkBlock( | ||
| 454 | address, size, | ||
| 455 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 456 | LOG_ERROR( | ||
| 457 | HW_Memory, | ||
| 458 | "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 459 | current_vaddr, address, size); | ||
| 460 | std::memset(dest_pointer, 0, copy_amount); | ||
| 461 | }, | ||
| 462 | [&](size_t copy_amount, const u8* const src_ptr) { | ||
| 463 | std::memcpy(dest_pointer, src_ptr, copy_amount); | ||
| 464 | }, | ||
| 465 | [&](const std::size_t copy_amount) { | ||
| 466 | dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount; | ||
| 467 | }); | ||
| 468 | } | ||
| 469 | |||
| 470 | template <typename Traits> | ||
| 471 | void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* src_pointer, | ||
| 472 | size_t size) { | ||
| 473 | WalkBlock( | ||
| 474 | address, size, | ||
| 475 | [&](size_t copy_amount, DAddr current_vaddr) { | ||
| 476 | LOG_ERROR( | ||
| 477 | HW_Memory, | ||
| 478 | "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 479 | current_vaddr, address, size); | ||
| 480 | }, | ||
| 481 | [&](size_t copy_amount, u8* const dst_ptr) { | ||
| 482 | std::memcpy(dst_ptr, src_pointer, copy_amount); | ||
| 483 | }, | ||
| 484 | [&](const std::size_t copy_amount) { | ||
| 485 | src_pointer = static_cast<const u8*>(src_pointer) + copy_amount; | ||
| 486 | }); | ||
| 487 | } | ||
| 488 | |||
| 489 | template <typename Traits> | ||
| 490 | Asid DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_device_inter) { | ||
| 491 | size_t new_id{}; | ||
| 492 | if (!id_pool.empty()) { | ||
| 493 | new_id = id_pool.front(); | ||
| 494 | id_pool.pop_front(); | ||
| 495 | registered_processes[new_id] = memory_device_inter; | ||
| 496 | } else { | ||
| 497 | registered_processes.emplace_back(memory_device_inter); | ||
| 498 | new_id = registered_processes.size() - 1U; | ||
| 499 | } | ||
| 500 | return Asid{new_id}; | ||
| 501 | } | ||
| 502 | |||
| 503 | template <typename Traits> | ||
| 504 | void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) { | ||
| 505 | registered_processes[asid.id] = nullptr; | ||
| 506 | id_pool.push_front(asid.id); | ||
| 507 | } | ||
| 508 | |||
| 509 | template <typename Traits> | ||
| 510 | void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { | ||
| 511 | std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock); | ||
| 512 | const auto Lock = [&] { | ||
| 513 | if (!lk) { | ||
| 514 | lk.lock(); | ||
| 515 | } | ||
| 516 | }; | ||
| 517 | u64 uncache_begin = 0; | ||
| 518 | u64 cache_begin = 0; | ||
| 519 | u64 uncache_bytes = 0; | ||
| 520 | u64 cache_bytes = 0; | ||
| 521 | const auto MarkRegionCaching = &DeviceMemoryManager<Traits>::DeviceMethods::MarkRegionCaching; | ||
| 522 | |||
| 523 | std::atomic_thread_fence(std::memory_order_acquire); | ||
| 524 | const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE); | ||
| 525 | size_t page = addr >> Memory::YUZU_PAGEBITS; | ||
| 526 | auto [asid, base_vaddress] = ExtractCPUBacking(page); | ||
| 527 | size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS; | ||
| 528 | auto* memory_device_inter = registered_processes[asid.id]; | ||
| 529 | for (; page != page_end; ++page) { | ||
| 530 | std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page); | ||
| 531 | |||
| 532 | if (delta > 0) { | ||
| 533 | ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(), | ||
| 534 | "Count may overflow!"); | ||
| 535 | } else if (delta < 0) { | ||
| 536 | ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); | ||
| 537 | } else { | ||
| 538 | ASSERT_MSG(false, "Delta must be non-zero!"); | ||
| 539 | } | ||
| 540 | |||
| 541 | // Adds or subtracts 1, as count is a unsigned 8-bit value | ||
| 542 | count.fetch_add(static_cast<u8>(delta), std::memory_order_release); | ||
| 543 | |||
| 544 | // Assume delta is either -1 or 1 | ||
| 545 | if (count.load(std::memory_order::relaxed) == 0) { | ||
| 546 | if (uncache_bytes == 0) { | ||
| 547 | uncache_begin = vpage; | ||
| 548 | } | ||
| 549 | uncache_bytes += Memory::YUZU_PAGESIZE; | ||
| 550 | } else if (uncache_bytes > 0) { | ||
| 551 | Lock(); | ||
| 552 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, | ||
| 553 | uncache_bytes, false); | ||
| 554 | uncache_bytes = 0; | ||
| 555 | } | ||
| 556 | if (count.load(std::memory_order::relaxed) == 1 && delta > 0) { | ||
| 557 | if (cache_bytes == 0) { | ||
| 558 | cache_begin = vpage; | ||
| 559 | } | ||
| 560 | cache_bytes += Memory::YUZU_PAGESIZE; | ||
| 561 | } else if (cache_bytes > 0) { | ||
| 562 | Lock(); | ||
| 563 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | ||
| 564 | true); | ||
| 565 | cache_bytes = 0; | ||
| 566 | } | ||
| 567 | vpage++; | ||
| 568 | } | ||
| 569 | if (uncache_bytes > 0) { | ||
| 570 | Lock(); | ||
| 571 | MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, | ||
| 572 | false); | ||
| 573 | } | ||
| 574 | if (cache_bytes > 0) { | ||
| 575 | Lock(); | ||
| 576 | MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, | ||
| 577 | true); | ||
| 578 | } | ||
| 579 | } | ||
| 580 | |||
| 581 | } // namespace Core | ||
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 4a3dbc6a3..612122224 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -466,12 +466,12 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs | |||
| 466 | return romfs; | 466 | return romfs; |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile update_raw) const { | 469 | std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const { |
| 470 | if (title_id == 0) { | 470 | if (title_id == 0) { |
| 471 | return {}; | 471 | return {}; |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | std::map<std::string, std::string, std::less<>> out; | 474 | std::vector<Patch> out; |
| 475 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 475 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 476 | 476 | ||
| 477 | // Game Updates | 477 | // Game Updates |
| @@ -482,20 +482,28 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 482 | 482 | ||
| 483 | const auto update_disabled = | 483 | const auto update_disabled = |
| 484 | std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); | 484 | std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); |
| 485 | const auto update_label = update_disabled ? "[D] Update" : "Update"; | 485 | Patch update_patch = {.enabled = !update_disabled, |
| 486 | .name = "Update", | ||
| 487 | .version = "", | ||
| 488 | .type = PatchType::Update, | ||
| 489 | .program_id = title_id, | ||
| 490 | .title_id = title_id}; | ||
| 486 | 491 | ||
| 487 | if (nacp != nullptr) { | 492 | if (nacp != nullptr) { |
| 488 | out.insert_or_assign(update_label, nacp->GetVersionString()); | 493 | update_patch.version = nacp->GetVersionString(); |
| 494 | out.push_back(update_patch); | ||
| 489 | } else { | 495 | } else { |
| 490 | if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { | 496 | if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { |
| 491 | const auto meta_ver = content_provider.GetEntryVersion(update_tid); | 497 | const auto meta_ver = content_provider.GetEntryVersion(update_tid); |
| 492 | if (meta_ver.value_or(0) == 0) { | 498 | if (meta_ver.value_or(0) == 0) { |
| 493 | out.insert_or_assign(update_label, ""); | 499 | out.push_back(update_patch); |
| 494 | } else { | 500 | } else { |
| 495 | out.insert_or_assign(update_label, FormatTitleVersion(*meta_ver)); | 501 | update_patch.version = FormatTitleVersion(*meta_ver); |
| 502 | out.push_back(update_patch); | ||
| 496 | } | 503 | } |
| 497 | } else if (update_raw != nullptr) { | 504 | } else if (update_raw != nullptr) { |
| 498 | out.insert_or_assign(update_label, "PACKED"); | 505 | update_patch.version = "PACKED"; |
| 506 | out.push_back(update_patch); | ||
| 499 | } | 507 | } |
| 500 | } | 508 | } |
| 501 | 509 | ||
| @@ -539,7 +547,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 539 | 547 | ||
| 540 | const auto mod_disabled = | 548 | const auto mod_disabled = |
| 541 | std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end(); | 549 | std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end(); |
| 542 | out.insert_or_assign(mod_disabled ? "[D] " + mod->GetName() : mod->GetName(), types); | 550 | out.push_back({.enabled = !mod_disabled, |
| 551 | .name = mod->GetName(), | ||
| 552 | .version = types, | ||
| 553 | .type = PatchType::Mod, | ||
| 554 | .program_id = title_id, | ||
| 555 | .title_id = title_id}); | ||
| 543 | } | 556 | } |
| 544 | } | 557 | } |
| 545 | 558 | ||
| @@ -557,7 +570,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 557 | if (!types.empty()) { | 570 | if (!types.empty()) { |
| 558 | const auto mod_disabled = | 571 | const auto mod_disabled = |
| 559 | std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); | 572 | std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); |
| 560 | out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", types); | 573 | out.push_back({.enabled = !mod_disabled, |
| 574 | .name = "SDMC", | ||
| 575 | .version = types, | ||
| 576 | .type = PatchType::Mod, | ||
| 577 | .program_id = title_id, | ||
| 578 | .title_id = title_id}); | ||
| 561 | } | 579 | } |
| 562 | } | 580 | } |
| 563 | 581 | ||
| @@ -584,7 +602,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u | |||
| 584 | 602 | ||
| 585 | const auto dlc_disabled = | 603 | const auto dlc_disabled = |
| 586 | std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end(); | 604 | std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end(); |
| 587 | out.insert_or_assign(dlc_disabled ? "[D] DLC" : "DLC", std::move(list)); | 605 | out.push_back({.enabled = !dlc_disabled, |
| 606 | .name = "DLC", | ||
| 607 | .version = std::move(list), | ||
| 608 | .type = PatchType::DLC, | ||
| 609 | .program_id = title_id, | ||
| 610 | .title_id = dlc_match.back().title_id}); | ||
| 588 | } | 611 | } |
| 589 | 612 | ||
| 590 | return out; | 613 | return out; |
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 03e9c7301..2601b8217 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h | |||
| @@ -26,12 +26,22 @@ class ContentProvider; | |||
| 26 | class NCA; | 26 | class NCA; |
| 27 | class NACP; | 27 | class NACP; |
| 28 | 28 | ||
| 29 | enum class PatchType { Update, DLC, Mod }; | ||
| 30 | |||
| 31 | struct Patch { | ||
| 32 | bool enabled; | ||
| 33 | std::string name; | ||
| 34 | std::string version; | ||
| 35 | PatchType type; | ||
| 36 | u64 program_id; | ||
| 37 | u64 title_id; | ||
| 38 | }; | ||
| 39 | |||
| 29 | // A centralized class to manage patches to games. | 40 | // A centralized class to manage patches to games. |
| 30 | class PatchManager { | 41 | class PatchManager { |
| 31 | public: | 42 | public: |
| 32 | using BuildID = std::array<u8, 0x20>; | 43 | using BuildID = std::array<u8, 0x20>; |
| 33 | using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; | 44 | using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; |
| 34 | using PatchVersionNames = std::map<std::string, std::string, std::less<>>; | ||
| 35 | 45 | ||
| 36 | explicit PatchManager(u64 title_id_, | 46 | explicit PatchManager(u64 title_id_, |
| 37 | const Service::FileSystem::FileSystemController& fs_controller_, | 47 | const Service::FileSystem::FileSystemController& fs_controller_, |
| @@ -66,9 +76,8 @@ public: | |||
| 66 | VirtualFile packed_update_raw = nullptr, | 76 | VirtualFile packed_update_raw = nullptr, |
| 67 | bool apply_layeredfs = true) const; | 77 | bool apply_layeredfs = true) const; |
| 68 | 78 | ||
| 69 | // Returns a vector of pairs between patch names and patch versions. | 79 | // Returns a vector of patches |
| 70 | // i.e. Update 3.2.2 will return {"Update", "3.2.2"} | 80 | [[nodiscard]] std::vector<Patch> GetPatches(VirtualFile update_raw = nullptr) const; |
| 71 | [[nodiscard]] PatchVersionNames GetPatchVersionNames(VirtualFile update_raw = nullptr) const; | ||
| 72 | 81 | ||
| 73 | // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, | 82 | // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, |
| 74 | // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be | 83 | // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be |
diff --git a/src/core/gpu_dirty_memory_manager.h b/src/core/gpu_dirty_memory_manager.h index 9687531e8..cc8fc176f 100644 --- a/src/core/gpu_dirty_memory_manager.h +++ b/src/core/gpu_dirty_memory_manager.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | #include "core/memory.h" | 13 | #include "core/device_memory_manager.h" |
| 14 | 14 | ||
| 15 | namespace Core { | 15 | namespace Core { |
| 16 | 16 | ||
| @@ -23,7 +23,7 @@ public: | |||
| 23 | 23 | ||
| 24 | ~GPUDirtyMemoryManager() = default; | 24 | ~GPUDirtyMemoryManager() = default; |
| 25 | 25 | ||
| 26 | void Collect(VAddr address, size_t size) { | 26 | void Collect(PAddr address, size_t size) { |
| 27 | TransformAddress t = BuildTransform(address, size); | 27 | TransformAddress t = BuildTransform(address, size); |
| 28 | TransformAddress tmp, original; | 28 | TransformAddress tmp, original; |
| 29 | do { | 29 | do { |
| @@ -47,7 +47,7 @@ public: | |||
| 47 | std::memory_order_relaxed)); | 47 | std::memory_order_relaxed)); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | void Gather(std::function<void(VAddr, size_t)>& callback) { | 50 | void Gather(std::function<void(PAddr, size_t)>& callback) { |
| 51 | { | 51 | { |
| 52 | std::scoped_lock lk(guard); | 52 | std::scoped_lock lk(guard); |
| 53 | TransformAddress t = current.exchange(default_transform, std::memory_order_relaxed); | 53 | TransformAddress t = current.exchange(default_transform, std::memory_order_relaxed); |
| @@ -65,7 +65,7 @@ public: | |||
| 65 | mask = mask >> empty_bits; | 65 | mask = mask >> empty_bits; |
| 66 | 66 | ||
| 67 | const size_t continuous_bits = std::countr_one(mask); | 67 | const size_t continuous_bits = std::countr_one(mask); |
| 68 | callback((static_cast<VAddr>(transform.address) << page_bits) + offset, | 68 | callback((static_cast<PAddr>(transform.address) << page_bits) + offset, |
| 69 | continuous_bits << align_bits); | 69 | continuous_bits << align_bits); |
| 70 | mask = continuous_bits < align_size ? (mask >> continuous_bits) : 0; | 70 | mask = continuous_bits < align_size ? (mask >> continuous_bits) : 0; |
| 71 | offset += continuous_bits << align_bits; | 71 | offset += continuous_bits << align_bits; |
| @@ -80,7 +80,7 @@ private: | |||
| 80 | u32 mask; | 80 | u32 mask; |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | constexpr static size_t page_bits = Memory::YUZU_PAGEBITS - 1; | 83 | constexpr static size_t page_bits = DEVICE_PAGEBITS - 1; |
| 84 | constexpr static size_t page_size = 1ULL << page_bits; | 84 | constexpr static size_t page_size = 1ULL << page_bits; |
| 85 | constexpr static size_t page_mask = page_size - 1; | 85 | constexpr static size_t page_mask = page_size - 1; |
| 86 | 86 | ||
| @@ -89,7 +89,7 @@ private: | |||
| 89 | constexpr static size_t align_mask = align_size - 1; | 89 | constexpr static size_t align_mask = align_size - 1; |
| 90 | constexpr static TransformAddress default_transform = {.address = ~0U, .mask = 0U}; | 90 | constexpr static TransformAddress default_transform = {.address = ~0U, .mask = 0U}; |
| 91 | 91 | ||
| 92 | bool IsValid(VAddr address) { | 92 | bool IsValid(PAddr address) { |
| 93 | return address < (1ULL << 39); | 93 | return address < (1ULL << 39); |
| 94 | } | 94 | } |
| 95 | 95 | ||
| @@ -103,7 +103,7 @@ private: | |||
| 103 | return mask; | 103 | return mask; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | TransformAddress BuildTransform(VAddr address, size_t size) { | 106 | TransformAddress BuildTransform(PAddr address, size_t size) { |
| 107 | const size_t minor_address = address & page_mask; | 107 | const size_t minor_address = address & page_mask; |
| 108 | const size_t minor_bit = minor_address >> align_bits; | 108 | const size_t minor_bit = minor_address >> align_bits; |
| 109 | const size_t top_bit = (minor_address + size + align_mask) >> align_bits; | 109 | const size_t top_bit = (minor_address + size + align_mask) >> align_bits; |
diff --git a/src/core/guest_memory.h b/src/core/guest_memory.h new file mode 100644 index 000000000..7ee18c126 --- /dev/null +++ b/src/core/guest_memory.h | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <iterator> | ||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | #include <span> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/scratch_buffer.h" | ||
| 14 | |||
| 15 | namespace Core::Memory { | ||
| 16 | |||
| 17 | enum GuestMemoryFlags : u32 { | ||
| 18 | Read = 1 << 0, | ||
| 19 | Write = 1 << 1, | ||
| 20 | Safe = 1 << 2, | ||
| 21 | Cached = 1 << 3, | ||
| 22 | |||
| 23 | SafeRead = Read | Safe, | ||
| 24 | SafeWrite = Write | Safe, | ||
| 25 | SafeReadWrite = SafeRead | SafeWrite, | ||
| 26 | SafeReadCachedWrite = SafeReadWrite | Cached, | ||
| 27 | |||
| 28 | UnsafeRead = Read, | ||
| 29 | UnsafeWrite = Write, | ||
| 30 | UnsafeReadWrite = UnsafeRead | UnsafeWrite, | ||
| 31 | UnsafeReadCachedWrite = UnsafeReadWrite | Cached, | ||
| 32 | }; | ||
| 33 | |||
| 34 | namespace { | ||
| 35 | template <typename M, typename T, GuestMemoryFlags FLAGS> | ||
| 36 | class GuestMemory { | ||
| 37 | using iterator = T*; | ||
| 38 | using const_iterator = const T*; | ||
| 39 | using value_type = T; | ||
| 40 | using element_type = T; | ||
| 41 | using iterator_category = std::contiguous_iterator_tag; | ||
| 42 | |||
| 43 | public: | ||
| 44 | GuestMemory() = delete; | ||
| 45 | explicit GuestMemory(M& memory, u64 addr, std::size_t size, | ||
| 46 | Common::ScratchBuffer<T>* backup = nullptr) | ||
| 47 | : m_memory{memory}, m_addr{addr}, m_size{size} { | ||
| 48 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); | ||
| 49 | if constexpr (FLAGS & GuestMemoryFlags::Read) { | ||
| 50 | Read(addr, size, backup); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | ~GuestMemory() = default; | ||
| 55 | |||
| 56 | T* data() noexcept { | ||
| 57 | return m_data_span.data(); | ||
| 58 | } | ||
| 59 | |||
| 60 | const T* data() const noexcept { | ||
| 61 | return m_data_span.data(); | ||
| 62 | } | ||
| 63 | |||
| 64 | size_t size() const noexcept { | ||
| 65 | return m_size; | ||
| 66 | } | ||
| 67 | |||
| 68 | size_t size_bytes() const noexcept { | ||
| 69 | return this->size() * sizeof(T); | ||
| 70 | } | ||
| 71 | |||
| 72 | [[nodiscard]] T* begin() noexcept { | ||
| 73 | return this->data(); | ||
| 74 | } | ||
| 75 | |||
| 76 | [[nodiscard]] const T* begin() const noexcept { | ||
| 77 | return this->data(); | ||
| 78 | } | ||
| 79 | |||
| 80 | [[nodiscard]] T* end() noexcept { | ||
| 81 | return this->data() + this->size(); | ||
| 82 | } | ||
| 83 | |||
| 84 | [[nodiscard]] const T* end() const noexcept { | ||
| 85 | return this->data() + this->size(); | ||
| 86 | } | ||
| 87 | |||
| 88 | T& operator[](size_t index) noexcept { | ||
| 89 | return m_data_span[index]; | ||
| 90 | } | ||
| 91 | |||
| 92 | const T& operator[](size_t index) const noexcept { | ||
| 93 | return m_data_span[index]; | ||
| 94 | } | ||
| 95 | |||
| 96 | void SetAddressAndSize(u64 addr, std::size_t size) noexcept { | ||
| 97 | m_addr = addr; | ||
| 98 | m_size = size; | ||
| 99 | m_addr_changed = true; | ||
| 100 | } | ||
| 101 | |||
| 102 | std::span<T> Read(u64 addr, std::size_t size, | ||
| 103 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { | ||
| 104 | m_addr = addr; | ||
| 105 | m_size = size; | ||
| 106 | if (m_size == 0) { | ||
| 107 | m_is_data_copy = true; | ||
| 108 | return {}; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (this->TrySetSpan()) { | ||
| 112 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 113 | m_memory.FlushRegion(m_addr, this->size_bytes()); | ||
| 114 | } | ||
| 115 | } else { | ||
| 116 | if (backup) { | ||
| 117 | backup->resize_destructive(this->size()); | ||
| 118 | m_data_span = *backup; | ||
| 119 | } else { | ||
| 120 | m_data_copy.resize(this->size()); | ||
| 121 | m_data_span = std::span(m_data_copy); | ||
| 122 | } | ||
| 123 | m_is_data_copy = true; | ||
| 124 | m_span_valid = true; | ||
| 125 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 126 | m_memory.ReadBlock(m_addr, this->data(), this->size_bytes()); | ||
| 127 | } else { | ||
| 128 | m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes()); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | return m_data_span; | ||
| 132 | } | ||
| 133 | |||
| 134 | void Write(std::span<T> write_data) noexcept { | ||
| 135 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | ||
| 136 | m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes()); | ||
| 137 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 138 | m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes()); | ||
| 139 | } else { | ||
| 140 | m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes()); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | bool TrySetSpan() noexcept { | ||
| 145 | if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) { | ||
| 146 | m_data_span = {reinterpret_cast<T*>(ptr), this->size()}; | ||
| 147 | m_span_valid = true; | ||
| 148 | return true; | ||
| 149 | } | ||
| 150 | return false; | ||
| 151 | } | ||
| 152 | |||
| 153 | protected: | ||
| 154 | bool IsDataCopy() const noexcept { | ||
| 155 | return m_is_data_copy; | ||
| 156 | } | ||
| 157 | |||
| 158 | bool AddressChanged() const noexcept { | ||
| 159 | return m_addr_changed; | ||
| 160 | } | ||
| 161 | |||
| 162 | M& m_memory; | ||
| 163 | u64 m_addr{}; | ||
| 164 | size_t m_size{}; | ||
| 165 | std::span<T> m_data_span{}; | ||
| 166 | std::vector<T> m_data_copy{}; | ||
| 167 | bool m_span_valid{false}; | ||
| 168 | bool m_is_data_copy{false}; | ||
| 169 | bool m_addr_changed{false}; | ||
| 170 | }; | ||
| 171 | |||
| 172 | template <typename M, typename T, GuestMemoryFlags FLAGS> | ||
| 173 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { | ||
| 174 | public: | ||
| 175 | GuestMemoryScoped() = delete; | ||
| 176 | explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size, | ||
| 177 | Common::ScratchBuffer<T>* backup = nullptr) | ||
| 178 | : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) { | ||
| 179 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { | ||
| 180 | if (!this->TrySetSpan()) { | ||
| 181 | if (backup) { | ||
| 182 | this->m_data_span = *backup; | ||
| 183 | this->m_span_valid = true; | ||
| 184 | this->m_is_data_copy = true; | ||
| 185 | } | ||
| 186 | } | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | ~GuestMemoryScoped() { | ||
| 191 | if constexpr (FLAGS & GuestMemoryFlags::Write) { | ||
| 192 | if (this->size() == 0) [[unlikely]] { | ||
| 193 | return; | ||
| 194 | } | ||
| 195 | |||
| 196 | if (this->AddressChanged() || this->IsDataCopy()) { | ||
| 197 | ASSERT(this->m_span_valid); | ||
| 198 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | ||
| 199 | this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes()); | ||
| 200 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 201 | this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes()); | ||
| 202 | } else { | ||
| 203 | this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes()); | ||
| 204 | } | ||
| 205 | } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) || | ||
| 206 | (FLAGS & GuestMemoryFlags::Cached)) { | ||
| 207 | this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes()); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | } | ||
| 211 | }; | ||
| 212 | } // namespace | ||
| 213 | |||
| 214 | } // namespace Core::Memory | ||
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 53735a225..0b08e877e 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/scope_exit.h" | 5 | #include "common/scope_exit.h" |
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/gpu_dirty_memory_manager.h" | ||
| 8 | #include "core/hle/kernel/k_process.h" | 9 | #include "core/hle/kernel/k_process.h" |
| 9 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 10 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 10 | #include "core/hle/kernel/k_shared_memory.h" | 11 | #include "core/hle/kernel/k_shared_memory.h" |
| @@ -320,7 +321,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa | |||
| 320 | 321 | ||
| 321 | // Ensure our memory is initialized. | 322 | // Ensure our memory is initialized. |
| 322 | m_memory.SetCurrentPageTable(*this); | 323 | m_memory.SetCurrentPageTable(*this); |
| 323 | m_memory.SetGPUDirtyManagers(m_dirty_memory_managers); | 324 | m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); |
| 324 | 325 | ||
| 325 | // Ensure we can insert the code region. | 326 | // Ensure we can insert the code region. |
| 326 | R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, | 327 | R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, |
| @@ -417,7 +418,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, | |||
| 417 | 418 | ||
| 418 | // Ensure our memory is initialized. | 419 | // Ensure our memory is initialized. |
| 419 | m_memory.SetCurrentPageTable(*this); | 420 | m_memory.SetCurrentPageTable(*this); |
| 420 | m_memory.SetGPUDirtyManagers(m_dirty_memory_managers); | 421 | m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); |
| 421 | 422 | ||
| 422 | // Ensure we can insert the code region. | 423 | // Ensure we can insert the code region. |
| 423 | R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), | 424 | R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), |
| @@ -1141,8 +1142,7 @@ void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} | |||
| 1141 | KProcess::KProcess(KernelCore& kernel) | 1142 | KProcess::KProcess(KernelCore& kernel) |
| 1142 | : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel}, | 1143 | : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel}, |
| 1143 | m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()}, | 1144 | m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()}, |
| 1144 | m_handle_table{kernel}, m_dirty_memory_managers{}, | 1145 | m_handle_table{kernel}, m_exclusive_monitor{}, m_memory{kernel.System()} {} |
| 1145 | m_exclusive_monitor{}, m_memory{kernel.System()} {} | ||
| 1146 | KProcess::~KProcess() = default; | 1146 | KProcess::~KProcess() = default; |
| 1147 | 1147 | ||
| 1148 | Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, | 1148 | Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, |
| @@ -1324,10 +1324,4 @@ bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT | |||
| 1324 | return true; | 1324 | return true; |
| 1325 | } | 1325 | } |
| 1326 | 1326 | ||
| 1327 | void KProcess::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) { | ||
| 1328 | for (auto& manager : m_dirty_memory_managers) { | ||
| 1329 | manager.Gather(callback); | ||
| 1330 | } | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | } // namespace Kernel | 1327 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 53c0e3316..ab1358a12 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | 7 | ||
| 8 | #include "core/arm/arm_interface.h" | 8 | #include "core/arm/arm_interface.h" |
| 9 | #include "core/file_sys/program_metadata.h" | 9 | #include "core/file_sys/program_metadata.h" |
| 10 | #include "core/gpu_dirty_memory_manager.h" | ||
| 11 | #include "core/hle/kernel/code_set.h" | 10 | #include "core/hle/kernel/code_set.h" |
| 12 | #include "core/hle/kernel/k_address_arbiter.h" | 11 | #include "core/hle/kernel/k_address_arbiter.h" |
| 13 | #include "core/hle/kernel/k_capabilities.h" | 12 | #include "core/hle/kernel/k_capabilities.h" |
| @@ -128,7 +127,6 @@ private: | |||
| 128 | #ifdef HAS_NCE | 127 | #ifdef HAS_NCE |
| 129 | std::unordered_map<u64, u64> m_post_handlers{}; | 128 | std::unordered_map<u64, u64> m_post_handlers{}; |
| 130 | #endif | 129 | #endif |
| 131 | std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> m_dirty_memory_managers; | ||
| 132 | std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor; | 130 | std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor; |
| 133 | Core::Memory::Memory m_memory; | 131 | Core::Memory::Memory m_memory; |
| 134 | 132 | ||
| @@ -511,8 +509,6 @@ public: | |||
| 511 | return m_memory; | 509 | return m_memory; |
| 512 | } | 510 | } |
| 513 | 511 | ||
| 514 | void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback); | ||
| 515 | |||
| 516 | Core::ExclusiveMonitor& GetExclusiveMonitor() const { | 512 | Core::ExclusiveMonitor& GetExclusiveMonitor() const { |
| 517 | return *m_exclusive_monitor; | 513 | return *m_exclusive_monitor; |
| 518 | } | 514 | } |
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 683f44e27..29a10ad13 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "common/fs/path_util.h" | 11 | #include "common/fs/path_util.h" |
| 12 | #include "common/polyfill_ranges.h" | 12 | #include "common/polyfill_ranges.h" |
| 13 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 14 | #include "common/string_util.h" | ||
| 14 | #include "core/hle/service/acc/profile_manager.h" | 15 | #include "core/hle/service/acc/profile_manager.h" |
| 15 | 16 | ||
| 16 | namespace Service::Account { | 17 | namespace Service::Account { |
| @@ -164,6 +165,22 @@ std::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user) | |||
| 164 | return GetUserIndex(user.user_uuid); | 165 | return GetUserIndex(user.user_uuid); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 168 | /// Returns the first user profile seen based on username (which does not enforce uniqueness) | ||
| 169 | std::optional<std::size_t> ProfileManager::GetUserIndex(const std::string& username) const { | ||
| 170 | const auto iter = | ||
| 171 | std::find_if(profiles.begin(), profiles.end(), [&username](const ProfileInfo& p) { | ||
| 172 | const std::string profile_username = Common::StringFromFixedZeroTerminatedBuffer( | ||
| 173 | reinterpret_cast<const char*>(p.username.data()), p.username.size()); | ||
| 174 | |||
| 175 | return username.compare(profile_username) == 0; | ||
| 176 | }); | ||
| 177 | if (iter == profiles.end()) { | ||
| 178 | return std::nullopt; | ||
| 179 | } | ||
| 180 | |||
| 181 | return static_cast<std::size_t>(std::distance(profiles.begin(), iter)); | ||
| 182 | } | ||
| 183 | |||
| 167 | /// Returns the data structure used by the switch when GetProfileBase is called on acc:* | 184 | /// Returns the data structure used by the switch when GetProfileBase is called on acc:* |
| 168 | bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const { | 185 | bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const { |
| 169 | if (!index || index >= MAX_USERS) { | 186 | if (!index || index >= MAX_USERS) { |
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h index e21863e64..f94157300 100644 --- a/src/core/hle/service/acc/profile_manager.h +++ b/src/core/hle/service/acc/profile_manager.h | |||
| @@ -70,6 +70,7 @@ public: | |||
| 70 | std::optional<Common::UUID> GetUser(std::size_t index) const; | 70 | std::optional<Common::UUID> GetUser(std::size_t index) const; |
| 71 | std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const; | 71 | std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const; |
| 72 | std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; | 72 | std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; |
| 73 | std::optional<std::size_t> GetUserIndex(const std::string& username) const; | ||
| 73 | bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const; | 74 | bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const; |
| 74 | bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const; | 75 | bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const; |
| 75 | bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const; | 76 | bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 03ebdc137..595a3372e 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -26,6 +26,7 @@ void LoopProcess(Core::System& system) { | |||
| 26 | resource_manager->Initialize(); | 26 | resource_manager->Initialize(); |
| 27 | resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), | 27 | resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), |
| 28 | true); | 28 | true); |
| 29 | resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true); | ||
| 29 | 30 | ||
| 30 | server_manager->RegisterNamedService( | 31 | server_manager->RegisterNamedService( |
| 31 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); | 32 | "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 1951da33b..30afed812 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -22,12 +22,16 @@ | |||
| 22 | #include "hid_core/resources/mouse/mouse.h" | 22 | #include "hid_core/resources/mouse/mouse.h" |
| 23 | #include "hid_core/resources/npad/npad.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 24 | #include "hid_core/resources/npad/npad_types.h" | 24 | #include "hid_core/resources/npad/npad_types.h" |
| 25 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 25 | #include "hid_core/resources/palma/palma.h" | 26 | #include "hid_core/resources/palma/palma.h" |
| 26 | #include "hid_core/resources/six_axis/console_six_axis.h" | 27 | #include "hid_core/resources/six_axis/console_six_axis.h" |
| 27 | #include "hid_core/resources/six_axis/seven_six_axis.h" | 28 | #include "hid_core/resources/six_axis/seven_six_axis.h" |
| 28 | #include "hid_core/resources/six_axis/six_axis.h" | 29 | #include "hid_core/resources/six_axis/six_axis.h" |
| 29 | #include "hid_core/resources/touch_screen/gesture.h" | 30 | #include "hid_core/resources/touch_screen/gesture.h" |
| 30 | #include "hid_core/resources/touch_screen/touch_screen.h" | 31 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 32 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 33 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 34 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 31 | 35 | ||
| 32 | namespace Service::HID { | 36 | namespace Service::HID { |
| 33 | 37 | ||
| @@ -38,7 +42,7 @@ public: | |||
| 38 | : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { | 42 | : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { |
| 39 | // clang-format off | 43 | // clang-format off |
| 40 | static const FunctionInfo functions[] = { | 44 | static const FunctionInfo functions[] = { |
| 41 | {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, | 45 | {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"}, |
| 42 | }; | 46 | }; |
| 43 | // clang-format on | 47 | // clang-format on |
| 44 | 48 | ||
| @@ -46,22 +50,49 @@ public: | |||
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | private: | 52 | private: |
| 49 | void InitializeVibrationDevice(HLERequestContext& ctx) { | 53 | void ActivateVibrationDevice(HLERequestContext& ctx) { |
| 50 | IPC::RequestParser rp{ctx}; | 54 | IPC::RequestParser rp{ctx}; |
| 51 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; | 55 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; |
| 52 | 56 | ||
| 53 | if (resource_manager != nullptr && resource_manager->GetNpad()) { | ||
| 54 | resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle); | ||
| 55 | } | ||
| 56 | |||
| 57 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", | 57 | LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", |
| 58 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, | 58 | vibration_device_handle.npad_type, vibration_device_handle.npad_id, |
| 59 | vibration_device_handle.device_index); | 59 | vibration_device_handle.device_index); |
| 60 | 60 | ||
| 61 | const auto result = ActivateVibrationDeviceImpl(vibration_device_handle); | ||
| 62 | |||
| 61 | IPC::ResponseBuilder rb{ctx, 2}; | 63 | IPC::ResponseBuilder rb{ctx, 2}; |
| 62 | rb.Push(ResultSuccess); | 64 | rb.Push(result); |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 67 | Result ActivateVibrationDeviceImpl(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 68 | std::scoped_lock lock{mutex}; | ||
| 69 | |||
| 70 | const Result is_valid = IsVibrationHandleValid(handle); | ||
| 71 | if (is_valid.IsError()) { | ||
| 72 | return is_valid; | ||
| 73 | } | ||
| 74 | |||
| 75 | for (std::size_t i = 0; i < list_size; i++) { | ||
| 76 | if (handle.device_index == vibration_device_list[i].device_index && | ||
| 77 | handle.npad_id == vibration_device_list[i].npad_id && | ||
| 78 | handle.npad_type == vibration_device_list[i].npad_type) { | ||
| 79 | return ResultSuccess; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | if (list_size == vibration_device_list.size()) { | ||
| 83 | return ResultVibrationDeviceIndexOutOfRange; | ||
| 84 | } | ||
| 85 | const Result result = resource_manager->GetVibrationDevice(handle)->Activate(); | ||
| 86 | if (result.IsError()) { | ||
| 87 | return result; | ||
| 88 | } | ||
| 89 | vibration_device_list[list_size++] = handle; | ||
| 90 | return ResultSuccess; | ||
| 91 | } | ||
| 92 | |||
| 93 | mutable std::mutex mutex; | ||
| 94 | std::size_t list_size{}; | ||
| 95 | std::array<Core::HID::VibrationDeviceHandle, 0x100> vibration_device_list{}; | ||
| 65 | std::shared_ptr<ResourceManager> resource_manager; | 96 | std::shared_ptr<ResourceManager> resource_manager; |
| 66 | }; | 97 | }; |
| 67 | 98 | ||
| @@ -153,7 +184,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r | |||
| 153 | {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, | 184 | {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 154 | {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, | 185 | {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 155 | {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, | 186 | {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, |
| 156 | {212, nullptr, "SendVibrationValueInBool"}, | 187 | {212, &IHidServer::SendVibrationValueInBool, "SendVibrationValueInBool"}, |
| 157 | {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 188 | {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 158 | {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 189 | {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 159 | {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, | 190 | {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| @@ -1492,59 +1523,13 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) { | |||
| 1492 | void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { | 1523 | void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { |
| 1493 | IPC::RequestParser rp{ctx}; | 1524 | IPC::RequestParser rp{ctx}; |
| 1494 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; | 1525 | const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; |
| 1495 | const auto controller = GetResourceManager()->GetNpad(); | ||
| 1496 | |||
| 1497 | Core::HID::VibrationDeviceInfo vibration_device_info; | ||
| 1498 | bool check_device_index = false; | ||
| 1499 | |||
| 1500 | switch (vibration_device_handle.npad_type) { | ||
| 1501 | case Core::HID::NpadStyleIndex::Fullkey: | ||
| 1502 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 1503 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 1504 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 1505 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 1506 | vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; | ||
| 1507 | check_device_index = true; | ||
| 1508 | break; | ||
| 1509 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 1510 | vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm; | ||
| 1511 | break; | ||
| 1512 | case Core::HID::NpadStyleIndex::N64: | ||
| 1513 | vibration_device_info.type = Core::HID::VibrationDeviceType::N64; | ||
| 1514 | break; | ||
| 1515 | default: | ||
| 1516 | vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown; | ||
| 1517 | break; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | vibration_device_info.position = Core::HID::VibrationDevicePosition::None; | ||
| 1521 | if (check_device_index) { | ||
| 1522 | switch (vibration_device_handle.device_index) { | ||
| 1523 | case Core::HID::DeviceIndex::Left: | ||
| 1524 | vibration_device_info.position = Core::HID::VibrationDevicePosition::Left; | ||
| 1525 | break; | ||
| 1526 | case Core::HID::DeviceIndex::Right: | ||
| 1527 | vibration_device_info.position = Core::HID::VibrationDevicePosition::Right; | ||
| 1528 | break; | ||
| 1529 | case Core::HID::DeviceIndex::None: | ||
| 1530 | default: | ||
| 1531 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 1532 | break; | ||
| 1533 | } | ||
| 1534 | } | ||
| 1535 | 1526 | ||
| 1536 | LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", | 1527 | Core::HID::VibrationDeviceInfo vibration_device_info{}; |
| 1537 | vibration_device_info.type, vibration_device_info.position); | 1528 | const auto result = GetResourceManager()->GetVibrationDeviceInfo(vibration_device_info, |
| 1538 | 1529 | vibration_device_handle); | |
| 1539 | const auto result = IsVibrationHandleValid(vibration_device_handle); | ||
| 1540 | if (result.IsError()) { | ||
| 1541 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1542 | rb.Push(result); | ||
| 1543 | return; | ||
| 1544 | } | ||
| 1545 | 1530 | ||
| 1546 | IPC::ResponseBuilder rb{ctx, 4}; | 1531 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1547 | rb.Push(ResultSuccess); | 1532 | rb.Push(result); |
| 1548 | rb.PushRaw(vibration_device_info); | 1533 | rb.PushRaw(vibration_device_info); |
| 1549 | } | 1534 | } |
| 1550 | 1535 | ||
| @@ -1560,16 +1545,16 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) { | |||
| 1560 | 1545 | ||
| 1561 | const auto parameters{rp.PopRaw<Parameters>()}; | 1546 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1562 | 1547 | ||
| 1563 | GetResourceManager()->GetNpad()->VibrateController(parameters.applet_resource_user_id, | ||
| 1564 | parameters.vibration_device_handle, | ||
| 1565 | parameters.vibration_value); | ||
| 1566 | |||
| 1567 | LOG_DEBUG(Service_HID, | 1548 | LOG_DEBUG(Service_HID, |
| 1568 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1549 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 1569 | parameters.vibration_device_handle.npad_type, | 1550 | parameters.vibration_device_handle.npad_type, |
| 1570 | parameters.vibration_device_handle.npad_id, | 1551 | parameters.vibration_device_handle.npad_id, |
| 1571 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1552 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1572 | 1553 | ||
| 1554 | GetResourceManager()->SendVibrationValue(parameters.applet_resource_user_id, | ||
| 1555 | parameters.vibration_device_handle, | ||
| 1556 | parameters.vibration_value); | ||
| 1557 | |||
| 1573 | IPC::ResponseBuilder rb{ctx, 2}; | 1558 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1574 | rb.Push(ResultSuccess); | 1559 | rb.Push(ResultSuccess); |
| 1575 | } | 1560 | } |
| @@ -1591,10 +1576,28 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) { | |||
| 1591 | parameters.vibration_device_handle.npad_id, | 1576 | parameters.vibration_device_handle.npad_id, |
| 1592 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1577 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1593 | 1578 | ||
| 1579 | bool has_active_aruid{}; | ||
| 1580 | NpadVibrationDevice* device{nullptr}; | ||
| 1581 | Core::HID::VibrationValue vibration_value{}; | ||
| 1582 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1583 | has_active_aruid); | ||
| 1584 | |||
| 1585 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1586 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1587 | } | ||
| 1588 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1589 | device = GetResourceManager()->GetNSVibrationDevice(parameters.vibration_device_handle); | ||
| 1590 | } | ||
| 1591 | if (device != nullptr) { | ||
| 1592 | result = device->GetActualVibrationValue(vibration_value); | ||
| 1593 | } | ||
| 1594 | if (result.IsError()) { | ||
| 1595 | vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 1596 | } | ||
| 1597 | |||
| 1594 | IPC::ResponseBuilder rb{ctx, 6}; | 1598 | IPC::ResponseBuilder rb{ctx, 6}; |
| 1595 | rb.Push(ResultSuccess); | 1599 | rb.Push(ResultSuccess); |
| 1596 | rb.PushRaw(GetResourceManager()->GetNpad()->GetLastVibration( | 1600 | rb.PushRaw(vibration_value); |
| 1597 | parameters.applet_resource_user_id, parameters.vibration_device_handle)); | ||
| 1598 | } | 1601 | } |
| 1599 | 1602 | ||
| 1600 | void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { | 1603 | void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { |
| @@ -1609,25 +1612,27 @@ void IHidServer::PermitVibration(HLERequestContext& ctx) { | |||
| 1609 | IPC::RequestParser rp{ctx}; | 1612 | IPC::RequestParser rp{ctx}; |
| 1610 | const auto can_vibrate{rp.Pop<bool>()}; | 1613 | const auto can_vibrate{rp.Pop<bool>()}; |
| 1611 | 1614 | ||
| 1612 | // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value | ||
| 1613 | // by converting it to a bool | ||
| 1614 | Settings::values.vibration_enabled.SetValue(can_vibrate); | ||
| 1615 | |||
| 1616 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); | 1615 | LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); |
| 1617 | 1616 | ||
| 1617 | const auto result = | ||
| 1618 | GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( | ||
| 1619 | can_vibrate ? 1.0f : 0.0f); | ||
| 1620 | |||
| 1618 | IPC::ResponseBuilder rb{ctx, 2}; | 1621 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1619 | rb.Push(ResultSuccess); | 1622 | rb.Push(result); |
| 1620 | } | 1623 | } |
| 1621 | 1624 | ||
| 1622 | void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { | 1625 | void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { |
| 1623 | LOG_DEBUG(Service_HID, "called"); | 1626 | LOG_DEBUG(Service_HID, "called"); |
| 1624 | 1627 | ||
| 1625 | // nnSDK checks if a float is greater than zero. We return the bool we stored earlier | 1628 | f32 master_volume{}; |
| 1626 | const auto is_enabled = Settings::values.vibration_enabled.GetValue(); | 1629 | const auto result = |
| 1630 | GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( | ||
| 1631 | master_volume); | ||
| 1627 | 1632 | ||
| 1628 | IPC::ResponseBuilder rb{ctx, 3}; | 1633 | IPC::ResponseBuilder rb{ctx, 3}; |
| 1629 | rb.Push(ResultSuccess); | 1634 | rb.Push(result); |
| 1630 | rb.Push(is_enabled); | 1635 | rb.Push(master_volume > 0.0f); |
| 1631 | } | 1636 | } |
| 1632 | 1637 | ||
| 1633 | void IHidServer::SendVibrationValues(HLERequestContext& ctx) { | 1638 | void IHidServer::SendVibrationValues(HLERequestContext& ctx) { |
| @@ -1645,13 +1650,22 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) { | |||
| 1645 | auto vibration_values = std::span( | 1650 | auto vibration_values = std::span( |
| 1646 | reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); | 1651 | reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); |
| 1647 | 1652 | ||
| 1648 | GetResourceManager()->GetNpad()->VibrateControllers(applet_resource_user_id, | ||
| 1649 | vibration_device_handles, vibration_values); | ||
| 1650 | |||
| 1651 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1653 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1652 | 1654 | ||
| 1655 | Result result = ResultSuccess; | ||
| 1656 | if (handle_count != vibration_count) { | ||
| 1657 | result = ResultVibrationArraySizeMismatch; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | for (std::size_t i = 0; i < handle_count; i++) { | ||
| 1661 | if (result.IsSuccess()) { | ||
| 1662 | result = GetResourceManager()->SendVibrationValue( | ||
| 1663 | applet_resource_user_id, vibration_device_handles[i], vibration_values[i]); | ||
| 1664 | } | ||
| 1665 | } | ||
| 1666 | |||
| 1653 | IPC::ResponseBuilder rb{ctx, 2}; | 1667 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1654 | rb.Push(ResultSuccess); | 1668 | rb.Push(result); |
| 1655 | } | 1669 | } |
| 1656 | 1670 | ||
| 1657 | void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | 1671 | void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { |
| @@ -1666,43 +1680,6 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1666 | 1680 | ||
| 1667 | const auto parameters{rp.PopRaw<Parameters>()}; | 1681 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1668 | 1682 | ||
| 1669 | /** | ||
| 1670 | * Note: This uses yuzu-specific behavior such that the StopHard command produces | ||
| 1671 | * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below, | ||
| 1672 | * in order to differentiate between Stop and StopHard commands. | ||
| 1673 | * This is done to reuse the controller vibration functions made for regular controllers. | ||
| 1674 | */ | ||
| 1675 | const auto vibration_value = [parameters] { | ||
| 1676 | switch (parameters.gc_erm_command) { | ||
| 1677 | case Core::HID::VibrationGcErmCommand::Stop: | ||
| 1678 | return Core::HID::VibrationValue{ | ||
| 1679 | .low_amplitude = 0.0f, | ||
| 1680 | .low_frequency = 160.0f, | ||
| 1681 | .high_amplitude = 0.0f, | ||
| 1682 | .high_frequency = 320.0f, | ||
| 1683 | }; | ||
| 1684 | case Core::HID::VibrationGcErmCommand::Start: | ||
| 1685 | return Core::HID::VibrationValue{ | ||
| 1686 | .low_amplitude = 1.0f, | ||
| 1687 | .low_frequency = 160.0f, | ||
| 1688 | .high_amplitude = 1.0f, | ||
| 1689 | .high_frequency = 320.0f, | ||
| 1690 | }; | ||
| 1691 | case Core::HID::VibrationGcErmCommand::StopHard: | ||
| 1692 | return Core::HID::VibrationValue{ | ||
| 1693 | .low_amplitude = 0.0f, | ||
| 1694 | .low_frequency = 0.0f, | ||
| 1695 | .high_amplitude = 0.0f, | ||
| 1696 | .high_frequency = 0.0f, | ||
| 1697 | }; | ||
| 1698 | default: | ||
| 1699 | return Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 1700 | } | ||
| 1701 | }(); | ||
| 1702 | |||
| 1703 | GetResourceManager()->GetNpad()->VibrateController( | ||
| 1704 | parameters.applet_resource_user_id, parameters.vibration_device_handle, vibration_value); | ||
| 1705 | |||
| 1706 | LOG_DEBUG(Service_HID, | 1683 | LOG_DEBUG(Service_HID, |
| 1707 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " | 1684 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " |
| 1708 | "gc_erm_command={}", | 1685 | "gc_erm_command={}", |
| @@ -1711,8 +1688,23 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1711 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, | 1688 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, |
| 1712 | parameters.gc_erm_command); | 1689 | parameters.gc_erm_command); |
| 1713 | 1690 | ||
| 1691 | bool has_active_aruid{}; | ||
| 1692 | NpadGcVibrationDevice* gc_device{nullptr}; | ||
| 1693 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1694 | has_active_aruid); | ||
| 1695 | |||
| 1696 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1697 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1698 | } | ||
| 1699 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1700 | gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); | ||
| 1701 | } | ||
| 1702 | if (gc_device != nullptr) { | ||
| 1703 | result = gc_device->SendVibrationGcErmCommand(parameters.gc_erm_command); | ||
| 1704 | } | ||
| 1705 | |||
| 1714 | IPC::ResponseBuilder rb{ctx, 2}; | 1706 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1715 | rb.Push(ResultSuccess); | 1707 | rb.Push(result); |
| 1716 | } | 1708 | } |
| 1717 | 1709 | ||
| 1718 | void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { | 1710 | void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { |
| @@ -1725,33 +1717,31 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { | |||
| 1725 | 1717 | ||
| 1726 | const auto parameters{rp.PopRaw<Parameters>()}; | 1718 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 1727 | 1719 | ||
| 1728 | const auto last_vibration = GetResourceManager()->GetNpad()->GetLastVibration( | ||
| 1729 | parameters.applet_resource_user_id, parameters.vibration_device_handle); | ||
| 1730 | |||
| 1731 | const auto gc_erm_command = [last_vibration] { | ||
| 1732 | if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) { | ||
| 1733 | return Core::HID::VibrationGcErmCommand::Start; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | /** | ||
| 1737 | * Note: This uses yuzu-specific behavior such that the StopHard command produces | ||
| 1738 | * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function | ||
| 1739 | * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands. | ||
| 1740 | * This is done to reuse the controller vibration functions made for regular controllers. | ||
| 1741 | */ | ||
| 1742 | if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) { | ||
| 1743 | return Core::HID::VibrationGcErmCommand::StopHard; | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | return Core::HID::VibrationGcErmCommand::Stop; | ||
| 1747 | }(); | ||
| 1748 | |||
| 1749 | LOG_DEBUG(Service_HID, | 1720 | LOG_DEBUG(Service_HID, |
| 1750 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", | 1721 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", |
| 1751 | parameters.vibration_device_handle.npad_type, | 1722 | parameters.vibration_device_handle.npad_type, |
| 1752 | parameters.vibration_device_handle.npad_id, | 1723 | parameters.vibration_device_handle.npad_id, |
| 1753 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1724 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1754 | 1725 | ||
| 1726 | bool has_active_aruid{}; | ||
| 1727 | NpadGcVibrationDevice* gc_device{nullptr}; | ||
| 1728 | Core::HID::VibrationGcErmCommand gc_erm_command{}; | ||
| 1729 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1730 | has_active_aruid); | ||
| 1731 | |||
| 1732 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1733 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1734 | } | ||
| 1735 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1736 | gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle); | ||
| 1737 | } | ||
| 1738 | if (gc_device != nullptr) { | ||
| 1739 | result = gc_device->GetActualVibrationGcErmCommand(gc_erm_command); | ||
| 1740 | } | ||
| 1741 | if (result.IsError()) { | ||
| 1742 | gc_erm_command = Core::HID::VibrationGcErmCommand::Stop; | ||
| 1743 | } | ||
| 1744 | |||
| 1755 | IPC::ResponseBuilder rb{ctx, 4}; | 1745 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1756 | rb.Push(ResultSuccess); | 1746 | rb.Push(ResultSuccess); |
| 1757 | rb.PushEnum(gc_erm_command); | 1747 | rb.PushEnum(gc_erm_command); |
| @@ -1761,21 +1751,24 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) { | |||
| 1761 | IPC::RequestParser rp{ctx}; | 1751 | IPC::RequestParser rp{ctx}; |
| 1762 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 1752 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 1763 | 1753 | ||
| 1764 | GetResourceManager()->GetNpad()->SetPermitVibrationSession(true); | ||
| 1765 | |||
| 1766 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | 1754 | LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); |
| 1767 | 1755 | ||
| 1756 | const auto result = | ||
| 1757 | GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( | ||
| 1758 | applet_resource_user_id); | ||
| 1759 | |||
| 1768 | IPC::ResponseBuilder rb{ctx, 2}; | 1760 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1769 | rb.Push(ResultSuccess); | 1761 | rb.Push(result); |
| 1770 | } | 1762 | } |
| 1771 | 1763 | ||
| 1772 | void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { | 1764 | void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { |
| 1773 | GetResourceManager()->GetNpad()->SetPermitVibrationSession(false); | ||
| 1774 | |||
| 1775 | LOG_DEBUG(Service_HID, "called"); | 1765 | LOG_DEBUG(Service_HID, "called"); |
| 1776 | 1766 | ||
| 1767 | const auto result = | ||
| 1768 | GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); | ||
| 1769 | |||
| 1777 | IPC::ResponseBuilder rb{ctx, 2}; | 1770 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1778 | rb.Push(ResultSuccess); | 1771 | rb.Push(result); |
| 1779 | } | 1772 | } |
| 1780 | 1773 | ||
| 1781 | void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { | 1774 | void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { |
| @@ -1795,10 +1788,61 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { | |||
| 1795 | parameters.vibration_device_handle.npad_id, | 1788 | parameters.vibration_device_handle.npad_id, |
| 1796 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); | 1789 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); |
| 1797 | 1790 | ||
| 1791 | bool is_mounted{}; | ||
| 1792 | NpadVibrationBase* device{nullptr}; | ||
| 1793 | Result result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1794 | |||
| 1795 | if (result.IsSuccess()) { | ||
| 1796 | device = GetResourceManager()->GetVibrationDevice(parameters.vibration_device_handle); | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | if (device != nullptr) { | ||
| 1800 | is_mounted = device->IsVibrationMounted(); | ||
| 1801 | } | ||
| 1802 | |||
| 1798 | IPC::ResponseBuilder rb{ctx, 3}; | 1803 | IPC::ResponseBuilder rb{ctx, 3}; |
| 1799 | rb.Push(ResultSuccess); | 1804 | rb.Push(result); |
| 1800 | rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted( | 1805 | rb.Push(is_mounted); |
| 1801 | parameters.applet_resource_user_id, parameters.vibration_device_handle)); | 1806 | } |
| 1807 | |||
| 1808 | void IHidServer::SendVibrationValueInBool(HLERequestContext& ctx) { | ||
| 1809 | IPC::RequestParser rp{ctx}; | ||
| 1810 | struct Parameters { | ||
| 1811 | Core::HID::VibrationDeviceHandle vibration_device_handle; | ||
| 1812 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 1813 | u64 applet_resource_user_id; | ||
| 1814 | bool is_vibrating; | ||
| 1815 | }; | ||
| 1816 | static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size."); | ||
| 1817 | |||
| 1818 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 1819 | |||
| 1820 | LOG_DEBUG(Service_HID, | ||
| 1821 | "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " | ||
| 1822 | "is_vibrating={}", | ||
| 1823 | parameters.vibration_device_handle.npad_type, | ||
| 1824 | parameters.vibration_device_handle.npad_id, | ||
| 1825 | parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, | ||
| 1826 | parameters.is_vibrating); | ||
| 1827 | |||
| 1828 | bool has_active_aruid{}; | ||
| 1829 | NpadN64VibrationDevice* n64_device{nullptr}; | ||
| 1830 | Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id, | ||
| 1831 | has_active_aruid); | ||
| 1832 | |||
| 1833 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1834 | result = IsVibrationHandleValid(parameters.vibration_device_handle); | ||
| 1835 | } | ||
| 1836 | if (result.IsSuccess() && has_active_aruid) { | ||
| 1837 | n64_device = | ||
| 1838 | GetResourceManager()->GetN64VibrationDevice(parameters.vibration_device_handle); | ||
| 1839 | } | ||
| 1840 | if (n64_device != nullptr) { | ||
| 1841 | result = n64_device->SendValueInBool(parameters.is_vibrating); | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 1845 | rb.Push(result); | ||
| 1802 | } | 1846 | } |
| 1803 | 1847 | ||
| 1804 | void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { | 1848 | void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h index cc7c4ebdd..3a2e0a230 100644 --- a/src/core/hle/service/hid/hid_server.h +++ b/src/core/hle/service/hid/hid_server.h | |||
| @@ -97,6 +97,7 @@ private: | |||
| 97 | void BeginPermitVibrationSession(HLERequestContext& ctx); | 97 | void BeginPermitVibrationSession(HLERequestContext& ctx); |
| 98 | void EndPermitVibrationSession(HLERequestContext& ctx); | 98 | void EndPermitVibrationSession(HLERequestContext& ctx); |
| 99 | void IsVibrationDeviceMounted(HLERequestContext& ctx); | 99 | void IsVibrationDeviceMounted(HLERequestContext& ctx); |
| 100 | void SendVibrationValueInBool(HLERequestContext& ctx); | ||
| 100 | void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); | 101 | void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); |
| 101 | void StartConsoleSixAxisSensor(HLERequestContext& ctx); | 102 | void StartConsoleSixAxisSensor(HLERequestContext& ctx); |
| 102 | void StopConsoleSixAxisSensor(HLERequestContext& ctx); | 103 | void StopConsoleSixAxisSensor(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 3a0cb3cb1..bf27ddfbf 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "hid_core/resource_manager.h" | 7 | #include "hid_core/resource_manager.h" |
| 8 | #include "hid_core/resources/npad/npad.h" | 8 | #include "hid_core/resources/npad/npad.h" |
| 9 | #include "hid_core/resources/npad/npad_types.h" | 9 | #include "hid_core/resources/npad/npad_types.h" |
| 10 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 10 | #include "hid_core/resources/palma/palma.h" | 11 | #include "hid_core/resources/palma/palma.h" |
| 11 | #include "hid_core/resources/touch_screen/touch_screen.h" | 12 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 12 | 13 | ||
| @@ -67,14 +68,14 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour | |||
| 67 | {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, | 68 | {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, |
| 68 | {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, | 69 | {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, |
| 69 | {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, | 70 | {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, |
| 70 | {504, nullptr, "SetAruidValidForVibration"}, | 71 | {504, &IHidSystemServer::SetAruidValidForVibration, "SetAruidValidForVibration"}, |
| 71 | {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, | 72 | {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, |
| 72 | {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, | 73 | {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, |
| 73 | {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, | 74 | {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, |
| 74 | {510, nullptr, "SetVibrationMasterVolume"}, | 75 | {510, &IHidSystemServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"}, |
| 75 | {511, nullptr, "GetVibrationMasterVolume"}, | 76 | {511, &IHidSystemServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"}, |
| 76 | {512, nullptr, "BeginPermitVibrationSession"}, | 77 | {512, &IHidSystemServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, |
| 77 | {513, nullptr, "EndPermitVibrationSession"}, | 78 | {513, &IHidSystemServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, |
| 78 | {514, nullptr, "Unknown514"}, | 79 | {514, nullptr, "Unknown514"}, |
| 79 | {520, nullptr, "EnableHandheldHids"}, | 80 | {520, nullptr, "EnableHandheldHids"}, |
| 80 | {521, nullptr, "DisableHandheldHids"}, | 81 | {521, nullptr, "DisableHandheldHids"}, |
| @@ -156,7 +157,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour | |||
| 156 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, | 157 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, |
| 157 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, | 158 | {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, |
| 158 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, | 159 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, |
| 159 | {1155, nullptr, "SetForceHandheldStyleVibration"}, | 160 | {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"}, |
| 160 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, | 161 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, |
| 161 | {1157, nullptr, "CancelConnectionTrigger"}, | 162 | {1157, nullptr, "CancelConnectionTrigger"}, |
| 162 | {1200, nullptr, "IsButtonConfigSupported"}, | 163 | {1200, nullptr, "IsButtonConfigSupported"}, |
| @@ -532,7 +533,28 @@ void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) { | |||
| 532 | parameters.is_enabled, parameters.applet_resource_user_id); | 533 | parameters.is_enabled, parameters.applet_resource_user_id); |
| 533 | 534 | ||
| 534 | GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled); | 535 | GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled); |
| 535 | // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); | 536 | GetResourceManager()->GetNpad()->EnableAppletToGetInput(parameters.applet_resource_user_id); |
| 537 | |||
| 538 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 539 | rb.Push(ResultSuccess); | ||
| 540 | } | ||
| 541 | |||
| 542 | void IHidSystemServer::SetAruidValidForVibration(HLERequestContext& ctx) { | ||
| 543 | IPC::RequestParser rp{ctx}; | ||
| 544 | struct Parameters { | ||
| 545 | bool is_enabled; | ||
| 546 | INSERT_PADDING_WORDS_NOINIT(1); | ||
| 547 | u64 applet_resource_user_id; | ||
| 548 | }; | ||
| 549 | static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); | ||
| 550 | |||
| 551 | const auto parameters{rp.PopRaw<Parameters>()}; | ||
| 552 | |||
| 553 | LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}", | ||
| 554 | parameters.is_enabled, parameters.applet_resource_user_id); | ||
| 555 | |||
| 556 | GetResourceManager()->SetAruidValidForVibration(parameters.applet_resource_user_id, | ||
| 557 | parameters.is_enabled); | ||
| 536 | 558 | ||
| 537 | IPC::ResponseBuilder rb{ctx, 2}; | 559 | IPC::ResponseBuilder rb{ctx, 2}; |
| 538 | rb.Push(ResultSuccess); | 560 | rb.Push(ResultSuccess); |
| @@ -574,7 +596,7 @@ void IHidSystemServer::EnableAppletToGetPadInput(HLERequestContext& ctx) { | |||
| 574 | parameters.is_enabled, parameters.applet_resource_user_id); | 596 | parameters.is_enabled, parameters.applet_resource_user_id); |
| 575 | 597 | ||
| 576 | GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled); | 598 | GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled); |
| 577 | // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); | 599 | GetResourceManager()->GetNpad()->EnableAppletToGetInput(parameters.applet_resource_user_id); |
| 578 | 600 | ||
| 579 | IPC::ResponseBuilder rb{ctx, 2}; | 601 | IPC::ResponseBuilder rb{ctx, 2}; |
| 580 | rb.Push(ResultSuccess); | 602 | rb.Push(ResultSuccess); |
| @@ -601,6 +623,57 @@ void IHidSystemServer::EnableAppletToGetTouchScreen(HLERequestContext& ctx) { | |||
| 601 | rb.Push(ResultSuccess); | 623 | rb.Push(ResultSuccess); |
| 602 | } | 624 | } |
| 603 | 625 | ||
| 626 | void IHidSystemServer::SetVibrationMasterVolume(HLERequestContext& ctx) { | ||
| 627 | IPC::RequestParser rp{ctx}; | ||
| 628 | const auto master_volume{rp.Pop<f32>()}; | ||
| 629 | |||
| 630 | LOG_INFO(Service_HID, "called, volume={}", master_volume); | ||
| 631 | |||
| 632 | const auto result = | ||
| 633 | GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume( | ||
| 634 | master_volume); | ||
| 635 | |||
| 636 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 637 | rb.Push(result); | ||
| 638 | } | ||
| 639 | |||
| 640 | void IHidSystemServer::GetVibrationMasterVolume(HLERequestContext& ctx) { | ||
| 641 | f32 master_volume{}; | ||
| 642 | const auto result = | ||
| 643 | GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume( | ||
| 644 | master_volume); | ||
| 645 | |||
| 646 | LOG_INFO(Service_HID, "called, volume={}", master_volume); | ||
| 647 | |||
| 648 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 649 | rb.Push(result); | ||
| 650 | rb.Push(master_volume); | ||
| 651 | } | ||
| 652 | |||
| 653 | void IHidSystemServer::BeginPermitVibrationSession(HLERequestContext& ctx) { | ||
| 654 | IPC::RequestParser rp{ctx}; | ||
| 655 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 656 | |||
| 657 | LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); | ||
| 658 | |||
| 659 | const auto result = | ||
| 660 | GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession( | ||
| 661 | applet_resource_user_id); | ||
| 662 | |||
| 663 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 664 | rb.Push(result); | ||
| 665 | } | ||
| 666 | |||
| 667 | void IHidSystemServer::EndPermitVibrationSession(HLERequestContext& ctx) { | ||
| 668 | LOG_INFO(Service_HID, "called"); | ||
| 669 | |||
| 670 | const auto result = | ||
| 671 | GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession(); | ||
| 672 | |||
| 673 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 674 | rb.Push(result); | ||
| 675 | } | ||
| 676 | |||
| 604 | void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { | 677 | void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { |
| 605 | const bool is_attached = true; | 678 | const bool is_attached = true; |
| 606 | 679 | ||
| @@ -749,6 +822,19 @@ void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx | |||
| 749 | rb.PushRaw(touchscreen_config); | 822 | rb.PushRaw(touchscreen_config); |
| 750 | } | 823 | } |
| 751 | 824 | ||
| 825 | void IHidSystemServer::SetForceHandheldStyleVibration(HLERequestContext& ctx) { | ||
| 826 | IPC::RequestParser rp{ctx}; | ||
| 827 | const auto is_forced{rp.Pop<bool>()}; | ||
| 828 | |||
| 829 | LOG_INFO(Service_HID, "called, is_forced={}", is_forced); | ||
| 830 | |||
| 831 | GetResourceManager()->SetForceHandheldStyleVibration(is_forced); | ||
| 832 | GetResourceManager()->GetNpad()->UpdateHandheldAbstractState(); | ||
| 833 | |||
| 834 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 835 | rb.Push(ResultSuccess); | ||
| 836 | } | ||
| 837 | |||
| 752 | void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { | 838 | void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { |
| 753 | const bool is_enabled = false; | 839 | const bool is_enabled = false; |
| 754 | 840 | ||
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index 0c2634e3f..90a719f02 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h | |||
| @@ -42,9 +42,14 @@ private: | |||
| 42 | void RegisterAppletResourceUserId(HLERequestContext& ctx); | 42 | void RegisterAppletResourceUserId(HLERequestContext& ctx); |
| 43 | void UnregisterAppletResourceUserId(HLERequestContext& ctx); | 43 | void UnregisterAppletResourceUserId(HLERequestContext& ctx); |
| 44 | void EnableAppletToGetInput(HLERequestContext& ctx); | 44 | void EnableAppletToGetInput(HLERequestContext& ctx); |
| 45 | void SetAruidValidForVibration(HLERequestContext& ctx); | ||
| 45 | void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); | 46 | void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); |
| 46 | void EnableAppletToGetPadInput(HLERequestContext& ctx); | 47 | void EnableAppletToGetPadInput(HLERequestContext& ctx); |
| 47 | void EnableAppletToGetTouchScreen(HLERequestContext& ctx); | 48 | void EnableAppletToGetTouchScreen(HLERequestContext& ctx); |
| 49 | void SetVibrationMasterVolume(HLERequestContext& ctx); | ||
| 50 | void GetVibrationMasterVolume(HLERequestContext& ctx); | ||
| 51 | void BeginPermitVibrationSession(HLERequestContext& ctx); | ||
| 52 | void EndPermitVibrationSession(HLERequestContext& ctx); | ||
| 48 | void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); | 53 | void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); |
| 49 | void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); | 54 | void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); |
| 50 | void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); | 55 | void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); |
| @@ -61,6 +66,7 @@ private: | |||
| 61 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); | 66 | void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); |
| 62 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); | 67 | void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); |
| 63 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); | 68 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); |
| 69 | void SetForceHandheldStyleVibration(HLERequestContext& ctx); | ||
| 64 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); | 70 | void IsUsingCustomButtonConfig(HLERequestContext& ctx); |
| 65 | 71 | ||
| 66 | std::shared_ptr<ResourceManager> GetResourceManager(); | 72 | std::shared_ptr<ResourceManager> GetResourceManager(); |
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 3f38ceb03..e491dd260 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/logging/log.h" | 13 | #include "common/logging/log.h" |
| 14 | #include "common/scratch_buffer.h" | 14 | #include "common/scratch_buffer.h" |
| 15 | #include "core/guest_memory.h" | ||
| 15 | #include "core/hle/kernel/k_auto_object.h" | 16 | #include "core/hle/kernel/k_auto_object.h" |
| 16 | #include "core/hle/kernel/k_handle_table.h" | 17 | #include "core/hle/kernel/k_handle_table.h" |
| 17 | #include "core/hle/kernel/k_process.h" | 18 | #include "core/hle/kernel/k_process.h" |
| @@ -23,19 +24,6 @@ | |||
| 23 | #include "core/hle/service/ipc_helpers.h" | 24 | #include "core/hle/service/ipc_helpers.h" |
| 24 | #include "core/memory.h" | 25 | #include "core/memory.h" |
| 25 | 26 | ||
| 26 | namespace { | ||
| 27 | static thread_local std::array read_buffer_data_a{ | ||
| 28 | Common::ScratchBuffer<u8>(), | ||
| 29 | Common::ScratchBuffer<u8>(), | ||
| 30 | Common::ScratchBuffer<u8>(), | ||
| 31 | }; | ||
| 32 | static thread_local std::array read_buffer_data_x{ | ||
| 33 | Common::ScratchBuffer<u8>(), | ||
| 34 | Common::ScratchBuffer<u8>(), | ||
| 35 | Common::ScratchBuffer<u8>(), | ||
| 36 | }; | ||
| 37 | } // Anonymous namespace | ||
| 38 | |||
| 39 | namespace Service { | 27 | namespace Service { |
| 40 | 28 | ||
| 41 | SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) | 29 | SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) |
| @@ -343,48 +331,27 @@ std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) cons | |||
| 343 | } | 331 | } |
| 344 | 332 | ||
| 345 | std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const { | 333 | std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const { |
| 346 | static thread_local std::array read_buffer_a{ | 334 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0); |
| 347 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 348 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 349 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 350 | }; | ||
| 351 | 335 | ||
| 352 | ASSERT_OR_EXECUTE_MSG( | 336 | ASSERT_OR_EXECUTE_MSG( |
| 353 | BufferDescriptorA().size() > buffer_index, { return {}; }, | 337 | BufferDescriptorA().size() > buffer_index, { return {}; }, |
| 354 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 338 | "BufferDescriptorA invalid buffer_index {}", buffer_index); |
| 355 | auto& read_buffer = read_buffer_a[buffer_index]; | 339 | return gm.Read(BufferDescriptorA()[buffer_index].Address(), |
| 356 | return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), | 340 | BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]); |
| 357 | BufferDescriptorA()[buffer_index].Size(), | ||
| 358 | &read_buffer_data_a[buffer_index]); | ||
| 359 | } | 341 | } |
| 360 | 342 | ||
| 361 | std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const { | 343 | std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const { |
| 362 | static thread_local std::array read_buffer_x{ | 344 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0); |
| 363 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 364 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 365 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 366 | }; | ||
| 367 | 345 | ||
| 368 | ASSERT_OR_EXECUTE_MSG( | 346 | ASSERT_OR_EXECUTE_MSG( |
| 369 | BufferDescriptorX().size() > buffer_index, { return {}; }, | 347 | BufferDescriptorX().size() > buffer_index, { return {}; }, |
| 370 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 348 | "BufferDescriptorX invalid buffer_index {}", buffer_index); |
| 371 | auto& read_buffer = read_buffer_x[buffer_index]; | 349 | return gm.Read(BufferDescriptorX()[buffer_index].Address(), |
| 372 | return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), | 350 | BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]); |
| 373 | BufferDescriptorX()[buffer_index].Size(), | ||
| 374 | &read_buffer_data_x[buffer_index]); | ||
| 375 | } | 351 | } |
| 376 | 352 | ||
| 377 | std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { | 353 | std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { |
| 378 | static thread_local std::array read_buffer_a{ | 354 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0); |
| 379 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 380 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 381 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 382 | }; | ||
| 383 | static thread_local std::array read_buffer_x{ | ||
| 384 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 385 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 386 | Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0), | ||
| 387 | }; | ||
| 388 | 355 | ||
| 389 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 356 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 390 | BufferDescriptorA()[buffer_index].Size()}; | 357 | BufferDescriptorA()[buffer_index].Size()}; |
| @@ -401,18 +368,14 @@ std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) cons | |||
| 401 | ASSERT_OR_EXECUTE_MSG( | 368 | ASSERT_OR_EXECUTE_MSG( |
| 402 | BufferDescriptorA().size() > buffer_index, { return {}; }, | 369 | BufferDescriptorA().size() > buffer_index, { return {}; }, |
| 403 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 370 | "BufferDescriptorA invalid buffer_index {}", buffer_index); |
| 404 | auto& read_buffer = read_buffer_a[buffer_index]; | 371 | return gm.Read(BufferDescriptorA()[buffer_index].Address(), |
| 405 | return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), | 372 | BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]); |
| 406 | BufferDescriptorA()[buffer_index].Size(), | ||
| 407 | &read_buffer_data_a[buffer_index]); | ||
| 408 | } else { | 373 | } else { |
| 409 | ASSERT_OR_EXECUTE_MSG( | 374 | ASSERT_OR_EXECUTE_MSG( |
| 410 | BufferDescriptorX().size() > buffer_index, { return {}; }, | 375 | BufferDescriptorX().size() > buffer_index, { return {}; }, |
| 411 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 376 | "BufferDescriptorX invalid buffer_index {}", buffer_index); |
| 412 | auto& read_buffer = read_buffer_x[buffer_index]; | 377 | return gm.Read(BufferDescriptorX()[buffer_index].Address(), |
| 413 | return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), | 378 | BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]); |
| 414 | BufferDescriptorX()[buffer_index].Size(), | ||
| 415 | &read_buffer_data_x[buffer_index]); | ||
| 416 | } | 379 | } |
| 417 | } | 380 | } |
| 418 | 381 | ||
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index 440737db5..8329d7265 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h | |||
| @@ -41,6 +41,8 @@ class KernelCore; | |||
| 41 | class KHandleTable; | 41 | class KHandleTable; |
| 42 | class KProcess; | 42 | class KProcess; |
| 43 | class KServerSession; | 43 | class KServerSession; |
| 44 | template <typename T> | ||
| 45 | class KScopedAutoObject; | ||
| 44 | class KThread; | 46 | class KThread; |
| 45 | } // namespace Kernel | 47 | } // namespace Kernel |
| 46 | 48 | ||
| @@ -424,6 +426,9 @@ private: | |||
| 424 | 426 | ||
| 425 | Kernel::KernelCore& kernel; | 427 | Kernel::KernelCore& kernel; |
| 426 | Core::Memory::Memory& memory; | 428 | Core::Memory::Memory& memory; |
| 429 | |||
| 430 | mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_a{}; | ||
| 431 | mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_x{}; | ||
| 427 | }; | 432 | }; |
| 428 | 433 | ||
| 429 | } // namespace Service | 434 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp index 37ca24f5d..21ef57d27 100644 --- a/src/core/hle/service/nvdrv/core/container.cpp +++ b/src/core/hle/service/nvdrv/core/container.cpp | |||
| @@ -2,27 +2,135 @@ | |||
| 2 | // SPDX-FileCopyrightText: 2022 Skyline Team and Contributors | 2 | // SPDX-FileCopyrightText: 2022 Skyline Team and Contributors |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later | 3 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 4 | 4 | ||
| 5 | #include <atomic> | ||
| 6 | #include <deque> | ||
| 7 | #include <mutex> | ||
| 8 | |||
| 9 | #include "core/hle/kernel/k_process.h" | ||
| 5 | #include "core/hle/service/nvdrv/core/container.h" | 10 | #include "core/hle/service/nvdrv/core/container.h" |
| 11 | #include "core/hle/service/nvdrv/core/heap_mapper.h" | ||
| 6 | #include "core/hle/service/nvdrv/core/nvmap.h" | 12 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 7 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 13 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| 14 | #include "core/memory.h" | ||
| 8 | #include "video_core/host1x/host1x.h" | 15 | #include "video_core/host1x/host1x.h" |
| 9 | 16 | ||
| 10 | namespace Service::Nvidia::NvCore { | 17 | namespace Service::Nvidia::NvCore { |
| 11 | 18 | ||
| 19 | Session::Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_) | ||
| 20 | : id{id_}, process{process_}, asid{asid_}, has_preallocated_area{}, mapper{}, is_active{} {} | ||
| 21 | |||
| 22 | Session::~Session() = default; | ||
| 23 | |||
| 12 | struct ContainerImpl { | 24 | struct ContainerImpl { |
| 13 | explicit ContainerImpl(Tegra::Host1x::Host1x& host1x_) | 25 | explicit ContainerImpl(Container& core, Tegra::Host1x::Host1x& host1x_) |
| 14 | : file{host1x_}, manager{host1x_}, device_file_data{} {} | 26 | : host1x{host1x_}, file{core, host1x_}, manager{host1x_}, device_file_data{} {} |
| 27 | Tegra::Host1x::Host1x& host1x; | ||
| 15 | NvMap file; | 28 | NvMap file; |
| 16 | SyncpointManager manager; | 29 | SyncpointManager manager; |
| 17 | Container::Host1xDeviceFileData device_file_data; | 30 | Container::Host1xDeviceFileData device_file_data; |
| 31 | std::deque<Session> sessions; | ||
| 32 | size_t new_ids{}; | ||
| 33 | std::deque<size_t> id_pool; | ||
| 34 | std::mutex session_guard; | ||
| 18 | }; | 35 | }; |
| 19 | 36 | ||
| 20 | Container::Container(Tegra::Host1x::Host1x& host1x_) { | 37 | Container::Container(Tegra::Host1x::Host1x& host1x_) { |
| 21 | impl = std::make_unique<ContainerImpl>(host1x_); | 38 | impl = std::make_unique<ContainerImpl>(*this, host1x_); |
| 22 | } | 39 | } |
| 23 | 40 | ||
| 24 | Container::~Container() = default; | 41 | Container::~Container() = default; |
| 25 | 42 | ||
| 43 | SessionId Container::OpenSession(Kernel::KProcess* process) { | ||
| 44 | using namespace Common::Literals; | ||
| 45 | |||
| 46 | std::scoped_lock lk(impl->session_guard); | ||
| 47 | for (auto& session : impl->sessions) { | ||
| 48 | if (!session.is_active) { | ||
| 49 | continue; | ||
| 50 | } | ||
| 51 | if (session.process == process) { | ||
| 52 | return session.id; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | size_t new_id{}; | ||
| 56 | auto* memory_interface = &process->GetMemory(); | ||
| 57 | auto& smmu = impl->host1x.MemoryManager(); | ||
| 58 | auto asid = smmu.RegisterProcess(memory_interface); | ||
| 59 | if (!impl->id_pool.empty()) { | ||
| 60 | new_id = impl->id_pool.front(); | ||
| 61 | impl->id_pool.pop_front(); | ||
| 62 | impl->sessions[new_id] = Session{SessionId{new_id}, process, asid}; | ||
| 63 | } else { | ||
| 64 | new_id = impl->new_ids++; | ||
| 65 | impl->sessions.emplace_back(SessionId{new_id}, process, asid); | ||
| 66 | } | ||
| 67 | auto& session = impl->sessions[new_id]; | ||
| 68 | session.is_active = true; | ||
| 69 | // Optimization | ||
| 70 | if (process->IsApplication()) { | ||
| 71 | auto& page_table = process->GetPageTable().GetBasePageTable(); | ||
| 72 | auto heap_start = page_table.GetHeapRegionStart(); | ||
| 73 | |||
| 74 | Kernel::KProcessAddress cur_addr = heap_start; | ||
| 75 | size_t region_size = 0; | ||
| 76 | VAddr region_start = 0; | ||
| 77 | while (true) { | ||
| 78 | Kernel::KMemoryInfo mem_info{}; | ||
| 79 | Kernel::Svc::PageInfo page_info{}; | ||
| 80 | R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info), | ||
| 81 | cur_addr)); | ||
| 82 | auto svc_mem_info = mem_info.GetSvcMemoryInfo(); | ||
| 83 | |||
| 84 | // Check if this memory block is heap. | ||
| 85 | if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) { | ||
| 86 | if (svc_mem_info.size > region_size) { | ||
| 87 | region_size = svc_mem_info.size; | ||
| 88 | region_start = svc_mem_info.base_address; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | // Check if we're done. | ||
| 93 | const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size; | ||
| 94 | if (next_address <= GetInteger(cur_addr)) { | ||
| 95 | break; | ||
| 96 | } | ||
| 97 | |||
| 98 | cur_addr = next_address; | ||
| 99 | } | ||
| 100 | session.has_preallocated_area = false; | ||
| 101 | auto start_region = region_size >= 32_MiB ? smmu.Allocate(region_size) : 0; | ||
| 102 | if (start_region != 0) { | ||
| 103 | session.mapper = std::make_unique<HeapMapper>(region_start, start_region, region_size, | ||
| 104 | asid, impl->host1x); | ||
| 105 | smmu.TrackContinuity(start_region, region_start, region_size, asid); | ||
| 106 | session.has_preallocated_area = true; | ||
| 107 | LOG_DEBUG(Debug, "Preallocation created!"); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | return SessionId{new_id}; | ||
| 111 | } | ||
| 112 | |||
| 113 | void Container::CloseSession(SessionId session_id) { | ||
| 114 | std::scoped_lock lk(impl->session_guard); | ||
| 115 | auto& session = impl->sessions[session_id.id]; | ||
| 116 | auto& smmu = impl->host1x.MemoryManager(); | ||
| 117 | if (session.has_preallocated_area) { | ||
| 118 | const DAddr region_start = session.mapper->GetRegionStart(); | ||
| 119 | const size_t region_size = session.mapper->GetRegionSize(); | ||
| 120 | session.mapper.reset(); | ||
| 121 | smmu.Free(region_start, region_size); | ||
| 122 | session.has_preallocated_area = false; | ||
| 123 | } | ||
| 124 | session.is_active = false; | ||
| 125 | smmu.UnregisterProcess(impl->sessions[session_id.id].asid); | ||
| 126 | impl->id_pool.emplace_front(session_id.id); | ||
| 127 | } | ||
| 128 | |||
| 129 | Session* Container::GetSession(SessionId session_id) { | ||
| 130 | std::atomic_thread_fence(std::memory_order_acquire); | ||
| 131 | return &impl->sessions[session_id.id]; | ||
| 132 | } | ||
| 133 | |||
| 26 | NvMap& Container::GetNvMapFile() { | 134 | NvMap& Container::GetNvMapFile() { |
| 27 | return impl->file; | 135 | return impl->file; |
| 28 | } | 136 | } |
diff --git a/src/core/hle/service/nvdrv/core/container.h b/src/core/hle/service/nvdrv/core/container.h index b4b63ac90..b4d3938a8 100644 --- a/src/core/hle/service/nvdrv/core/container.h +++ b/src/core/hle/service/nvdrv/core/container.h | |||
| @@ -8,24 +8,56 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | 10 | ||
| 11 | #include "core/device_memory_manager.h" | ||
| 11 | #include "core/hle/service/nvdrv/nvdata.h" | 12 | #include "core/hle/service/nvdrv/nvdata.h" |
| 12 | 13 | ||
| 14 | namespace Kernel { | ||
| 15 | class KProcess; | ||
| 16 | } | ||
| 17 | |||
| 13 | namespace Tegra::Host1x { | 18 | namespace Tegra::Host1x { |
| 14 | class Host1x; | 19 | class Host1x; |
| 15 | } // namespace Tegra::Host1x | 20 | } // namespace Tegra::Host1x |
| 16 | 21 | ||
| 17 | namespace Service::Nvidia::NvCore { | 22 | namespace Service::Nvidia::NvCore { |
| 18 | 23 | ||
| 24 | class HeapMapper; | ||
| 19 | class NvMap; | 25 | class NvMap; |
| 20 | class SyncpointManager; | 26 | class SyncpointManager; |
| 21 | 27 | ||
| 22 | struct ContainerImpl; | 28 | struct ContainerImpl; |
| 23 | 29 | ||
| 30 | struct SessionId { | ||
| 31 | size_t id; | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct Session { | ||
| 35 | Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_); | ||
| 36 | ~Session(); | ||
| 37 | |||
| 38 | Session(const Session&) = delete; | ||
| 39 | Session& operator=(const Session&) = delete; | ||
| 40 | Session(Session&&) = default; | ||
| 41 | Session& operator=(Session&&) = default; | ||
| 42 | |||
| 43 | SessionId id; | ||
| 44 | Kernel::KProcess* process; | ||
| 45 | Core::Asid asid; | ||
| 46 | bool has_preallocated_area{}; | ||
| 47 | std::unique_ptr<HeapMapper> mapper{}; | ||
| 48 | bool is_active{}; | ||
| 49 | }; | ||
| 50 | |||
| 24 | class Container { | 51 | class Container { |
| 25 | public: | 52 | public: |
| 26 | explicit Container(Tegra::Host1x::Host1x& host1x); | 53 | explicit Container(Tegra::Host1x::Host1x& host1x); |
| 27 | ~Container(); | 54 | ~Container(); |
| 28 | 55 | ||
| 56 | SessionId OpenSession(Kernel::KProcess* process); | ||
| 57 | void CloseSession(SessionId id); | ||
| 58 | |||
| 59 | Session* GetSession(SessionId id); | ||
| 60 | |||
| 29 | NvMap& GetNvMapFile(); | 61 | NvMap& GetNvMapFile(); |
| 30 | 62 | ||
| 31 | const NvMap& GetNvMapFile() const; | 63 | const NvMap& GetNvMapFile() const; |
diff --git a/src/core/hle/service/nvdrv/core/heap_mapper.cpp b/src/core/hle/service/nvdrv/core/heap_mapper.cpp new file mode 100644 index 000000000..096dc5deb --- /dev/null +++ b/src/core/hle/service/nvdrv/core/heap_mapper.cpp | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #include <mutex> | ||
| 5 | |||
| 6 | #include <boost/container/small_vector.hpp> | ||
| 7 | #define BOOST_NO_MT | ||
| 8 | #include <boost/pool/detail/mutex.hpp> | ||
| 9 | #undef BOOST_NO_MT | ||
| 10 | #include <boost/icl/interval.hpp> | ||
| 11 | #include <boost/icl/interval_base_set.hpp> | ||
| 12 | #include <boost/icl/interval_set.hpp> | ||
| 13 | #include <boost/icl/split_interval_map.hpp> | ||
| 14 | #include <boost/pool/pool.hpp> | ||
| 15 | #include <boost/pool/pool_alloc.hpp> | ||
| 16 | #include <boost/pool/poolfwd.hpp> | ||
| 17 | |||
| 18 | #include "core/hle/service/nvdrv/core/heap_mapper.h" | ||
| 19 | #include "video_core/host1x/host1x.h" | ||
| 20 | |||
| 21 | namespace boost { | ||
| 22 | template <typename T> | ||
| 23 | class fast_pool_allocator<T, default_user_allocator_new_delete, details::pool::null_mutex, 4096, 0>; | ||
| 24 | } | ||
| 25 | |||
| 26 | namespace Service::Nvidia::NvCore { | ||
| 27 | |||
| 28 | using IntervalCompare = std::less<DAddr>; | ||
| 29 | using IntervalInstance = boost::icl::interval_type_default<DAddr, std::less>; | ||
| 30 | using IntervalAllocator = boost::fast_pool_allocator<DAddr>; | ||
| 31 | using IntervalSet = boost::icl::interval_set<DAddr>; | ||
| 32 | using IntervalType = typename IntervalSet::interval_type; | ||
| 33 | |||
| 34 | template <typename Type> | ||
| 35 | struct counter_add_functor : public boost::icl::identity_based_inplace_combine<Type> { | ||
| 36 | // types | ||
| 37 | typedef counter_add_functor<Type> type; | ||
| 38 | typedef boost::icl::identity_based_inplace_combine<Type> base_type; | ||
| 39 | |||
| 40 | // public member functions | ||
| 41 | void operator()(Type& current, const Type& added) const { | ||
| 42 | current += added; | ||
| 43 | if (current < base_type::identity_element()) { | ||
| 44 | current = base_type::identity_element(); | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | // public static functions | ||
| 49 | static void version(Type&){}; | ||
| 50 | }; | ||
| 51 | |||
| 52 | using OverlapCombine = counter_add_functor<int>; | ||
| 53 | using OverlapSection = boost::icl::inter_section<int>; | ||
| 54 | using OverlapCounter = boost::icl::split_interval_map<DAddr, int>; | ||
| 55 | |||
| 56 | struct HeapMapper::HeapMapperInternal { | ||
| 57 | HeapMapperInternal(Tegra::Host1x::Host1x& host1x) : device_memory{host1x.MemoryManager()} {} | ||
| 58 | ~HeapMapperInternal() = default; | ||
| 59 | |||
| 60 | template <typename Func> | ||
| 61 | void ForEachInOverlapCounter(OverlapCounter& current_range, VAddr cpu_addr, u64 size, | ||
| 62 | Func&& func) { | ||
| 63 | const DAddr start_address = cpu_addr; | ||
| 64 | const DAddr end_address = start_address + size; | ||
| 65 | const IntervalType search_interval{start_address, end_address}; | ||
| 66 | auto it = current_range.lower_bound(search_interval); | ||
| 67 | if (it == current_range.end()) { | ||
| 68 | return; | ||
| 69 | } | ||
| 70 | auto end_it = current_range.upper_bound(search_interval); | ||
| 71 | for (; it != end_it; it++) { | ||
| 72 | auto& inter = it->first; | ||
| 73 | DAddr inter_addr_end = inter.upper(); | ||
| 74 | DAddr inter_addr = inter.lower(); | ||
| 75 | if (inter_addr_end > end_address) { | ||
| 76 | inter_addr_end = end_address; | ||
| 77 | } | ||
| 78 | if (inter_addr < start_address) { | ||
| 79 | inter_addr = start_address; | ||
| 80 | } | ||
| 81 | func(inter_addr, inter_addr_end, it->second); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | void RemoveEachInOverlapCounter(OverlapCounter& current_range, | ||
| 86 | const IntervalType search_interval, int subtract_value) { | ||
| 87 | bool any_removals = false; | ||
| 88 | current_range.add(std::make_pair(search_interval, subtract_value)); | ||
| 89 | do { | ||
| 90 | any_removals = false; | ||
| 91 | auto it = current_range.lower_bound(search_interval); | ||
| 92 | if (it == current_range.end()) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | auto end_it = current_range.upper_bound(search_interval); | ||
| 96 | for (; it != end_it; it++) { | ||
| 97 | if (it->second <= 0) { | ||
| 98 | any_removals = true; | ||
| 99 | current_range.erase(it); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } while (any_removals); | ||
| 104 | } | ||
| 105 | |||
| 106 | IntervalSet base_set; | ||
| 107 | OverlapCounter mapping_overlaps; | ||
| 108 | Tegra::MaxwellDeviceMemoryManager& device_memory; | ||
| 109 | std::mutex guard; | ||
| 110 | }; | ||
| 111 | |||
| 112 | HeapMapper::HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid, | ||
| 113 | Tegra::Host1x::Host1x& host1x) | ||
| 114 | : m_vaddress{start_vaddress}, m_daddress{start_daddress}, m_size{size}, m_asid{asid} { | ||
| 115 | m_internal = std::make_unique<HeapMapperInternal>(host1x); | ||
| 116 | } | ||
| 117 | |||
| 118 | HeapMapper::~HeapMapper() { | ||
| 119 | m_internal->device_memory.Unmap(m_daddress, m_size); | ||
| 120 | } | ||
| 121 | |||
| 122 | DAddr HeapMapper::Map(VAddr start, size_t size) { | ||
| 123 | std::scoped_lock lk(m_internal->guard); | ||
| 124 | m_internal->base_set.clear(); | ||
| 125 | const IntervalType interval{start, start + size}; | ||
| 126 | m_internal->base_set.insert(interval); | ||
| 127 | m_internal->ForEachInOverlapCounter(m_internal->mapping_overlaps, start, size, | ||
| 128 | [this](VAddr start_addr, VAddr end_addr, int) { | ||
| 129 | const IntervalType other{start_addr, end_addr}; | ||
| 130 | m_internal->base_set.subtract(other); | ||
| 131 | }); | ||
| 132 | if (!m_internal->base_set.empty()) { | ||
| 133 | auto it = m_internal->base_set.begin(); | ||
| 134 | auto end_it = m_internal->base_set.end(); | ||
| 135 | for (; it != end_it; it++) { | ||
| 136 | const VAddr inter_addr_end = it->upper(); | ||
| 137 | const VAddr inter_addr = it->lower(); | ||
| 138 | const size_t offset = inter_addr - m_vaddress; | ||
| 139 | const size_t sub_size = inter_addr_end - inter_addr; | ||
| 140 | m_internal->device_memory.Map(m_daddress + offset, m_vaddress + offset, sub_size, | ||
| 141 | m_asid); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | m_internal->mapping_overlaps += std::make_pair(interval, 1); | ||
| 145 | m_internal->base_set.clear(); | ||
| 146 | return m_daddress + (start - m_vaddress); | ||
| 147 | } | ||
| 148 | |||
| 149 | void HeapMapper::Unmap(VAddr start, size_t size) { | ||
| 150 | std::scoped_lock lk(m_internal->guard); | ||
| 151 | m_internal->base_set.clear(); | ||
| 152 | m_internal->ForEachInOverlapCounter(m_internal->mapping_overlaps, start, size, | ||
| 153 | [this](VAddr start_addr, VAddr end_addr, int value) { | ||
| 154 | if (value <= 1) { | ||
| 155 | const IntervalType other{start_addr, end_addr}; | ||
| 156 | m_internal->base_set.insert(other); | ||
| 157 | } | ||
| 158 | }); | ||
| 159 | if (!m_internal->base_set.empty()) { | ||
| 160 | auto it = m_internal->base_set.begin(); | ||
| 161 | auto end_it = m_internal->base_set.end(); | ||
| 162 | for (; it != end_it; it++) { | ||
| 163 | const VAddr inter_addr_end = it->upper(); | ||
| 164 | const VAddr inter_addr = it->lower(); | ||
| 165 | const size_t offset = inter_addr - m_vaddress; | ||
| 166 | const size_t sub_size = inter_addr_end - inter_addr; | ||
| 167 | m_internal->device_memory.Unmap(m_daddress + offset, sub_size); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | const IntervalType to_remove{start, start + size}; | ||
| 171 | m_internal->RemoveEachInOverlapCounter(m_internal->mapping_overlaps, to_remove, -1); | ||
| 172 | m_internal->base_set.clear(); | ||
| 173 | } | ||
| 174 | |||
| 175 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/core/heap_mapper.h b/src/core/hle/service/nvdrv/core/heap_mapper.h new file mode 100644 index 000000000..491a12e4f --- /dev/null +++ b/src/core/hle/service/nvdrv/core/heap_mapper.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/device_memory_manager.h" | ||
| 10 | |||
| 11 | namespace Tegra::Host1x { | ||
| 12 | class Host1x; | ||
| 13 | } // namespace Tegra::Host1x | ||
| 14 | |||
| 15 | namespace Service::Nvidia::NvCore { | ||
| 16 | |||
| 17 | class HeapMapper { | ||
| 18 | public: | ||
| 19 | HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid, | ||
| 20 | Tegra::Host1x::Host1x& host1x); | ||
| 21 | ~HeapMapper(); | ||
| 22 | |||
| 23 | bool IsInBounds(VAddr start, size_t size) const { | ||
| 24 | VAddr end = start + size; | ||
| 25 | return start >= m_vaddress && end <= (m_vaddress + m_size); | ||
| 26 | } | ||
| 27 | |||
| 28 | DAddr Map(VAddr start, size_t size); | ||
| 29 | |||
| 30 | void Unmap(VAddr start, size_t size); | ||
| 31 | |||
| 32 | DAddr GetRegionStart() const { | ||
| 33 | return m_daddress; | ||
| 34 | } | ||
| 35 | |||
| 36 | size_t GetRegionSize() const { | ||
| 37 | return m_size; | ||
| 38 | } | ||
| 39 | |||
| 40 | private: | ||
| 41 | struct HeapMapperInternal; | ||
| 42 | VAddr m_vaddress; | ||
| 43 | DAddr m_daddress; | ||
| 44 | size_t m_size; | ||
| 45 | Core::Asid m_asid; | ||
| 46 | std::unique_ptr<HeapMapperInternal> m_internal; | ||
| 47 | }; | ||
| 48 | |||
| 49 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp index 0ca05257e..1b59c6b15 100644 --- a/src/core/hle/service/nvdrv/core/nvmap.cpp +++ b/src/core/hle/service/nvdrv/core/nvmap.cpp | |||
| @@ -2,14 +2,19 @@ | |||
| 2 | // SPDX-FileCopyrightText: 2022 Skyline Team and Contributors | 2 | // SPDX-FileCopyrightText: 2022 Skyline Team and Contributors |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later | 3 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 4 | 4 | ||
| 5 | #include <functional> | ||
| 6 | |||
| 5 | #include "common/alignment.h" | 7 | #include "common/alignment.h" |
| 6 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 11 | #include "core/hle/service/nvdrv/core/heap_mapper.h" | ||
| 8 | #include "core/hle/service/nvdrv/core/nvmap.h" | 12 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 9 | #include "core/memory.h" | 13 | #include "core/memory.h" |
| 10 | #include "video_core/host1x/host1x.h" | 14 | #include "video_core/host1x/host1x.h" |
| 11 | 15 | ||
| 12 | using Core::Memory::YUZU_PAGESIZE; | 16 | using Core::Memory::YUZU_PAGESIZE; |
| 17 | constexpr size_t BIG_PAGE_SIZE = YUZU_PAGESIZE * 16; | ||
| 13 | 18 | ||
| 14 | namespace Service::Nvidia::NvCore { | 19 | namespace Service::Nvidia::NvCore { |
| 15 | NvMap::Handle::Handle(u64 size_, Id id_) | 20 | NvMap::Handle::Handle(u64 size_, Id id_) |
| @@ -17,9 +22,9 @@ NvMap::Handle::Handle(u64 size_, Id id_) | |||
| 17 | flags.raw = 0; | 22 | flags.raw = 0; |
| 18 | } | 23 | } |
| 19 | 24 | ||
| 20 | NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) { | 25 | NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, |
| 26 | NvCore::SessionId pSessionId) { | ||
| 21 | std::scoped_lock lock(mutex); | 27 | std::scoped_lock lock(mutex); |
| 22 | |||
| 23 | // Handles cannot be allocated twice | 28 | // Handles cannot be allocated twice |
| 24 | if (allocated) { | 29 | if (allocated) { |
| 25 | return NvResult::AccessDenied; | 30 | return NvResult::AccessDenied; |
| @@ -28,6 +33,7 @@ NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) | |||
| 28 | flags = pFlags; | 33 | flags = pFlags; |
| 29 | kind = pKind; | 34 | kind = pKind; |
| 30 | align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign; | 35 | align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign; |
| 36 | session_id = pSessionId; | ||
| 31 | 37 | ||
| 32 | // This flag is only applicable for handles with an address passed | 38 | // This flag is only applicable for handles with an address passed |
| 33 | if (pAddress) { | 39 | if (pAddress) { |
| @@ -63,7 +69,7 @@ NvResult NvMap::Handle::Duplicate(bool internal_session) { | |||
| 63 | return NvResult::Success; | 69 | return NvResult::Success; |
| 64 | } | 70 | } |
| 65 | 71 | ||
| 66 | NvMap::NvMap(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {} | 72 | NvMap::NvMap(Container& core_, Tegra::Host1x::Host1x& host1x_) : host1x{host1x_}, core{core_} {} |
| 67 | 73 | ||
| 68 | void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) { | 74 | void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) { |
| 69 | std::scoped_lock lock(handles_lock); | 75 | std::scoped_lock lock(handles_lock); |
| @@ -78,12 +84,30 @@ void NvMap::UnmapHandle(Handle& handle_description) { | |||
| 78 | handle_description.unmap_queue_entry.reset(); | 84 | handle_description.unmap_queue_entry.reset(); |
| 79 | } | 85 | } |
| 80 | 86 | ||
| 87 | // Free and unmap the handle from Host1x GMMU | ||
| 88 | if (handle_description.pin_virt_address) { | ||
| 89 | host1x.GMMU().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address), | ||
| 90 | handle_description.aligned_size); | ||
| 91 | host1x.Allocator().Free(handle_description.pin_virt_address, | ||
| 92 | static_cast<u32>(handle_description.aligned_size)); | ||
| 93 | handle_description.pin_virt_address = 0; | ||
| 94 | } | ||
| 95 | |||
| 81 | // Free and unmap the handle from the SMMU | 96 | // Free and unmap the handle from the SMMU |
| 82 | host1x.MemoryManager().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address), | 97 | const size_t map_size = handle_description.aligned_size; |
| 83 | handle_description.aligned_size); | 98 | if (!handle_description.in_heap) { |
| 84 | host1x.Allocator().Free(handle_description.pin_virt_address, | 99 | auto& smmu = host1x.MemoryManager(); |
| 85 | static_cast<u32>(handle_description.aligned_size)); | 100 | size_t aligned_up = Common::AlignUp(map_size, BIG_PAGE_SIZE); |
| 86 | handle_description.pin_virt_address = 0; | 101 | smmu.Unmap(handle_description.d_address, map_size); |
| 102 | smmu.Free(handle_description.d_address, static_cast<size_t>(aligned_up)); | ||
| 103 | handle_description.d_address = 0; | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | const VAddr vaddress = handle_description.address; | ||
| 107 | auto* session = core.GetSession(handle_description.session_id); | ||
| 108 | session->mapper->Unmap(vaddress, map_size); | ||
| 109 | handle_description.d_address = 0; | ||
| 110 | handle_description.in_heap = false; | ||
| 87 | } | 111 | } |
| 88 | 112 | ||
| 89 | bool NvMap::TryRemoveHandle(const Handle& handle_description) { | 113 | bool NvMap::TryRemoveHandle(const Handle& handle_description) { |
| @@ -124,22 +148,33 @@ std::shared_ptr<NvMap::Handle> NvMap::GetHandle(Handle::Id handle) { | |||
| 124 | } | 148 | } |
| 125 | } | 149 | } |
| 126 | 150 | ||
| 127 | VAddr NvMap::GetHandleAddress(Handle::Id handle) { | 151 | DAddr NvMap::GetHandleAddress(Handle::Id handle) { |
| 128 | std::scoped_lock lock(handles_lock); | 152 | std::scoped_lock lock(handles_lock); |
| 129 | try { | 153 | try { |
| 130 | return handles.at(handle)->address; | 154 | return handles.at(handle)->d_address; |
| 131 | } catch (std::out_of_range&) { | 155 | } catch (std::out_of_range&) { |
| 132 | return 0; | 156 | return 0; |
| 133 | } | 157 | } |
| 134 | } | 158 | } |
| 135 | 159 | ||
| 136 | u32 NvMap::PinHandle(NvMap::Handle::Id handle) { | 160 | DAddr NvMap::PinHandle(NvMap::Handle::Id handle, bool low_area_pin) { |
| 137 | auto handle_description{GetHandle(handle)}; | 161 | auto handle_description{GetHandle(handle)}; |
| 138 | if (!handle_description) [[unlikely]] { | 162 | if (!handle_description) [[unlikely]] { |
| 139 | return 0; | 163 | return 0; |
| 140 | } | 164 | } |
| 141 | 165 | ||
| 142 | std::scoped_lock lock(handle_description->mutex); | 166 | std::scoped_lock lock(handle_description->mutex); |
| 167 | const auto map_low_area = [&] { | ||
| 168 | if (handle_description->pin_virt_address == 0) { | ||
| 169 | auto& gmmu_allocator = host1x.Allocator(); | ||
| 170 | auto& gmmu = host1x.GMMU(); | ||
| 171 | u32 address = | ||
| 172 | gmmu_allocator.Allocate(static_cast<u32>(handle_description->aligned_size)); | ||
| 173 | gmmu.Map(static_cast<GPUVAddr>(address), handle_description->d_address, | ||
| 174 | handle_description->aligned_size); | ||
| 175 | handle_description->pin_virt_address = address; | ||
| 176 | } | ||
| 177 | }; | ||
| 143 | if (!handle_description->pins) { | 178 | if (!handle_description->pins) { |
| 144 | // If we're in the unmap queue we can just remove ourselves and return since we're already | 179 | // If we're in the unmap queue we can just remove ourselves and return since we're already |
| 145 | // mapped | 180 | // mapped |
| @@ -151,37 +186,58 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) { | |||
| 151 | unmap_queue.erase(*handle_description->unmap_queue_entry); | 186 | unmap_queue.erase(*handle_description->unmap_queue_entry); |
| 152 | handle_description->unmap_queue_entry.reset(); | 187 | handle_description->unmap_queue_entry.reset(); |
| 153 | 188 | ||
| 189 | if (low_area_pin) { | ||
| 190 | map_low_area(); | ||
| 191 | handle_description->pins++; | ||
| 192 | return static_cast<DAddr>(handle_description->pin_virt_address); | ||
| 193 | } | ||
| 194 | |||
| 154 | handle_description->pins++; | 195 | handle_description->pins++; |
| 155 | return handle_description->pin_virt_address; | 196 | return handle_description->d_address; |
| 156 | } | 197 | } |
| 157 | } | 198 | } |
| 158 | 199 | ||
| 200 | using namespace std::placeholders; | ||
| 159 | // If not then allocate some space and map it | 201 | // If not then allocate some space and map it |
| 160 | u32 address{}; | 202 | DAddr address{}; |
| 161 | auto& smmu_allocator = host1x.Allocator(); | 203 | auto& smmu = host1x.MemoryManager(); |
| 162 | auto& smmu_memory_manager = host1x.MemoryManager(); | 204 | auto* session = core.GetSession(handle_description->session_id); |
| 163 | while ((address = smmu_allocator.Allocate( | 205 | const VAddr vaddress = handle_description->address; |
| 164 | static_cast<u32>(handle_description->aligned_size))) == 0) { | 206 | const size_t map_size = handle_description->aligned_size; |
| 165 | // Free handles until the allocation succeeds | 207 | if (session->has_preallocated_area && session->mapper->IsInBounds(vaddress, map_size)) { |
| 166 | std::scoped_lock queueLock(unmap_queue_lock); | 208 | handle_description->d_address = session->mapper->Map(vaddress, map_size); |
| 167 | if (auto freeHandleDesc{unmap_queue.front()}) { | 209 | handle_description->in_heap = true; |
| 168 | // Handles in the unmap queue are guaranteed not to be pinned so don't bother | 210 | } else { |
| 169 | // checking if they are before unmapping | 211 | size_t aligned_up = Common::AlignUp(map_size, BIG_PAGE_SIZE); |
| 170 | std::scoped_lock freeLock(freeHandleDesc->mutex); | 212 | while ((address = smmu.Allocate(aligned_up)) == 0) { |
| 171 | if (handle_description->pin_virt_address) | 213 | // Free handles until the allocation succeeds |
| 172 | UnmapHandle(*freeHandleDesc); | 214 | std::scoped_lock queueLock(unmap_queue_lock); |
| 173 | } else { | 215 | if (auto freeHandleDesc{unmap_queue.front()}) { |
| 174 | LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!"); | 216 | // Handles in the unmap queue are guaranteed not to be pinned so don't bother |
| 217 | // checking if they are before unmapping | ||
| 218 | std::scoped_lock freeLock(freeHandleDesc->mutex); | ||
| 219 | if (handle_description->d_address) | ||
| 220 | UnmapHandle(*freeHandleDesc); | ||
| 221 | } else { | ||
| 222 | LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!"); | ||
| 223 | } | ||
| 175 | } | 224 | } |
| 225 | |||
| 226 | handle_description->d_address = address; | ||
| 227 | smmu.Map(address, vaddress, map_size, session->asid, true); | ||
| 228 | handle_description->in_heap = false; | ||
| 176 | } | 229 | } |
| 230 | } | ||
| 177 | 231 | ||
| 178 | smmu_memory_manager.Map(static_cast<GPUVAddr>(address), handle_description->address, | 232 | if (low_area_pin) { |
| 179 | handle_description->aligned_size); | 233 | map_low_area(); |
| 180 | handle_description->pin_virt_address = address; | ||
| 181 | } | 234 | } |
| 182 | 235 | ||
| 183 | handle_description->pins++; | 236 | handle_description->pins++; |
| 184 | return handle_description->pin_virt_address; | 237 | if (low_area_pin) { |
| 238 | return static_cast<DAddr>(handle_description->pin_virt_address); | ||
| 239 | } | ||
| 240 | return handle_description->d_address; | ||
| 185 | } | 241 | } |
| 186 | 242 | ||
| 187 | void NvMap::UnpinHandle(Handle::Id handle) { | 243 | void NvMap::UnpinHandle(Handle::Id handle) { |
| @@ -232,7 +288,7 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna | |||
| 232 | LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!"); | 288 | LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!"); |
| 233 | } else if (handle_description->dupes == 0) { | 289 | } else if (handle_description->dupes == 0) { |
| 234 | // Force unmap the handle | 290 | // Force unmap the handle |
| 235 | if (handle_description->pin_virt_address) { | 291 | if (handle_description->d_address) { |
| 236 | std::scoped_lock queueLock(unmap_queue_lock); | 292 | std::scoped_lock queueLock(unmap_queue_lock); |
| 237 | UnmapHandle(*handle_description); | 293 | UnmapHandle(*handle_description); |
| 238 | } | 294 | } |
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h index a8e573890..d7f695845 100644 --- a/src/core/hle/service/nvdrv/core/nvmap.h +++ b/src/core/hle/service/nvdrv/core/nvmap.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include "common/bit_field.h" | 15 | #include "common/bit_field.h" |
| 16 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 17 | #include "core/hle/service/nvdrv/nvdata.h" | 18 | #include "core/hle/service/nvdrv/nvdata.h" |
| 18 | 19 | ||
| 19 | namespace Tegra { | 20 | namespace Tegra { |
| @@ -25,6 +26,8 @@ class Host1x; | |||
| 25 | } // namespace Tegra | 26 | } // namespace Tegra |
| 26 | 27 | ||
| 27 | namespace Service::Nvidia::NvCore { | 28 | namespace Service::Nvidia::NvCore { |
| 29 | |||
| 30 | class Container; | ||
| 28 | /** | 31 | /** |
| 29 | * @brief The nvmap core class holds the global state for nvmap and provides methods to manage | 32 | * @brief The nvmap core class holds the global state for nvmap and provides methods to manage |
| 30 | * handles | 33 | * handles |
| @@ -48,7 +51,7 @@ public: | |||
| 48 | using Id = u32; | 51 | using Id = u32; |
| 49 | Id id; //!< A globally unique identifier for this handle | 52 | Id id; //!< A globally unique identifier for this handle |
| 50 | 53 | ||
| 51 | s32 pins{}; | 54 | s64 pins{}; |
| 52 | u32 pin_virt_address{}; | 55 | u32 pin_virt_address{}; |
| 53 | std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{}; | 56 | std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{}; |
| 54 | 57 | ||
| @@ -61,15 +64,18 @@ public: | |||
| 61 | } flags{}; | 64 | } flags{}; |
| 62 | static_assert(sizeof(Flags) == sizeof(u32)); | 65 | static_assert(sizeof(Flags) == sizeof(u32)); |
| 63 | 66 | ||
| 64 | u64 address{}; //!< The memory location in the guest's AS that this handle corresponds to, | 67 | VAddr address{}; //!< The memory location in the guest's AS that this handle corresponds to, |
| 65 | //!< this can also be in the nvdrv tmem | 68 | //!< this can also be in the nvdrv tmem |
| 66 | bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC | 69 | bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC |
| 67 | //!< call | 70 | //!< call |
| 68 | 71 | ||
| 69 | u8 kind{}; //!< Used for memory compression | 72 | u8 kind{}; //!< Used for memory compression |
| 70 | bool allocated{}; //!< If the handle has been allocated with `Alloc` | 73 | bool allocated{}; //!< If the handle has been allocated with `Alloc` |
| 74 | bool in_heap{}; | ||
| 75 | NvCore::SessionId session_id{}; | ||
| 71 | 76 | ||
| 72 | u64 dma_map_addr{}; //! remove me after implementing pinning. | 77 | DAddr d_address{}; //!< The memory location in the device's AS that this handle corresponds |
| 78 | //!< to, this can also be in the nvdrv tmem | ||
| 73 | 79 | ||
| 74 | Handle(u64 size, Id id); | 80 | Handle(u64 size, Id id); |
| 75 | 81 | ||
| @@ -77,7 +83,8 @@ public: | |||
| 77 | * @brief Sets up the handle with the given memory config, can allocate memory from the tmem | 83 | * @brief Sets up the handle with the given memory config, can allocate memory from the tmem |
| 78 | * if a 0 address is passed | 84 | * if a 0 address is passed |
| 79 | */ | 85 | */ |
| 80 | [[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress); | 86 | [[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, |
| 87 | NvCore::SessionId pSessionId); | ||
| 81 | 88 | ||
| 82 | /** | 89 | /** |
| 83 | * @brief Increases the dupe counter of the handle for the given session | 90 | * @brief Increases the dupe counter of the handle for the given session |
| @@ -108,7 +115,7 @@ public: | |||
| 108 | bool can_unlock; //!< If the address region is ready to be unlocked | 115 | bool can_unlock; //!< If the address region is ready to be unlocked |
| 109 | }; | 116 | }; |
| 110 | 117 | ||
| 111 | explicit NvMap(Tegra::Host1x::Host1x& host1x); | 118 | explicit NvMap(Container& core, Tegra::Host1x::Host1x& host1x); |
| 112 | 119 | ||
| 113 | /** | 120 | /** |
| 114 | * @brief Creates an unallocated handle of the given size | 121 | * @brief Creates an unallocated handle of the given size |
| @@ -117,7 +124,7 @@ public: | |||
| 117 | 124 | ||
| 118 | std::shared_ptr<Handle> GetHandle(Handle::Id handle); | 125 | std::shared_ptr<Handle> GetHandle(Handle::Id handle); |
| 119 | 126 | ||
| 120 | VAddr GetHandleAddress(Handle::Id handle); | 127 | DAddr GetHandleAddress(Handle::Id handle); |
| 121 | 128 | ||
| 122 | /** | 129 | /** |
| 123 | * @brief Maps a handle into the SMMU address space | 130 | * @brief Maps a handle into the SMMU address space |
| @@ -125,7 +132,7 @@ public: | |||
| 125 | * number of calls to `UnpinHandle` | 132 | * number of calls to `UnpinHandle` |
| 126 | * @return The SMMU virtual address that the handle has been mapped to | 133 | * @return The SMMU virtual address that the handle has been mapped to |
| 127 | */ | 134 | */ |
| 128 | u32 PinHandle(Handle::Id handle); | 135 | DAddr PinHandle(Handle::Id handle, bool low_area_pin); |
| 129 | 136 | ||
| 130 | /** | 137 | /** |
| 131 | * @brief When this has been called an equal number of times to `PinHandle` for the supplied | 138 | * @brief When this has been called an equal number of times to `PinHandle` for the supplied |
| @@ -172,5 +179,7 @@ private: | |||
| 172 | * @return If the handle was removed from the map | 179 | * @return If the handle was removed from the map |
| 173 | */ | 180 | */ |
| 174 | bool TryRemoveHandle(const Handle& handle_description); | 181 | bool TryRemoveHandle(const Handle& handle_description); |
| 182 | |||
| 183 | Container& core; | ||
| 175 | }; | 184 | }; |
| 176 | } // namespace Service::Nvidia::NvCore | 185 | } // namespace Service::Nvidia::NvCore |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index a04538d5d..8adaddc60 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 10 | #include "core/hle/service/nvdrv/nvdata.h" | 11 | #include "core/hle/service/nvdrv/nvdata.h" |
| 11 | 12 | ||
| 12 | namespace Core { | 13 | namespace Core { |
| @@ -62,7 +63,7 @@ public: | |||
| 62 | * Called once a device is opened | 63 | * Called once a device is opened |
| 63 | * @param fd The device fd | 64 | * @param fd The device fd |
| 64 | */ | 65 | */ |
| 65 | virtual void OnOpen(DeviceFD fd) = 0; | 66 | virtual void OnOpen(NvCore::SessionId session_id, DeviceFD fd) = 0; |
| 66 | 67 | ||
| 67 | /** | 68 | /** |
| 68 | * Called once a device is closed | 69 | * Called once a device is closed |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 05a43d8dc..c1ebbd62d 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -35,14 +35,14 @@ NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 35 | return NvResult::NotImplemented; | 35 | return NvResult::NotImplemented; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | void nvdisp_disp0::OnOpen(DeviceFD fd) {} | 38 | void nvdisp_disp0::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 39 | void nvdisp_disp0::OnClose(DeviceFD fd) {} | 39 | void nvdisp_disp0::OnClose(DeviceFD fd) {} |
| 40 | 40 | ||
| 41 | void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, | 41 | void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, |
| 42 | u32 height, u32 stride, android::BufferTransformFlags transform, | 42 | u32 height, u32 stride, android::BufferTransformFlags transform, |
| 43 | const Common::Rectangle<int>& crop_rect, | 43 | const Common::Rectangle<int>& crop_rect, |
| 44 | std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) { | 44 | std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) { |
| 45 | const VAddr addr = nvmap.GetHandleAddress(buffer_handle); | 45 | const DAddr addr = nvmap.GetHandleAddress(buffer_handle); |
| 46 | LOG_TRACE(Service, | 46 | LOG_TRACE(Service, |
| 47 | "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", | 47 | "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", |
| 48 | addr, offset, width, height, stride, format); | 48 | addr, offset, width, height, stride, format); |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index daee05fe8..5f13a50a2 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | |||
| @@ -32,7 +32,7 @@ public: | |||
| 32 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 32 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 33 | std::span<u8> inline_output) override; | 33 | std::span<u8> inline_output) override; |
| 34 | 34 | ||
| 35 | void OnOpen(DeviceFD fd) override; | 35 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 36 | void OnClose(DeviceFD fd) override; | 36 | void OnClose(DeviceFD fd) override; |
| 37 | 37 | ||
| 38 | /// Performs a screen flip, drawing the buffer pointed to by the handle. | 38 | /// Performs a screen flip, drawing the buffer pointed to by the handle. |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 6b3639008..e6646ba04 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | |||
| @@ -86,7 +86,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i | |||
| 86 | return NvResult::NotImplemented; | 86 | return NvResult::NotImplemented; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | void nvhost_as_gpu::OnOpen(DeviceFD fd) {} | 89 | void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 90 | void nvhost_as_gpu::OnClose(DeviceFD fd) {} | 90 | void nvhost_as_gpu::OnClose(DeviceFD fd) {} |
| 91 | 91 | ||
| 92 | NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { | 92 | NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { |
| @@ -206,6 +206,8 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) { | |||
| 206 | static_cast<u32>(aligned_size >> page_size_bits)); | 206 | static_cast<u32>(aligned_size >> page_size_bits)); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | nvmap.UnpinHandle(mapping->handle); | ||
| 210 | |||
| 209 | // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state | 211 | // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state |
| 210 | // Only FreeSpace can unmap them fully | 212 | // Only FreeSpace can unmap them fully |
| 211 | if (mapping->sparse_alloc) { | 213 | if (mapping->sparse_alloc) { |
| @@ -293,12 +295,12 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) { | |||
| 293 | return NvResult::BadValue; | 295 | return NvResult::BadValue; |
| 294 | } | 296 | } |
| 295 | 297 | ||
| 296 | VAddr cpu_address{static_cast<VAddr>( | 298 | DAddr base = nvmap.PinHandle(entry.handle, false); |
| 297 | handle->address + | 299 | DAddr device_address{static_cast<DAddr>( |
| 298 | (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))}; | 300 | base + (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))}; |
| 299 | 301 | ||
| 300 | gmmu->Map(virtual_address, cpu_address, size, static_cast<Tegra::PTEKind>(entry.kind), | 302 | gmmu->Map(virtual_address, device_address, size, |
| 301 | use_big_pages); | 303 | static_cast<Tegra::PTEKind>(entry.kind), use_big_pages); |
| 302 | } | 304 | } |
| 303 | } | 305 | } |
| 304 | 306 | ||
| @@ -331,9 +333,9 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { | |||
| 331 | } | 333 | } |
| 332 | 334 | ||
| 333 | u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)}; | 335 | u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)}; |
| 334 | VAddr cpu_address{mapping->ptr + params.buffer_offset}; | 336 | VAddr device_address{mapping->ptr + params.buffer_offset}; |
| 335 | 337 | ||
| 336 | gmmu->Map(gpu_address, cpu_address, params.mapping_size, | 338 | gmmu->Map(gpu_address, device_address, params.mapping_size, |
| 337 | static_cast<Tegra::PTEKind>(params.kind), mapping->big_page); | 339 | static_cast<Tegra::PTEKind>(params.kind), mapping->big_page); |
| 338 | 340 | ||
| 339 | return NvResult::Success; | 341 | return NvResult::Success; |
| @@ -349,7 +351,8 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { | |||
| 349 | return NvResult::BadValue; | 351 | return NvResult::BadValue; |
| 350 | } | 352 | } |
| 351 | 353 | ||
| 352 | VAddr cpu_address{static_cast<VAddr>(handle->address + params.buffer_offset)}; | 354 | DAddr device_address{ |
| 355 | static_cast<DAddr>(nvmap.PinHandle(params.handle, false) + params.buffer_offset)}; | ||
| 353 | u64 size{params.mapping_size ? params.mapping_size : handle->orig_size}; | 356 | u64 size{params.mapping_size ? params.mapping_size : handle->orig_size}; |
| 354 | 357 | ||
| 355 | bool big_page{[&]() { | 358 | bool big_page{[&]() { |
| @@ -373,15 +376,14 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { | |||
| 373 | } | 376 | } |
| 374 | 377 | ||
| 375 | const bool use_big_pages = alloc->second.big_pages && big_page; | 378 | const bool use_big_pages = alloc->second.big_pages && big_page; |
| 376 | gmmu->Map(params.offset, cpu_address, size, static_cast<Tegra::PTEKind>(params.kind), | 379 | gmmu->Map(params.offset, device_address, size, static_cast<Tegra::PTEKind>(params.kind), |
| 377 | use_big_pages); | 380 | use_big_pages); |
| 378 | 381 | ||
| 379 | auto mapping{std::make_shared<Mapping>(cpu_address, params.offset, size, true, | 382 | auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size, |
| 380 | use_big_pages, alloc->second.sparse)}; | 383 | true, use_big_pages, alloc->second.sparse)}; |
| 381 | alloc->second.mappings.push_back(mapping); | 384 | alloc->second.mappings.push_back(mapping); |
| 382 | mapping_map[params.offset] = mapping; | 385 | mapping_map[params.offset] = mapping; |
| 383 | } else { | 386 | } else { |
| 384 | |||
| 385 | auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; | 387 | auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; |
| 386 | u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE}; | 388 | u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE}; |
| 387 | u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; | 389 | u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; |
| @@ -394,11 +396,11 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) { | |||
| 394 | return NvResult::InsufficientMemory; | 396 | return NvResult::InsufficientMemory; |
| 395 | } | 397 | } |
| 396 | 398 | ||
| 397 | gmmu->Map(params.offset, cpu_address, Common::AlignUp(size, page_size), | 399 | gmmu->Map(params.offset, device_address, Common::AlignUp(size, page_size), |
| 398 | static_cast<Tegra::PTEKind>(params.kind), big_page); | 400 | static_cast<Tegra::PTEKind>(params.kind), big_page); |
| 399 | 401 | ||
| 400 | auto mapping{ | 402 | auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size, |
| 401 | std::make_shared<Mapping>(cpu_address, params.offset, size, false, big_page, false)}; | 403 | false, big_page, false)}; |
| 402 | mapping_map[params.offset] = mapping; | 404 | mapping_map[params.offset] = mapping; |
| 403 | } | 405 | } |
| 404 | 406 | ||
| @@ -433,6 +435,8 @@ NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) { | |||
| 433 | gmmu->Unmap(params.offset, mapping->size); | 435 | gmmu->Unmap(params.offset, mapping->size); |
| 434 | } | 436 | } |
| 435 | 437 | ||
| 438 | nvmap.UnpinHandle(mapping->handle); | ||
| 439 | |||
| 436 | mapping_map.erase(params.offset); | 440 | mapping_map.erase(params.offset); |
| 437 | } catch (const std::out_of_range&) { | 441 | } catch (const std::out_of_range&) { |
| 438 | LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset); | 442 | LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 79a21683d..7d0a99988 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -55,7 +55,7 @@ public: | |||
| 55 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 55 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 56 | std::span<u8> inline_output) override; | 56 | std::span<u8> inline_output) override; |
| 57 | 57 | ||
| 58 | void OnOpen(DeviceFD fd) override; | 58 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 59 | void OnClose(DeviceFD fd) override; | 59 | void OnClose(DeviceFD fd) override; |
| 60 | 60 | ||
| 61 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 61 | Kernel::KEvent* QueryEvent(u32 event_id) override; |
| @@ -159,16 +159,18 @@ private: | |||
| 159 | NvCore::NvMap& nvmap; | 159 | NvCore::NvMap& nvmap; |
| 160 | 160 | ||
| 161 | struct Mapping { | 161 | struct Mapping { |
| 162 | VAddr ptr; | 162 | NvCore::NvMap::Handle::Id handle; |
| 163 | DAddr ptr; | ||
| 163 | u64 offset; | 164 | u64 offset; |
| 164 | u64 size; | 165 | u64 size; |
| 165 | bool fixed; | 166 | bool fixed; |
| 166 | bool big_page; // Only valid if fixed == false | 167 | bool big_page; // Only valid if fixed == false |
| 167 | bool sparse_alloc; | 168 | bool sparse_alloc; |
| 168 | 169 | ||
| 169 | Mapping(VAddr ptr_, u64 offset_, u64 size_, bool fixed_, bool big_page_, bool sparse_alloc_) | 170 | Mapping(NvCore::NvMap::Handle::Id handle_, DAddr ptr_, u64 offset_, u64 size_, bool fixed_, |
| 170 | : ptr(ptr_), offset(offset_), size(size_), fixed(fixed_), big_page(big_page_), | 171 | bool big_page_, bool sparse_alloc_) |
| 171 | sparse_alloc(sparse_alloc_) {} | 172 | : handle(handle_), ptr(ptr_), offset(offset_), size(size_), fixed(fixed_), |
| 173 | big_page(big_page_), sparse_alloc(sparse_alloc_) {} | ||
| 172 | }; | 174 | }; |
| 173 | 175 | ||
| 174 | struct Allocation { | 176 | struct Allocation { |
| @@ -212,9 +214,6 @@ private: | |||
| 212 | bool initialised{}; | 214 | bool initialised{}; |
| 213 | } vm; | 215 | } vm; |
| 214 | std::shared_ptr<Tegra::MemoryManager> gmmu; | 216 | std::shared_ptr<Tegra::MemoryManager> gmmu; |
| 215 | |||
| 216 | // s32 channel{}; | ||
| 217 | // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE}; | ||
| 218 | }; | 217 | }; |
| 219 | 218 | ||
| 220 | } // namespace Service::Nvidia::Devices | 219 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index b8dd34e24..250d01de3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -76,7 +76,7 @@ NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inp | |||
| 76 | return NvResult::NotImplemented; | 76 | return NvResult::NotImplemented; |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | void nvhost_ctrl::OnOpen(DeviceFD fd) {} | 79 | void nvhost_ctrl::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 80 | 80 | ||
| 81 | void nvhost_ctrl::OnClose(DeviceFD fd) {} | 81 | void nvhost_ctrl::OnClose(DeviceFD fd) {} |
| 82 | 82 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 992124b60..403f1a746 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -32,7 +32,7 @@ public: | |||
| 32 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 32 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 33 | std::span<u8> inline_output) override; | 33 | std::span<u8> inline_output) override; |
| 34 | 34 | ||
| 35 | void OnOpen(DeviceFD fd) override; | 35 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 36 | void OnClose(DeviceFD fd) override; | 36 | void OnClose(DeviceFD fd) override; |
| 37 | 37 | ||
| 38 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 38 | Kernel::KEvent* QueryEvent(u32 event_id) override; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 3e0c96456..ddd85678b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -82,7 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> | |||
| 82 | return NvResult::NotImplemented; | 82 | return NvResult::NotImplemented; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} | 85 | void nvhost_ctrl_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 86 | void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} | 86 | void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} |
| 87 | 87 | ||
| 88 | NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { | 88 | NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index d170299bd..d2ab05b21 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | |||
| @@ -28,7 +28,7 @@ public: | |||
| 28 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 28 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 29 | std::span<u8> inline_output) override; | 29 | std::span<u8> inline_output) override; |
| 30 | 30 | ||
| 31 | void OnOpen(DeviceFD fd) override; | 31 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 32 | void OnClose(DeviceFD fd) override; | 32 | void OnClose(DeviceFD fd) override; |
| 33 | 33 | ||
| 34 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 34 | Kernel::KEvent* QueryEvent(u32 event_id) override; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index b0395c2f0..bf12d69a5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -120,7 +120,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 120 | return NvResult::NotImplemented; | 120 | return NvResult::NotImplemented; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | void nvhost_gpu::OnOpen(DeviceFD fd) {} | 123 | void nvhost_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 124 | void nvhost_gpu::OnClose(DeviceFD fd) {} | 124 | void nvhost_gpu::OnClose(DeviceFD fd) {} |
| 125 | 125 | ||
| 126 | NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { | 126 | NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 88fd228ff..e34a978db 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -47,7 +47,7 @@ public: | |||
| 47 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 47 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 48 | std::span<u8> inline_output) override; | 48 | std::span<u8> inline_output) override; |
| 49 | 49 | ||
| 50 | void OnOpen(DeviceFD fd) override; | 50 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 51 | void OnClose(DeviceFD fd) override; | 51 | void OnClose(DeviceFD fd) override; |
| 52 | 52 | ||
| 53 | Kernel::KEvent* QueryEvent(u32 event_id) override; | 53 | Kernel::KEvent* QueryEvent(u32 event_id) override; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index f43914e1b..2c0ac2a46 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -35,7 +35,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 35 | case 0x7: | 35 | case 0x7: |
| 36 | return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); | 36 | return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); |
| 37 | case 0x9: | 37 | case 0x9: |
| 38 | return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output); | 38 | return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output, fd); |
| 39 | case 0xa: | 39 | case 0xa: |
| 40 | return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); | 40 | return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); |
| 41 | default: | 41 | default: |
| @@ -68,9 +68,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 68 | return NvResult::NotImplemented; | 68 | return NvResult::NotImplemented; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void nvhost_nvdec::OnOpen(DeviceFD fd) { | 71 | void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) { |
| 72 | LOG_INFO(Service_NVDRV, "NVDEC video stream started"); | 72 | LOG_INFO(Service_NVDRV, "NVDEC video stream started"); |
| 73 | system.SetNVDECActive(true); | 73 | system.SetNVDECActive(true); |
| 74 | sessions[fd] = session_id; | ||
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | void nvhost_nvdec::OnClose(DeviceFD fd) { | 77 | void nvhost_nvdec::OnClose(DeviceFD fd) { |
| @@ -81,6 +82,10 @@ void nvhost_nvdec::OnClose(DeviceFD fd) { | |||
| 81 | system.GPU().ClearCdmaInstance(iter->second); | 82 | system.GPU().ClearCdmaInstance(iter->second); |
| 82 | } | 83 | } |
| 83 | system.SetNVDECActive(false); | 84 | system.SetNVDECActive(false); |
| 85 | auto it = sessions.find(fd); | ||
| 86 | if (it != sessions.end()) { | ||
| 87 | sessions.erase(it); | ||
| 88 | } | ||
| 84 | } | 89 | } |
| 85 | 90 | ||
| 86 | } // namespace Service::Nvidia::Devices | 91 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index ad2233c49..627686757 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | |||
| @@ -20,7 +20,7 @@ public: | |||
| 20 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 20 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 21 | std::span<u8> inline_output) override; | 21 | std::span<u8> inline_output) override; |
| 22 | 22 | ||
| 23 | void OnOpen(DeviceFD fd) override; | 23 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 24 | void OnClose(DeviceFD fd) override; | 24 | void OnClose(DeviceFD fd) override; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 74c701b95..a0a7bfa40 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/hle/kernel/k_process.h" | ||
| 11 | #include "core/hle/service/nvdrv/core/container.h" | 12 | #include "core/hle/service/nvdrv/core/container.h" |
| 12 | #include "core/hle/service/nvdrv/core/nvmap.h" | 13 | #include "core/hle/service/nvdrv/core/nvmap.h" |
| 13 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 14 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| @@ -95,6 +96,8 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De | |||
| 95 | offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); | 96 | offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); |
| 96 | 97 | ||
| 97 | auto& gpu = system.GPU(); | 98 | auto& gpu = system.GPU(); |
| 99 | auto* session = core.GetSession(sessions[fd]); | ||
| 100 | |||
| 98 | if (gpu.UseNvdec()) { | 101 | if (gpu.UseNvdec()) { |
| 99 | for (std::size_t i = 0; i < syncpt_increments.size(); i++) { | 102 | for (std::size_t i = 0; i < syncpt_increments.size(); i++) { |
| 100 | const SyncptIncr& syncpt_incr = syncpt_increments[i]; | 103 | const SyncptIncr& syncpt_incr = syncpt_increments[i]; |
| @@ -106,8 +109,8 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De | |||
| 106 | const auto object = nvmap.GetHandle(cmd_buffer.memory_id); | 109 | const auto object = nvmap.GetHandle(cmd_buffer.memory_id); |
| 107 | ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); | 110 | ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); |
| 108 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); | 111 | Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); |
| 109 | system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), | 112 | session->process->GetMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), |
| 110 | cmdlist.size() * sizeof(u32)); | 113 | cmdlist.size() * sizeof(u32)); |
| 111 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); | 114 | gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); |
| 112 | } | 115 | } |
| 113 | // Some games expect command_buffers to be written back | 116 | // Some games expect command_buffers to be written back |
| @@ -133,10 +136,12 @@ NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) { | |||
| 133 | return NvResult::Success; | 136 | return NvResult::Success; |
| 134 | } | 137 | } |
| 135 | 138 | ||
| 136 | NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) { | 139 | NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries, |
| 140 | DeviceFD fd) { | ||
| 137 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); | 141 | const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); |
| 138 | for (size_t i = 0; i < num_entries; i++) { | 142 | for (size_t i = 0; i < num_entries; i++) { |
| 139 | entries[i].map_address = nvmap.PinHandle(entries[i].map_handle); | 143 | DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, true); |
| 144 | entries[i].map_address = static_cast<u32>(pin_address); | ||
| 140 | } | 145 | } |
| 141 | 146 | ||
| 142 | return NvResult::Success; | 147 | return NvResult::Success; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 7ce748e18..900db81d2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <deque> | 6 | #include <deque> |
| 7 | #include <unordered_map> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 9 | |||
| 8 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 9 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 10 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | 12 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| @@ -111,7 +113,7 @@ protected: | |||
| 111 | NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); | 113 | NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); |
| 112 | NvResult GetSyncpoint(IoctlGetSyncpoint& params); | 114 | NvResult GetSyncpoint(IoctlGetSyncpoint& params); |
| 113 | NvResult GetWaitbase(IoctlGetWaitbase& params); | 115 | NvResult GetWaitbase(IoctlGetWaitbase& params); |
| 114 | NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); | 116 | NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries, DeviceFD fd); |
| 115 | NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); | 117 | NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); |
| 116 | NvResult SetSubmitTimeout(u32 timeout); | 118 | NvResult SetSubmitTimeout(u32 timeout); |
| 117 | 119 | ||
| @@ -125,6 +127,7 @@ protected: | |||
| 125 | NvCore::NvMap& nvmap; | 127 | NvCore::NvMap& nvmap; |
| 126 | NvCore::ChannelType channel_type; | 128 | NvCore::ChannelType channel_type; |
| 127 | std::array<u32, MaxSyncPoints> device_syncpoints{}; | 129 | std::array<u32, MaxSyncPoints> device_syncpoints{}; |
| 130 | std::unordered_map<DeviceFD, NvCore::SessionId> sessions; | ||
| 128 | }; | 131 | }; |
| 129 | }; // namespace Devices | 132 | }; // namespace Devices |
| 130 | } // namespace Service::Nvidia | 133 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 9e6b86458..f87d53f12 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp | |||
| @@ -44,7 +44,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in | |||
| 44 | return NvResult::NotImplemented; | 44 | return NvResult::NotImplemented; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void nvhost_nvjpg::OnOpen(DeviceFD fd) {} | 47 | void nvhost_nvjpg::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} |
| 48 | void nvhost_nvjpg::OnClose(DeviceFD fd) {} | 48 | void nvhost_nvjpg::OnClose(DeviceFD fd) {} |
| 49 | 49 | ||
| 50 | NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) { | 50 | NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 790c97f6a..def9c254d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h | |||
| @@ -22,7 +22,7 @@ public: | |||
| 22 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 22 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 23 | std::span<u8> inline_output) override; | 23 | std::span<u8> inline_output) override; |
| 24 | 24 | ||
| 25 | void OnOpen(DeviceFD fd) override; | 25 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 26 | void OnClose(DeviceFD fd) override; | 26 | void OnClose(DeviceFD fd) override; |
| 27 | 27 | ||
| 28 | private: | 28 | private: |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 87f8d7c22..bf090f5eb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -33,7 +33,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 33 | case 0x3: | 33 | case 0x3: |
| 34 | return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); | 34 | return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); |
| 35 | case 0x9: | 35 | case 0x9: |
| 36 | return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output); | 36 | return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output, fd); |
| 37 | case 0xa: | 37 | case 0xa: |
| 38 | return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); | 38 | return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); |
| 39 | default: | 39 | default: |
| @@ -68,7 +68,9 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu | |||
| 68 | return NvResult::NotImplemented; | 68 | return NvResult::NotImplemented; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void nvhost_vic::OnOpen(DeviceFD fd) {} | 71 | void nvhost_vic::OnOpen(NvCore::SessionId session_id, DeviceFD fd) { |
| 72 | sessions[fd] = session_id; | ||
| 73 | } | ||
| 72 | 74 | ||
| 73 | void nvhost_vic::OnClose(DeviceFD fd) { | 75 | void nvhost_vic::OnClose(DeviceFD fd) { |
| 74 | auto& host1x_file = core.Host1xDeviceFile(); | 76 | auto& host1x_file = core.Host1xDeviceFile(); |
| @@ -76,6 +78,7 @@ void nvhost_vic::OnClose(DeviceFD fd) { | |||
| 76 | if (iter != host1x_file.fd_to_id.end()) { | 78 | if (iter != host1x_file.fd_to_id.end()) { |
| 77 | system.GPU().ClearCdmaInstance(iter->second); | 79 | system.GPU().ClearCdmaInstance(iter->second); |
| 78 | } | 80 | } |
| 81 | sessions.erase(fd); | ||
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | } // namespace Service::Nvidia::Devices | 84 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index cadbcb0a5..0cc04354a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 19 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 20 | std::span<u8> inline_output) override; | 20 | std::span<u8> inline_output) override; |
| 21 | 21 | ||
| 22 | void OnOpen(DeviceFD fd) override; | 22 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 23 | void OnClose(DeviceFD fd) override; | 23 | void OnClose(DeviceFD fd) override; |
| 24 | }; | 24 | }; |
| 25 | } // namespace Service::Nvidia::Devices | 25 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 71b2e62ec..da61a3bfe 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp | |||
| @@ -36,9 +36,9 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, | |||
| 36 | case 0x3: | 36 | case 0x3: |
| 37 | return WrapFixed(this, &nvmap::IocFromId, input, output); | 37 | return WrapFixed(this, &nvmap::IocFromId, input, output); |
| 38 | case 0x4: | 38 | case 0x4: |
| 39 | return WrapFixed(this, &nvmap::IocAlloc, input, output); | 39 | return WrapFixed(this, &nvmap::IocAlloc, input, output, fd); |
| 40 | case 0x5: | 40 | case 0x5: |
| 41 | return WrapFixed(this, &nvmap::IocFree, input, output); | 41 | return WrapFixed(this, &nvmap::IocFree, input, output, fd); |
| 42 | case 0x9: | 42 | case 0x9: |
| 43 | return WrapFixed(this, &nvmap::IocParam, input, output); | 43 | return WrapFixed(this, &nvmap::IocParam, input, output); |
| 44 | case 0xe: | 44 | case 0xe: |
| @@ -67,8 +67,15 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st | |||
| 67 | return NvResult::NotImplemented; | 67 | return NvResult::NotImplemented; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | void nvmap::OnOpen(DeviceFD fd) {} | 70 | void nvmap::OnOpen(NvCore::SessionId session_id, DeviceFD fd) { |
| 71 | void nvmap::OnClose(DeviceFD fd) {} | 71 | sessions[fd] = session_id; |
| 72 | } | ||
| 73 | void nvmap::OnClose(DeviceFD fd) { | ||
| 74 | auto it = sessions.find(fd); | ||
| 75 | if (it != sessions.end()) { | ||
| 76 | sessions.erase(it); | ||
| 77 | } | ||
| 78 | } | ||
| 72 | 79 | ||
| 73 | NvResult nvmap::IocCreate(IocCreateParams& params) { | 80 | NvResult nvmap::IocCreate(IocCreateParams& params) { |
| 74 | LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); | 81 | LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); |
| @@ -87,7 +94,7 @@ NvResult nvmap::IocCreate(IocCreateParams& params) { | |||
| 87 | return NvResult::Success; | 94 | return NvResult::Success; |
| 88 | } | 95 | } |
| 89 | 96 | ||
| 90 | NvResult nvmap::IocAlloc(IocAllocParams& params) { | 97 | NvResult nvmap::IocAlloc(IocAllocParams& params, DeviceFD fd) { |
| 91 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); | 98 | LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); |
| 92 | 99 | ||
| 93 | if (!params.handle) { | 100 | if (!params.handle) { |
| @@ -116,15 +123,15 @@ NvResult nvmap::IocAlloc(IocAllocParams& params) { | |||
| 116 | return NvResult::InsufficientMemory; | 123 | return NvResult::InsufficientMemory; |
| 117 | } | 124 | } |
| 118 | 125 | ||
| 119 | const auto result = | 126 | const auto result = handle_description->Alloc(params.flags, params.align, params.kind, |
| 120 | handle_description->Alloc(params.flags, params.align, params.kind, params.address); | 127 | params.address, sessions[fd]); |
| 121 | if (result != NvResult::Success) { | 128 | if (result != NvResult::Success) { |
| 122 | LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle); | 129 | LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle); |
| 123 | return result; | 130 | return result; |
| 124 | } | 131 | } |
| 125 | bool is_out_io{}; | 132 | bool is_out_io{}; |
| 126 | ASSERT(system.ApplicationProcess() | 133 | auto process = container.GetSession(sessions[fd])->process; |
| 127 | ->GetPageTable() | 134 | ASSERT(process->GetPageTable() |
| 128 | .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, | 135 | .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, |
| 129 | handle_description->size, | 136 | handle_description->size, |
| 130 | Kernel::KMemoryPermission::None, true, false) | 137 | Kernel::KMemoryPermission::None, true, false) |
| @@ -224,7 +231,7 @@ NvResult nvmap::IocParam(IocParamParams& params) { | |||
| 224 | return NvResult::Success; | 231 | return NvResult::Success; |
| 225 | } | 232 | } |
| 226 | 233 | ||
| 227 | NvResult nvmap::IocFree(IocFreeParams& params) { | 234 | NvResult nvmap::IocFree(IocFreeParams& params, DeviceFD fd) { |
| 228 | LOG_DEBUG(Service_NVDRV, "called"); | 235 | LOG_DEBUG(Service_NVDRV, "called"); |
| 229 | 236 | ||
| 230 | if (!params.handle) { | 237 | if (!params.handle) { |
| @@ -233,9 +240,9 @@ NvResult nvmap::IocFree(IocFreeParams& params) { | |||
| 233 | } | 240 | } |
| 234 | 241 | ||
| 235 | if (auto freeInfo{file.FreeHandle(params.handle, false)}) { | 242 | if (auto freeInfo{file.FreeHandle(params.handle, false)}) { |
| 243 | auto process = container.GetSession(sessions[fd])->process; | ||
| 236 | if (freeInfo->can_unlock) { | 244 | if (freeInfo->can_unlock) { |
| 237 | ASSERT(system.ApplicationProcess() | 245 | ASSERT(process->GetPageTable() |
| 238 | ->GetPageTable() | ||
| 239 | .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) | 246 | .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) |
| 240 | .IsSuccess()); | 247 | .IsSuccess()); |
| 241 | } | 248 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 049c11028..d07d85f88 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -33,7 +33,7 @@ public: | |||
| 33 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, | 33 | NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, |
| 34 | std::span<u8> inline_output) override; | 34 | std::span<u8> inline_output) override; |
| 35 | 35 | ||
| 36 | void OnOpen(DeviceFD fd) override; | 36 | void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; |
| 37 | void OnClose(DeviceFD fd) override; | 37 | void OnClose(DeviceFD fd) override; |
| 38 | 38 | ||
| 39 | enum class HandleParameterType : u32_le { | 39 | enum class HandleParameterType : u32_le { |
| @@ -100,11 +100,11 @@ public: | |||
| 100 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); | 100 | static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); |
| 101 | 101 | ||
| 102 | NvResult IocCreate(IocCreateParams& params); | 102 | NvResult IocCreate(IocCreateParams& params); |
| 103 | NvResult IocAlloc(IocAllocParams& params); | 103 | NvResult IocAlloc(IocAllocParams& params, DeviceFD fd); |
| 104 | NvResult IocGetId(IocGetIdParams& params); | 104 | NvResult IocGetId(IocGetIdParams& params); |
| 105 | NvResult IocFromId(IocFromIdParams& params); | 105 | NvResult IocFromId(IocFromIdParams& params); |
| 106 | NvResult IocParam(IocParamParams& params); | 106 | NvResult IocParam(IocParamParams& params); |
| 107 | NvResult IocFree(IocFreeParams& params); | 107 | NvResult IocFree(IocFreeParams& params, DeviceFD fd); |
| 108 | 108 | ||
| 109 | private: | 109 | private: |
| 110 | /// Id to use for the next handle that is created. | 110 | /// Id to use for the next handle that is created. |
| @@ -115,6 +115,7 @@ private: | |||
| 115 | 115 | ||
| 116 | NvCore::Container& container; | 116 | NvCore::Container& container; |
| 117 | NvCore::NvMap& file; | 117 | NvCore::NvMap& file; |
| 118 | std::unordered_map<DeviceFD, NvCore::SessionId> sessions; | ||
| 118 | }; | 119 | }; |
| 119 | 120 | ||
| 120 | } // namespace Service::Nvidia::Devices | 121 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 9e46ee8dd..cb256e5b4 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -45,13 +45,22 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) { | |||
| 45 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { | 45 | void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { |
| 46 | auto server_manager = std::make_unique<ServerManager>(system); | 46 | auto server_manager = std::make_unique<ServerManager>(system); |
| 47 | auto module = std::make_shared<Module>(system); | 47 | auto module = std::make_shared<Module>(system); |
| 48 | server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv")); | 48 | const auto NvdrvInterfaceFactoryForApplication = [&, module] { |
| 49 | server_manager->RegisterNamedService("nvdrv:a", | 49 | return std::make_shared<NVDRV>(system, module, "nvdrv"); |
| 50 | std::make_shared<NVDRV>(system, module, "nvdrv:a")); | 50 | }; |
| 51 | server_manager->RegisterNamedService("nvdrv:s", | 51 | const auto NvdrvInterfaceFactoryForApplets = [&, module] { |
| 52 | std::make_shared<NVDRV>(system, module, "nvdrv:s")); | 52 | return std::make_shared<NVDRV>(system, module, "nvdrv:a"); |
| 53 | server_manager->RegisterNamedService("nvdrv:t", | 53 | }; |
| 54 | std::make_shared<NVDRV>(system, module, "nvdrv:t")); | 54 | const auto NvdrvInterfaceFactoryForSysmodules = [&, module] { |
| 55 | return std::make_shared<NVDRV>(system, module, "nvdrv:s"); | ||
| 56 | }; | ||
| 57 | const auto NvdrvInterfaceFactoryForTesting = [&, module] { | ||
| 58 | return std::make_shared<NVDRV>(system, module, "nvdrv:t"); | ||
| 59 | }; | ||
| 60 | server_manager->RegisterNamedService("nvdrv", NvdrvInterfaceFactoryForApplication); | ||
| 61 | server_manager->RegisterNamedService("nvdrv:a", NvdrvInterfaceFactoryForApplets); | ||
| 62 | server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules); | ||
| 63 | server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting); | ||
| 55 | server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); | 64 | server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); |
| 56 | nvnflinger.SetNVDrvInstance(module); | 65 | nvnflinger.SetNVDrvInstance(module); |
| 57 | ServerManager::RunServer(std::move(server_manager)); | 66 | ServerManager::RunServer(std::move(server_manager)); |
| @@ -113,7 +122,7 @@ NvResult Module::VerifyFD(DeviceFD fd) const { | |||
| 113 | return NvResult::Success; | 122 | return NvResult::Success; |
| 114 | } | 123 | } |
| 115 | 124 | ||
| 116 | DeviceFD Module::Open(const std::string& device_name) { | 125 | DeviceFD Module::Open(const std::string& device_name, NvCore::SessionId session_id) { |
| 117 | auto it = builders.find(device_name); | 126 | auto it = builders.find(device_name); |
| 118 | if (it == builders.end()) { | 127 | if (it == builders.end()) { |
| 119 | LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name); | 128 | LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name); |
| @@ -124,7 +133,7 @@ DeviceFD Module::Open(const std::string& device_name) { | |||
| 124 | auto& builder = it->second; | 133 | auto& builder = it->second; |
| 125 | auto device = builder(fd)->second; | 134 | auto device = builder(fd)->second; |
| 126 | 135 | ||
| 127 | device->OnOpen(fd); | 136 | device->OnOpen(session_id, fd); |
| 128 | 137 | ||
| 129 | return fd; | 138 | return fd; |
| 130 | } | 139 | } |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index d8622b3ca..c594f0e5e 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -77,7 +77,7 @@ public: | |||
| 77 | NvResult VerifyFD(DeviceFD fd) const; | 77 | NvResult VerifyFD(DeviceFD fd) const; |
| 78 | 78 | ||
| 79 | /// Opens a device node and returns a file descriptor to it. | 79 | /// Opens a device node and returns a file descriptor to it. |
| 80 | DeviceFD Open(const std::string& device_name); | 80 | DeviceFD Open(const std::string& device_name, NvCore::SessionId session_id); |
| 81 | 81 | ||
| 82 | /// Sends an ioctl command to the specified file descriptor. | 82 | /// Sends an ioctl command to the specified file descriptor. |
| 83 | NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output); | 83 | NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output); |
| @@ -93,6 +93,10 @@ public: | |||
| 93 | 93 | ||
| 94 | NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event); | 94 | NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event); |
| 95 | 95 | ||
| 96 | NvCore::Container& GetContainer() { | ||
| 97 | return container; | ||
| 98 | } | ||
| 99 | |||
| 96 | private: | 100 | private: |
| 97 | friend class EventInterface; | 101 | friend class EventInterface; |
| 98 | friend class Service::Nvnflinger::Nvnflinger; | 102 | friend class Service::Nvnflinger::Nvnflinger; |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index c8a880e84..ffe72f281 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp | |||
| @@ -3,8 +3,11 @@ | |||
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later | 3 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/scope_exit.h" | ||
| 7 | #include "common/string_util.h" | ||
| 6 | #include "core/core.h" | 8 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_event.h" | 9 | #include "core/hle/kernel/k_event.h" |
| 10 | #include "core/hle/kernel/k_process.h" | ||
| 8 | #include "core/hle/kernel/k_readable_event.h" | 11 | #include "core/hle/kernel/k_readable_event.h" |
| 9 | #include "core/hle/service/ipc_helpers.h" | 12 | #include "core/hle/service/ipc_helpers.h" |
| 10 | #include "core/hle/service/nvdrv/nvdata.h" | 13 | #include "core/hle/service/nvdrv/nvdata.h" |
| @@ -27,7 +30,7 @@ void NVDRV::Open(HLERequestContext& ctx) { | |||
| 27 | } | 30 | } |
| 28 | 31 | ||
| 29 | const auto& buffer = ctx.ReadBuffer(); | 32 | const auto& buffer = ctx.ReadBuffer(); |
| 30 | const std::string device_name(buffer.begin(), buffer.end()); | 33 | const std::string device_name(Common::StringFromBuffer(buffer)); |
| 31 | 34 | ||
| 32 | if (device_name == "/dev/nvhost-prof-gpu") { | 35 | if (device_name == "/dev/nvhost-prof-gpu") { |
| 33 | rb.Push<DeviceFD>(0); | 36 | rb.Push<DeviceFD>(0); |
| @@ -37,7 +40,7 @@ void NVDRV::Open(HLERequestContext& ctx) { | |||
| 37 | return; | 40 | return; |
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | DeviceFD fd = nvdrv->Open(device_name); | 43 | DeviceFD fd = nvdrv->Open(device_name, session_id); |
| 41 | 44 | ||
| 42 | rb.Push<DeviceFD>(fd); | 45 | rb.Push<DeviceFD>(fd); |
| 43 | rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); | 46 | rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); |
| @@ -150,12 +153,29 @@ void NVDRV::Close(HLERequestContext& ctx) { | |||
| 150 | 153 | ||
| 151 | void NVDRV::Initialize(HLERequestContext& ctx) { | 154 | void NVDRV::Initialize(HLERequestContext& ctx) { |
| 152 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); | 155 | LOG_WARNING(Service_NVDRV, "(STUBBED) called"); |
| 156 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 157 | SCOPE_EXIT({ | ||
| 158 | rb.Push(ResultSuccess); | ||
| 159 | rb.PushEnum(NvResult::Success); | ||
| 160 | }); | ||
| 153 | 161 | ||
| 154 | is_initialized = true; | 162 | if (is_initialized) { |
| 163 | // No need to initialize again | ||
| 164 | return; | ||
| 165 | } | ||
| 155 | 166 | ||
| 156 | IPC::ResponseBuilder rb{ctx, 3}; | 167 | IPC::RequestParser rp{ctx}; |
| 157 | rb.Push(ResultSuccess); | 168 | const auto process_handle{ctx.GetCopyHandle(0)}; |
| 158 | rb.PushEnum(NvResult::Success); | 169 | // The transfer memory is lent to nvdrv as a work buffer since nvdrv is |
| 170 | // unable to allocate as much memory on its own. For HLE it's unnecessary to handle it | ||
| 171 | [[maybe_unused]] const auto transfer_memory_handle{ctx.GetCopyHandle(1)}; | ||
| 172 | [[maybe_unused]] const auto transfer_memory_size = rp.Pop<u32>(); | ||
| 173 | |||
| 174 | auto& container = nvdrv->GetContainer(); | ||
| 175 | auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle); | ||
| 176 | session_id = container.OpenSession(process.GetPointerUnsafe()); | ||
| 177 | |||
| 178 | is_initialized = true; | ||
| 159 | } | 179 | } |
| 160 | 180 | ||
| 161 | void NVDRV::QueryEvent(HLERequestContext& ctx) { | 181 | void NVDRV::QueryEvent(HLERequestContext& ctx) { |
| @@ -242,6 +262,9 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* | |||
| 242 | RegisterHandlers(functions); | 262 | RegisterHandlers(functions); |
| 243 | } | 263 | } |
| 244 | 264 | ||
| 245 | NVDRV::~NVDRV() = default; | 265 | NVDRV::~NVDRV() { |
| 266 | auto& container = nvdrv->GetContainer(); | ||
| 267 | container.CloseSession(session_id); | ||
| 268 | } | ||
| 246 | 269 | ||
| 247 | } // namespace Service::Nvidia | 270 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h index 6e98115dc..f2195ae1e 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.h +++ b/src/core/hle/service/nvdrv/nvdrv_interface.h | |||
| @@ -35,6 +35,7 @@ private: | |||
| 35 | 35 | ||
| 36 | u64 pid{}; | 36 | u64 pid{}; |
| 37 | bool is_initialized{}; | 37 | bool is_initialized{}; |
| 38 | NvCore::SessionId session_id{}; | ||
| 38 | Common::ScratchBuffer<u8> output_buffer; | 39 | Common::ScratchBuffer<u8> output_buffer; |
| 39 | Common::ScratchBuffer<u8> inline_output_buffer; | 40 | Common::ScratchBuffer<u8> inline_output_buffer; |
| 40 | }; | 41 | }; |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp index 2fef6cc1a..86e272b41 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | |||
| @@ -87,19 +87,20 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, | |||
| 87 | R_SUCCEED(); | 87 | R_SUCCEED(); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | 90 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) { |
| 91 | // Free the handle. | 91 | // Free the handle. |
| 92 | Nvidia::Devices::nvmap::IocFreeParams free_params{ | 92 | Nvidia::Devices::nvmap::IocFreeParams free_params{ |
| 93 | .handle = handle, | 93 | .handle = handle, |
| 94 | }; | 94 | }; |
| 95 | R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); | 95 | R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success, |
| 96 | VI::ResultOperationFailed); | ||
| 96 | 97 | ||
| 97 | // We succeeded. | 98 | // We succeeded. |
| 98 | R_SUCCEED(); | 99 | R_SUCCEED(); |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, | 102 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, |
| 102 | u32 size) { | 103 | u32 size, Nvidia::DeviceFD nvmap_fd) { |
| 103 | // Assign the allocated memory to the handle. | 104 | // Assign the allocated memory to the handle. |
| 104 | Nvidia::Devices::nvmap::IocAllocParams alloc_params{ | 105 | Nvidia::Devices::nvmap::IocAllocParams alloc_params{ |
| 105 | .handle = handle, | 106 | .handle = handle, |
| @@ -109,16 +110,16 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce | |||
| 109 | .kind = 0, | 110 | .kind = 0, |
| 110 | .address = GetInteger(buffer), | 111 | .address = GetInteger(buffer), |
| 111 | }; | 112 | }; |
| 112 | R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); | 113 | R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success, |
| 114 | VI::ResultOperationFailed); | ||
| 113 | 115 | ||
| 114 | // We succeeded. | 116 | // We succeeded. |
| 115 | R_SUCCEED(); | 117 | R_SUCCEED(); |
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, | 120 | Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd, |
| 119 | Common::ProcessAddress buffer, u32 size) { | 121 | Common::ProcessAddress buffer, u32 size) { |
| 120 | // Get the nvmap device. | 122 | // Get the nvmap device. |
| 121 | auto nvmap_fd = nvdrv.Open("/dev/nvmap"); | ||
| 122 | auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); | 123 | auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); |
| 123 | ASSERT(nvmap != nullptr); | 124 | ASSERT(nvmap != nullptr); |
| 124 | 125 | ||
| @@ -127,11 +128,11 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, | |||
| 127 | 128 | ||
| 128 | // Ensure we maintain a clean state on failure. | 129 | // Ensure we maintain a clean state on failure. |
| 129 | ON_RESULT_FAILURE { | 130 | ON_RESULT_FAILURE { |
| 130 | ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle))); | 131 | ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd))); |
| 131 | }; | 132 | }; |
| 132 | 133 | ||
| 133 | // Assign the allocated memory to the handle. | 134 | // Assign the allocated memory to the handle. |
| 134 | R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size)); | 135 | R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd)); |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; | 138 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; |
| @@ -197,9 +198,13 @@ Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u | |||
| 197 | std::addressof(m_buffer_page_group), m_system, | 198 | std::addressof(m_buffer_page_group), m_system, |
| 198 | SharedBufferSize)); | 199 | SharedBufferSize)); |
| 199 | 200 | ||
| 201 | auto& container = m_nvdrv->GetContainer(); | ||
| 202 | m_session_id = container.OpenSession(m_system.ApplicationProcess()); | ||
| 203 | m_nvmap_fd = m_nvdrv->Open("/dev/nvmap", m_session_id); | ||
| 204 | |||
| 200 | // Create an nvmap handle for the buffer and assign the memory to it. | 205 | // Create an nvmap handle for the buffer and assign the memory to it. |
| 201 | R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, map_address, | 206 | R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, m_nvmap_fd, |
| 202 | SharedBufferSize)); | 207 | map_address, SharedBufferSize)); |
| 203 | 208 | ||
| 204 | // Record the display id. | 209 | // Record the display id. |
| 205 | m_display_id = display_id; | 210 | m_display_id = display_id; |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h index c809c01b4..033bf4bbe 100644 --- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/math_util.h" | 6 | #include "common/math_util.h" |
| 7 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 8 | #include "core/hle/service/nvdrv/nvdata.h" | ||
| 7 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 9 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 8 | #include "core/hle/service/nvnflinger/ui/fence.h" | 10 | #include "core/hle/service/nvnflinger/ui/fence.h" |
| 9 | 11 | ||
| @@ -53,7 +55,8 @@ private: | |||
| 53 | u64 m_layer_id = 0; | 55 | u64 m_layer_id = 0; |
| 54 | u32 m_buffer_nvmap_handle = 0; | 56 | u32 m_buffer_nvmap_handle = 0; |
| 55 | SharedMemoryPoolLayout m_pool_layout = {}; | 57 | SharedMemoryPoolLayout m_pool_layout = {}; |
| 56 | 58 | Nvidia::DeviceFD m_nvmap_fd = {}; | |
| 59 | Nvidia::NvCore::SessionId m_session_id = {}; | ||
| 57 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; | 60 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; |
| 58 | 61 | ||
| 59 | std::mutex m_guard; | 62 | std::mutex m_guard; |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 0469110e8..71d6fdb0c 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -112,9 +112,7 @@ void Nvnflinger::ShutdownLayers() { | |||
| 112 | { | 112 | { |
| 113 | const auto lock_guard = Lock(); | 113 | const auto lock_guard = Lock(); |
| 114 | for (auto& display : displays) { | 114 | for (auto& display : displays) { |
| 115 | for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { | 115 | display.Abandon(); |
| 116 | display.GetLayer(layer).GetConsumer().Abandon(); | ||
| 117 | } | ||
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | is_abandoned = true; | 118 | is_abandoned = true; |
| @@ -126,7 +124,7 @@ void Nvnflinger::ShutdownLayers() { | |||
| 126 | 124 | ||
| 127 | void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { | 125 | void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { |
| 128 | nvdrv = std::move(instance); | 126 | nvdrv = std::move(instance); |
| 129 | disp_fd = nvdrv->Open("/dev/nvdisp_disp0"); | 127 | disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); |
| 130 | } | 128 | } |
| 131 | 129 | ||
| 132 | std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { | 130 | std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { |
| @@ -176,24 +174,28 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | |||
| 176 | display.CreateLayer(layer_id, buffer_id, nvdrv->container); | 174 | display.CreateLayer(layer_id, buffer_id, nvdrv->container); |
| 177 | } | 175 | } |
| 178 | 176 | ||
| 179 | void Nvnflinger::OpenLayer(u64 layer_id) { | 177 | bool Nvnflinger::OpenLayer(u64 layer_id) { |
| 180 | const auto lock_guard = Lock(); | 178 | const auto lock_guard = Lock(); |
| 181 | 179 | ||
| 182 | for (auto& display : displays) { | 180 | for (auto& display : displays) { |
| 183 | if (auto* layer = display.FindLayer(layer_id); layer) { | 181 | if (auto* layer = display.FindLayer(layer_id); layer) { |
| 184 | layer->Open(); | 182 | return layer->Open(); |
| 185 | } | 183 | } |
| 186 | } | 184 | } |
| 185 | |||
| 186 | return false; | ||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | void Nvnflinger::CloseLayer(u64 layer_id) { | 189 | bool Nvnflinger::CloseLayer(u64 layer_id) { |
| 190 | const auto lock_guard = Lock(); | 190 | const auto lock_guard = Lock(); |
| 191 | 191 | ||
| 192 | for (auto& display : displays) { | 192 | for (auto& display : displays) { |
| 193 | if (auto* layer = display.FindLayer(layer_id); layer) { | 193 | if (auto* layer = display.FindLayer(layer_id); layer) { |
| 194 | layer->Close(); | 194 | return layer->Close(); |
| 195 | } | 195 | } |
| 196 | } | 196 | } |
| 197 | |||
| 198 | return false; | ||
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | void Nvnflinger::DestroyLayer(u64 layer_id) { | 201 | void Nvnflinger::DestroyLayer(u64 layer_id) { |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 871285764..a60e0ae6b 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -74,10 +74,10 @@ public: | |||
| 74 | [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); | 74 | [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); |
| 75 | 75 | ||
| 76 | /// Opens a layer on all displays for the given layer ID. | 76 | /// Opens a layer on all displays for the given layer ID. |
| 77 | void OpenLayer(u64 layer_id); | 77 | bool OpenLayer(u64 layer_id); |
| 78 | 78 | ||
| 79 | /// Closes a layer on all displays for the given layer ID. | 79 | /// Closes a layer on all displays for the given layer ID. |
| 80 | void CloseLayer(u64 layer_id); | 80 | bool CloseLayer(u64 layer_id); |
| 81 | 81 | ||
| 82 | /// Destroys the given layer ID. | 82 | /// Destroys the given layer ID. |
| 83 | void DestroyLayer(u64 layer_id); | 83 | void DestroyLayer(u64 layer_id); |
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp index ce70946ec..ede2a1193 100644 --- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp | |||
| @@ -22,11 +22,13 @@ GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap, | |||
| 22 | : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) { | 22 | : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) { |
| 23 | if (this->BufferId() > 0) { | 23 | if (this->BufferId() > 0) { |
| 24 | m_nvmap->DuplicateHandle(this->BufferId(), true); | 24 | m_nvmap->DuplicateHandle(this->BufferId(), true); |
| 25 | m_nvmap->PinHandle(this->BufferId(), false); | ||
| 25 | } | 26 | } |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | GraphicBuffer::~GraphicBuffer() { | 29 | GraphicBuffer::~GraphicBuffer() { |
| 29 | if (m_nvmap != nullptr && this->BufferId() > 0) { | 30 | if (m_nvmap != nullptr && this->BufferId() > 0) { |
| 31 | m_nvmap->UnpinHandle(this->BufferId()); | ||
| 30 | m_nvmap->FreeHandle(this->BufferId(), true); | 32 | m_nvmap->FreeHandle(this->BufferId(), true); |
| 31 | } | 33 | } |
| 32 | } | 34 | } |
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 688c54b58..f40a1c8f3 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -709,12 +709,12 @@ void ISystemSettingsServer::GetSettingsItemValueSize(HLERequestContext& ctx) { | |||
| 709 | // The category of the setting. This corresponds to the top-level keys of | 709 | // The category of the setting. This corresponds to the top-level keys of |
| 710 | // system_settings.ini. | 710 | // system_settings.ini. |
| 711 | const auto setting_category_buf{ctx.ReadBuffer(0)}; | 711 | const auto setting_category_buf{ctx.ReadBuffer(0)}; |
| 712 | const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; | 712 | const std::string setting_category{Common::StringFromBuffer(setting_category_buf)}; |
| 713 | 713 | ||
| 714 | // The name of the setting. This corresponds to the second-level keys of | 714 | // The name of the setting. This corresponds to the second-level keys of |
| 715 | // system_settings.ini. | 715 | // system_settings.ini. |
| 716 | const auto setting_name_buf{ctx.ReadBuffer(1)}; | 716 | const auto setting_name_buf{ctx.ReadBuffer(1)}; |
| 717 | const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; | 717 | const std::string setting_name{Common::StringFromBuffer(setting_name_buf)}; |
| 718 | 718 | ||
| 719 | auto settings{GetSettings()}; | 719 | auto settings{GetSettings()}; |
| 720 | u64 response_size{0}; | 720 | u64 response_size{0}; |
| @@ -732,12 +732,12 @@ void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) { | |||
| 732 | // The category of the setting. This corresponds to the top-level keys of | 732 | // The category of the setting. This corresponds to the top-level keys of |
| 733 | // system_settings.ini. | 733 | // system_settings.ini. |
| 734 | const auto setting_category_buf{ctx.ReadBuffer(0)}; | 734 | const auto setting_category_buf{ctx.ReadBuffer(0)}; |
| 735 | const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; | 735 | const std::string setting_category{Common::StringFromBuffer(setting_category_buf)}; |
| 736 | 736 | ||
| 737 | // The name of the setting. This corresponds to the second-level keys of | 737 | // The name of the setting. This corresponds to the second-level keys of |
| 738 | // system_settings.ini. | 738 | // system_settings.ini. |
| 739 | const auto setting_name_buf{ctx.ReadBuffer(1)}; | 739 | const auto setting_name_buf{ctx.ReadBuffer(1)}; |
| 740 | const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; | 740 | const std::string setting_name{Common::StringFromBuffer(setting_name_buf)}; |
| 741 | 741 | ||
| 742 | std::vector<u8> value; | 742 | std::vector<u8> value; |
| 743 | auto response = GetSettingsItemValue(value, setting_category, setting_name); | 743 | auto response = GetSettingsItemValue(value, setting_category, setting_name); |
| @@ -1036,6 +1036,11 @@ void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) { | |||
| 1036 | } | 1036 | } |
| 1037 | 1037 | ||
| 1038 | void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { | 1038 | void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { |
| 1039 | if (m_system_settings.mii_author_id.IsInvalid()) { | ||
| 1040 | m_system_settings.mii_author_id = Common::UUID::MakeDefault(); | ||
| 1041 | SetSaveNeeded(); | ||
| 1042 | } | ||
| 1043 | |||
| 1039 | LOG_INFO(Service_SET, "called, author_id={}", | 1044 | LOG_INFO(Service_SET, "called, author_id={}", |
| 1040 | m_system_settings.mii_author_id.FormattedString()); | 1045 | m_system_settings.mii_author_id.FormattedString()); |
| 1041 | 1046 | ||
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index e2d9cd98a..725311c53 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -91,6 +91,10 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id, | |||
| 91 | layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, | 91 | layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, |
| 92 | std::move(buffer_item_consumer))); | 92 | std::move(buffer_item_consumer))); |
| 93 | 93 | ||
| 94 | if (is_abandoned) { | ||
| 95 | this->FindLayer(layer_id)->GetConsumer().Abandon(); | ||
| 96 | } | ||
| 97 | |||
| 94 | hos_binder_driver_server.RegisterProducer(std::move(producer)); | 98 | hos_binder_driver_server.RegisterProducer(std::move(producer)); |
| 95 | } | 99 | } |
| 96 | 100 | ||
| @@ -103,6 +107,13 @@ void Display::DestroyLayer(u64 layer_id) { | |||
| 103 | [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); | 107 | [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); |
| 104 | } | 108 | } |
| 105 | 109 | ||
| 110 | void Display::Abandon() { | ||
| 111 | for (auto& layer : layers) { | ||
| 112 | layer->GetConsumer().Abandon(); | ||
| 113 | } | ||
| 114 | is_abandoned = true; | ||
| 115 | } | ||
| 116 | |||
| 106 | Layer* Display::FindLayer(u64 layer_id) { | 117 | Layer* Display::FindLayer(u64 layer_id) { |
| 107 | const auto itr = | 118 | const auto itr = |
| 108 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { | 119 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 7e68ee79b..8eb8a5155 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -98,6 +98,8 @@ public: | |||
| 98 | layers.clear(); | 98 | layers.clear(); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void Abandon(); | ||
| 102 | |||
| 101 | /// Attempts to find a layer with the given ID. | 103 | /// Attempts to find a layer with the given ID. |
| 102 | /// | 104 | /// |
| 103 | /// @param layer_id The layer ID. | 105 | /// @param layer_id The layer ID. |
| @@ -124,6 +126,7 @@ private: | |||
| 124 | 126 | ||
| 125 | std::vector<std::unique_ptr<Layer>> layers; | 127 | std::vector<std::unique_ptr<Layer>> layers; |
| 126 | Kernel::KEvent* vsync_event{}; | 128 | Kernel::KEvent* vsync_event{}; |
| 129 | bool is_abandoned{}; | ||
| 127 | }; | 130 | }; |
| 128 | 131 | ||
| 129 | } // namespace Service::VI | 132 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index 295005e23..f95e2dc71 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <utility> | ||
| 7 | 8 | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | 10 | ||
| @@ -75,12 +76,12 @@ public: | |||
| 75 | return open; | 76 | return open; |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | void Close() { | 79 | bool Close() { |
| 79 | open = false; | 80 | return std::exchange(open, false); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | void Open() { | 83 | bool Open() { |
| 83 | open = true; | 84 | return !std::exchange(open, true); |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | private: | 87 | private: |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 39d5be90d..1f3d82c57 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "common/math_util.h" | 16 | #include "common/math_util.h" |
| 17 | #include "common/settings.h" | 17 | #include "common/settings.h" |
| 18 | #include "common/string_util.h" | ||
| 18 | #include "common/swap.h" | 19 | #include "common/swap.h" |
| 19 | #include "core/core_timing.h" | 20 | #include "core/core_timing.h" |
| 20 | #include "core/hle/kernel/k_readable_event.h" | 21 | #include "core/hle/kernel/k_readable_event.h" |
| @@ -694,9 +695,7 @@ private: | |||
| 694 | void OpenLayer(HLERequestContext& ctx) { | 695 | void OpenLayer(HLERequestContext& ctx) { |
| 695 | IPC::RequestParser rp{ctx}; | 696 | IPC::RequestParser rp{ctx}; |
| 696 | const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); | 697 | const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); |
| 697 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | 698 | const std::string display_name(Common::StringFromBuffer(name_buf)); |
| 698 | |||
| 699 | const std::string display_name(name_buf.begin(), end); | ||
| 700 | 699 | ||
| 701 | const u64 layer_id = rp.Pop<u64>(); | 700 | const u64 layer_id = rp.Pop<u64>(); |
| 702 | const u64 aruid = rp.Pop<u64>(); | 701 | const u64 aruid = rp.Pop<u64>(); |
| @@ -719,7 +718,12 @@ private: | |||
| 719 | return; | 718 | return; |
| 720 | } | 719 | } |
| 721 | 720 | ||
| 722 | nvnflinger.OpenLayer(layer_id); | 721 | if (!nvnflinger.OpenLayer(layer_id)) { |
| 722 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||
| 723 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 724 | rb.Push(ResultOperationFailed); | ||
| 725 | return; | ||
| 726 | } | ||
| 723 | 727 | ||
| 724 | android::OutputParcel parcel; | 728 | android::OutputParcel parcel; |
| 725 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 729 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); |
| @@ -737,7 +741,12 @@ private: | |||
| 737 | 741 | ||
| 738 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | 742 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); |
| 739 | 743 | ||
| 740 | nvnflinger.CloseLayer(layer_id); | 744 | if (!nvnflinger.CloseLayer(layer_id)) { |
| 745 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||
| 746 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 747 | rb.Push(ResultOperationFailed); | ||
| 748 | return; | ||
| 749 | } | ||
| 741 | 750 | ||
| 742 | IPC::ResponseBuilder rb{ctx, 2}; | 751 | IPC::ResponseBuilder rb{ctx, 2}; |
| 743 | rb.Push(ResultSuccess); | 752 | rb.Push(ResultSuccess); |
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 28116ff3a..3016d5f25 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/file_sys/nca_metadata.h" | 10 | #include "core/file_sys/nca_metadata.h" |
| 11 | #include "core/file_sys/patch_manager.h" | 11 | #include "core/file_sys/patch_manager.h" |
| 12 | #include "core/file_sys/registered_cache.h" | 12 | #include "core/file_sys/registered_cache.h" |
| 13 | #include "core/file_sys/romfs_factory.h" | ||
| 13 | #include "core/file_sys/submission_package.h" | 14 | #include "core/file_sys/submission_package.h" |
| 14 | #include "core/hle/kernel/k_process.h" | 15 | #include "core/hle/kernel/k_process.h" |
| 15 | #include "core/hle/service/filesystem/filesystem.h" | 16 | #include "core/hle/service/filesystem/filesystem.h" |
| @@ -109,6 +110,13 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S | |||
| 109 | return result; | 110 | return result; |
| 110 | } | 111 | } |
| 111 | 112 | ||
| 113 | if (nsp->IsExtractedType()) { | ||
| 114 | system.GetFileSystemController().RegisterProcess( | ||
| 115 | process.GetProcessId(), {}, | ||
| 116 | std::make_shared<FileSys::RomFSFactory>(*this, system.GetContentProvider(), | ||
| 117 | system.GetFileSystemController())); | ||
| 118 | } | ||
| 119 | |||
| 112 | FileSys::VirtualFile update_raw; | 120 | FileSys::VirtualFile update_raw; |
| 113 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { | 121 | if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { |
| 114 | system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(), | 122 | system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(), |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8176a41be..1c218566f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include "core/hle/kernel/k_process.h" | 24 | #include "core/hle/kernel/k_process.h" |
| 25 | #include "core/memory.h" | 25 | #include "core/memory.h" |
| 26 | #include "video_core/gpu.h" | 26 | #include "video_core/gpu.h" |
| 27 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 28 | #include "video_core/host1x/host1x.h" | ||
| 27 | #include "video_core/rasterizer_download_area.h" | 29 | #include "video_core/rasterizer_download_area.h" |
| 28 | 30 | ||
| 29 | namespace Core::Memory { | 31 | namespace Core::Memory { |
| @@ -637,17 +639,6 @@ struct Memory::Impl { | |||
| 637 | LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", GetInteger(target), | 639 | LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", GetInteger(target), |
| 638 | base * YUZU_PAGESIZE, (base + size) * YUZU_PAGESIZE); | 640 | base * YUZU_PAGESIZE, (base + size) * YUZU_PAGESIZE); |
| 639 | 641 | ||
| 640 | // During boot, current_page_table might not be set yet, in which case we need not flush | ||
| 641 | if (system.IsPoweredOn()) { | ||
| 642 | auto& gpu = system.GPU(); | ||
| 643 | for (u64 i = 0; i < size; i++) { | ||
| 644 | const auto page = base + i; | ||
| 645 | if (page_table.pointers[page].Type() == Common::PageType::RasterizerCachedMemory) { | ||
| 646 | gpu.FlushAndInvalidateRegion(page << YUZU_PAGEBITS, YUZU_PAGESIZE); | ||
| 647 | } | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 651 | const auto end = base + size; | 642 | const auto end = base + size; |
| 652 | ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", | 643 | ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", |
| 653 | base + page_table.pointers.size()); | 644 | base + page_table.pointers.size()); |
| @@ -811,21 +802,33 @@ struct Memory::Impl { | |||
| 811 | return true; | 802 | return true; |
| 812 | } | 803 | } |
| 813 | 804 | ||
| 814 | void HandleRasterizerDownload(VAddr address, size_t size) { | 805 | void HandleRasterizerDownload(VAddr v_address, size_t size) { |
| 806 | const auto* p = GetPointerImpl( | ||
| 807 | v_address, []() {}, []() {}); | ||
| 808 | if (!gpu_device_memory) [[unlikely]] { | ||
| 809 | gpu_device_memory = &system.Host1x().MemoryManager(); | ||
| 810 | } | ||
| 815 | const size_t core = system.GetCurrentHostThreadID(); | 811 | const size_t core = system.GetCurrentHostThreadID(); |
| 816 | auto& current_area = rasterizer_read_areas[core]; | 812 | auto& current_area = rasterizer_read_areas[core]; |
| 817 | const VAddr end_address = address + size; | 813 | gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) { |
| 818 | if (current_area.start_address <= address && end_address <= current_area.end_address) | 814 | const DAddr end_address = address + size; |
| 819 | [[likely]] { | 815 | if (current_area.start_address <= address && end_address <= current_area.end_address) |
| 820 | return; | 816 | [[likely]] { |
| 821 | } | 817 | return; |
| 822 | current_area = system.GPU().OnCPURead(address, size); | 818 | } |
| 819 | current_area = system.GPU().OnCPURead(address, size); | ||
| 820 | }); | ||
| 823 | } | 821 | } |
| 824 | 822 | ||
| 825 | void HandleRasterizerWrite(VAddr address, size_t size) { | 823 | void HandleRasterizerWrite(VAddr v_address, size_t size) { |
| 824 | const auto* p = GetPointerImpl( | ||
| 825 | v_address, []() {}, []() {}); | ||
| 826 | constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; | 826 | constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; |
| 827 | const size_t core = std::min(system.GetCurrentHostThreadID(), | 827 | const size_t core = std::min(system.GetCurrentHostThreadID(), |
| 828 | sys_core); // any other calls threads go to syscore. | 828 | sys_core); // any other calls threads go to syscore. |
| 829 | if (!gpu_device_memory) [[unlikely]] { | ||
| 830 | gpu_device_memory = &system.Host1x().MemoryManager(); | ||
| 831 | } | ||
| 829 | // Guard on sys_core; | 832 | // Guard on sys_core; |
| 830 | if (core == sys_core) [[unlikely]] { | 833 | if (core == sys_core) [[unlikely]] { |
| 831 | sys_core_guard.lock(); | 834 | sys_core_guard.lock(); |
| @@ -835,36 +838,53 @@ struct Memory::Impl { | |||
| 835 | sys_core_guard.unlock(); | 838 | sys_core_guard.unlock(); |
| 836 | } | 839 | } |
| 837 | }); | 840 | }); |
| 838 | auto& current_area = rasterizer_write_areas[core]; | 841 | gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) { |
| 839 | VAddr subaddress = address >> YUZU_PAGEBITS; | 842 | auto& current_area = rasterizer_write_areas[core]; |
| 840 | bool do_collection = current_area.last_address == subaddress; | 843 | PAddr subaddress = address >> YUZU_PAGEBITS; |
| 841 | if (!do_collection) [[unlikely]] { | 844 | bool do_collection = current_area.last_address == subaddress; |
| 842 | do_collection = system.GPU().OnCPUWrite(address, size); | 845 | if (!do_collection) [[unlikely]] { |
| 843 | if (!do_collection) { | 846 | do_collection = system.GPU().OnCPUWrite(address, size); |
| 844 | return; | 847 | if (!do_collection) { |
| 848 | return; | ||
| 849 | } | ||
| 850 | current_area.last_address = subaddress; | ||
| 845 | } | 851 | } |
| 846 | current_area.last_address = subaddress; | 852 | gpu_dirty_managers[core].Collect(address, size); |
| 847 | } | 853 | }); |
| 848 | gpu_dirty_managers[core].Collect(address, size); | ||
| 849 | } | 854 | } |
| 850 | 855 | ||
| 851 | struct GPUDirtyState { | 856 | struct GPUDirtyState { |
| 852 | VAddr last_address; | 857 | PAddr last_address; |
| 853 | }; | 858 | }; |
| 854 | 859 | ||
| 855 | void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size) { | 860 | void InvalidateGPUMemory(u8* p, size_t size) { |
| 856 | system.GPU().InvalidateRegion(GetInteger(dest_addr), size); | 861 | constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; |
| 857 | } | 862 | const size_t core = std::min(system.GetCurrentHostThreadID(), |
| 858 | 863 | sys_core); // any other calls threads go to syscore. | |
| 859 | void FlushRegion(Common::ProcessAddress dest_addr, size_t size) { | 864 | if (!gpu_device_memory) [[unlikely]] { |
| 860 | system.GPU().FlushRegion(GetInteger(dest_addr), size); | 865 | gpu_device_memory = &system.Host1x().MemoryManager(); |
| 866 | } | ||
| 867 | // Guard on sys_core; | ||
| 868 | if (core == sys_core) [[unlikely]] { | ||
| 869 | sys_core_guard.lock(); | ||
| 870 | } | ||
| 871 | SCOPE_EXIT({ | ||
| 872 | if (core == sys_core) [[unlikely]] { | ||
| 873 | sys_core_guard.unlock(); | ||
| 874 | } | ||
| 875 | }); | ||
| 876 | auto& gpu = system.GPU(); | ||
| 877 | gpu_device_memory->ApplyOpOnPointer( | ||
| 878 | p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size); }); | ||
| 861 | } | 879 | } |
| 862 | 880 | ||
| 863 | Core::System& system; | 881 | Core::System& system; |
| 882 | Tegra::MaxwellDeviceMemoryManager* gpu_device_memory{}; | ||
| 864 | Common::PageTable* current_page_table = nullptr; | 883 | Common::PageTable* current_page_table = nullptr; |
| 865 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> | 884 | std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> |
| 866 | rasterizer_read_areas{}; | 885 | rasterizer_read_areas{}; |
| 867 | std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; | 886 | std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; |
| 887 | std::array<Common::ScratchBuffer<u32>, Core::Hardware::NUM_CPU_CORES> scratch_buffers{}; | ||
| 868 | std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; | 888 | std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; |
| 869 | std::mutex sys_core_guard; | 889 | std::mutex sys_core_guard; |
| 870 | 890 | ||
| @@ -1059,14 +1079,6 @@ void Memory::MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug) | |||
| 1059 | impl->MarkRegionDebug(GetInteger(vaddr), size, debug); | 1079 | impl->MarkRegionDebug(GetInteger(vaddr), size, debug); |
| 1060 | } | 1080 | } |
| 1061 | 1081 | ||
| 1062 | void Memory::InvalidateRegion(Common::ProcessAddress dest_addr, size_t size) { | ||
| 1063 | impl->InvalidateRegion(dest_addr, size); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | void Memory::FlushRegion(Common::ProcessAddress dest_addr, size_t size) { | ||
| 1067 | impl->FlushRegion(dest_addr, size); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { | 1082 | bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { |
| 1071 | [[maybe_unused]] bool mapped = true; | 1083 | [[maybe_unused]] bool mapped = true; |
| 1072 | [[maybe_unused]] bool rasterizer = false; | 1084 | [[maybe_unused]] bool rasterizer = false; |
| @@ -1078,10 +1090,10 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { | |||
| 1078 | GetInteger(vaddr)); | 1090 | GetInteger(vaddr)); |
| 1079 | mapped = false; | 1091 | mapped = false; |
| 1080 | }, | 1092 | }, |
| 1081 | [&] { | 1093 | [&] { rasterizer = true; }); |
| 1082 | impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); | 1094 | if (rasterizer) { |
| 1083 | rasterizer = true; | 1095 | impl->InvalidateGPUMemory(ptr, size); |
| 1084 | }); | 1096 | } |
| 1085 | 1097 | ||
| 1086 | #ifdef __linux__ | 1098 | #ifdef __linux__ |
| 1087 | if (!rasterizer && mapped) { | 1099 | if (!rasterizer && mapped) { |
diff --git a/src/core/memory.h b/src/core/memory.h index dddfaf4a4..f7e6b297f 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/scratch_buffer.h" | 13 | #include "common/scratch_buffer.h" |
| 14 | #include "common/typed_address.h" | 14 | #include "common/typed_address.h" |
| 15 | #include "core/guest_memory.h" | ||
| 15 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| 16 | 17 | ||
| 17 | namespace Common { | 18 | namespace Common { |
| @@ -486,10 +487,10 @@ public: | |||
| 486 | void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); | 487 | void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); |
| 487 | 488 | ||
| 488 | void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers); | 489 | void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers); |
| 489 | void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size); | 490 | |
| 490 | bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); | 491 | bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); |
| 492 | |||
| 491 | bool InvalidateSeparateHeap(void* fault_address); | 493 | bool InvalidateSeparateHeap(void* fault_address); |
| 492 | void FlushRegion(Common::ProcessAddress dest_addr, size_t size); | ||
| 493 | 494 | ||
| 494 | private: | 495 | private: |
| 495 | Core::System& system; | 496 | Core::System& system; |
| @@ -498,209 +499,9 @@ private: | |||
| 498 | std::unique_ptr<Impl> impl; | 499 | std::unique_ptr<Impl> impl; |
| 499 | }; | 500 | }; |
| 500 | 501 | ||
| 501 | enum GuestMemoryFlags : u32 { | ||
| 502 | Read = 1 << 0, | ||
| 503 | Write = 1 << 1, | ||
| 504 | Safe = 1 << 2, | ||
| 505 | Cached = 1 << 3, | ||
| 506 | |||
| 507 | SafeRead = Read | Safe, | ||
| 508 | SafeWrite = Write | Safe, | ||
| 509 | SafeReadWrite = SafeRead | SafeWrite, | ||
| 510 | SafeReadCachedWrite = SafeReadWrite | Cached, | ||
| 511 | |||
| 512 | UnsafeRead = Read, | ||
| 513 | UnsafeWrite = Write, | ||
| 514 | UnsafeReadWrite = UnsafeRead | UnsafeWrite, | ||
| 515 | UnsafeReadCachedWrite = UnsafeReadWrite | Cached, | ||
| 516 | }; | ||
| 517 | |||
| 518 | namespace { | ||
| 519 | template <typename M, typename T, GuestMemoryFlags FLAGS> | ||
| 520 | class GuestMemory { | ||
| 521 | using iterator = T*; | ||
| 522 | using const_iterator = const T*; | ||
| 523 | using value_type = T; | ||
| 524 | using element_type = T; | ||
| 525 | using iterator_category = std::contiguous_iterator_tag; | ||
| 526 | |||
| 527 | public: | ||
| 528 | GuestMemory() = delete; | ||
| 529 | explicit GuestMemory(M& memory, u64 addr, std::size_t size, | ||
| 530 | Common::ScratchBuffer<T>* backup = nullptr) | ||
| 531 | : m_memory{memory}, m_addr{addr}, m_size{size} { | ||
| 532 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); | ||
| 533 | if constexpr (FLAGS & GuestMemoryFlags::Read) { | ||
| 534 | Read(addr, size, backup); | ||
| 535 | } | ||
| 536 | } | ||
| 537 | |||
| 538 | ~GuestMemory() = default; | ||
| 539 | |||
| 540 | T* data() noexcept { | ||
| 541 | return m_data_span.data(); | ||
| 542 | } | ||
| 543 | |||
| 544 | const T* data() const noexcept { | ||
| 545 | return m_data_span.data(); | ||
| 546 | } | ||
| 547 | |||
| 548 | size_t size() const noexcept { | ||
| 549 | return m_size; | ||
| 550 | } | ||
| 551 | |||
| 552 | size_t size_bytes() const noexcept { | ||
| 553 | return this->size() * sizeof(T); | ||
| 554 | } | ||
| 555 | |||
| 556 | [[nodiscard]] T* begin() noexcept { | ||
| 557 | return this->data(); | ||
| 558 | } | ||
| 559 | |||
| 560 | [[nodiscard]] const T* begin() const noexcept { | ||
| 561 | return this->data(); | ||
| 562 | } | ||
| 563 | |||
| 564 | [[nodiscard]] T* end() noexcept { | ||
| 565 | return this->data() + this->size(); | ||
| 566 | } | ||
| 567 | |||
| 568 | [[nodiscard]] const T* end() const noexcept { | ||
| 569 | return this->data() + this->size(); | ||
| 570 | } | ||
| 571 | |||
| 572 | T& operator[](size_t index) noexcept { | ||
| 573 | return m_data_span[index]; | ||
| 574 | } | ||
| 575 | |||
| 576 | const T& operator[](size_t index) const noexcept { | ||
| 577 | return m_data_span[index]; | ||
| 578 | } | ||
| 579 | |||
| 580 | void SetAddressAndSize(u64 addr, std::size_t size) noexcept { | ||
| 581 | m_addr = addr; | ||
| 582 | m_size = size; | ||
| 583 | m_addr_changed = true; | ||
| 584 | } | ||
| 585 | |||
| 586 | std::span<T> Read(u64 addr, std::size_t size, | ||
| 587 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { | ||
| 588 | m_addr = addr; | ||
| 589 | m_size = size; | ||
| 590 | if (m_size == 0) { | ||
| 591 | m_is_data_copy = true; | ||
| 592 | return {}; | ||
| 593 | } | ||
| 594 | |||
| 595 | if (this->TrySetSpan()) { | ||
| 596 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 597 | m_memory.FlushRegion(m_addr, this->size_bytes()); | ||
| 598 | } | ||
| 599 | } else { | ||
| 600 | if (backup) { | ||
| 601 | backup->resize_destructive(this->size()); | ||
| 602 | m_data_span = *backup; | ||
| 603 | } else { | ||
| 604 | m_data_copy.resize(this->size()); | ||
| 605 | m_data_span = std::span(m_data_copy); | ||
| 606 | } | ||
| 607 | m_is_data_copy = true; | ||
| 608 | m_span_valid = true; | ||
| 609 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 610 | m_memory.ReadBlock(m_addr, this->data(), this->size_bytes()); | ||
| 611 | } else { | ||
| 612 | m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes()); | ||
| 613 | } | ||
| 614 | } | ||
| 615 | return m_data_span; | ||
| 616 | } | ||
| 617 | |||
| 618 | void Write(std::span<T> write_data) noexcept { | ||
| 619 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | ||
| 620 | m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes()); | ||
| 621 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 622 | m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes()); | ||
| 623 | } else { | ||
| 624 | m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes()); | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 628 | bool TrySetSpan() noexcept { | ||
| 629 | if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) { | ||
| 630 | m_data_span = {reinterpret_cast<T*>(ptr), this->size()}; | ||
| 631 | m_span_valid = true; | ||
| 632 | return true; | ||
| 633 | } | ||
| 634 | return false; | ||
| 635 | } | ||
| 636 | |||
| 637 | protected: | ||
| 638 | bool IsDataCopy() const noexcept { | ||
| 639 | return m_is_data_copy; | ||
| 640 | } | ||
| 641 | |||
| 642 | bool AddressChanged() const noexcept { | ||
| 643 | return m_addr_changed; | ||
| 644 | } | ||
| 645 | |||
| 646 | M& m_memory; | ||
| 647 | u64 m_addr{}; | ||
| 648 | size_t m_size{}; | ||
| 649 | std::span<T> m_data_span{}; | ||
| 650 | std::vector<T> m_data_copy{}; | ||
| 651 | bool m_span_valid{false}; | ||
| 652 | bool m_is_data_copy{false}; | ||
| 653 | bool m_addr_changed{false}; | ||
| 654 | }; | ||
| 655 | |||
| 656 | template <typename M, typename T, GuestMemoryFlags FLAGS> | ||
| 657 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { | ||
| 658 | public: | ||
| 659 | GuestMemoryScoped() = delete; | ||
| 660 | explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size, | ||
| 661 | Common::ScratchBuffer<T>* backup = nullptr) | ||
| 662 | : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) { | ||
| 663 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { | ||
| 664 | if (!this->TrySetSpan()) { | ||
| 665 | if (backup) { | ||
| 666 | this->m_data_span = *backup; | ||
| 667 | this->m_span_valid = true; | ||
| 668 | this->m_is_data_copy = true; | ||
| 669 | } | ||
| 670 | } | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | ~GuestMemoryScoped() { | ||
| 675 | if constexpr (FLAGS & GuestMemoryFlags::Write) { | ||
| 676 | if (this->size() == 0) [[unlikely]] { | ||
| 677 | return; | ||
| 678 | } | ||
| 679 | |||
| 680 | if (this->AddressChanged() || this->IsDataCopy()) { | ||
| 681 | ASSERT(this->m_span_valid); | ||
| 682 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | ||
| 683 | this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes()); | ||
| 684 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | ||
| 685 | this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes()); | ||
| 686 | } else { | ||
| 687 | this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes()); | ||
| 688 | } | ||
| 689 | } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) || | ||
| 690 | (FLAGS & GuestMemoryFlags::Cached)) { | ||
| 691 | this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes()); | ||
| 692 | } | ||
| 693 | } | ||
| 694 | } | ||
| 695 | }; | ||
| 696 | } // namespace | ||
| 697 | |||
| 698 | template <typename T, GuestMemoryFlags FLAGS> | 502 | template <typename T, GuestMemoryFlags FLAGS> |
| 699 | using CpuGuestMemory = GuestMemory<Memory, T, FLAGS>; | 503 | using CpuGuestMemory = GuestMemory<Core::Memory::Memory, T, FLAGS>; |
| 700 | template <typename T, GuestMemoryFlags FLAGS> | 504 | template <typename T, GuestMemoryFlags FLAGS> |
| 701 | using CpuGuestMemoryScoped = GuestMemoryScoped<Memory, T, FLAGS>; | 505 | using CpuGuestMemoryScoped = GuestMemoryScoped<Core::Memory::Memory, T, FLAGS>; |
| 702 | template <typename T, GuestMemoryFlags FLAGS> | 506 | |
| 703 | using GpuGuestMemory = GuestMemory<Tegra::MemoryManager, T, FLAGS>; | ||
| 704 | template <typename T, GuestMemoryFlags FLAGS> | ||
| 705 | using GpuGuestMemoryScoped = GuestMemoryScoped<Tegra::MemoryManager, T, FLAGS>; | ||
| 706 | } // namespace Core::Memory | 507 | } // namespace Core::Memory |
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt index 22e9337c4..94d8cc4c3 100644 --- a/src/frontend_common/CMakeLists.txt +++ b/src/frontend_common/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | add_library(frontend_common STATIC | 4 | add_library(frontend_common STATIC |
| 5 | config.cpp | 5 | config.cpp |
| 6 | config.h | 6 | config.h |
| 7 | content_manager.h | ||
| 7 | ) | 8 | ) |
| 8 | 9 | ||
| 9 | create_target_directory_groups(frontend_common) | 10 | create_target_directory_groups(frontend_common) |
diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h new file mode 100644 index 000000000..0b0fee73e --- /dev/null +++ b/src/frontend_common/content_manager.h | |||
| @@ -0,0 +1,371 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <boost/algorithm/string.hpp> | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/literals.h" | ||
| 9 | #include "core/core.h" | ||
| 10 | #include "core/file_sys/common_funcs.h" | ||
| 11 | #include "core/file_sys/content_archive.h" | ||
| 12 | #include "core/file_sys/mode.h" | ||
| 13 | #include "core/file_sys/nca_metadata.h" | ||
| 14 | #include "core/file_sys/patch_manager.h" | ||
| 15 | #include "core/file_sys/registered_cache.h" | ||
| 16 | #include "core/file_sys/submission_package.h" | ||
| 17 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 18 | #include "core/loader/loader.h" | ||
| 19 | #include "core/loader/nca.h" | ||
| 20 | |||
| 21 | namespace ContentManager { | ||
| 22 | |||
| 23 | enum class InstallResult { | ||
| 24 | Success, | ||
| 25 | Overwrite, | ||
| 26 | Failure, | ||
| 27 | BaseInstallAttempted, | ||
| 28 | }; | ||
| 29 | |||
| 30 | enum class GameVerificationResult { | ||
| 31 | Success, | ||
| 32 | Failed, | ||
| 33 | NotImplemented, | ||
| 34 | }; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * \brief Removes a single installed DLC | ||
| 38 | * \param fs_controller [FileSystemController] reference from the Core::System instance | ||
| 39 | * \param title_id Unique title ID representing the DLC which will be removed | ||
| 40 | * \return 'true' if successful | ||
| 41 | */ | ||
| 42 | inline bool RemoveDLC(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 43 | const u64 title_id) { | ||
| 44 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(title_id) || | ||
| 45 | fs_controller.GetSDMCContents()->RemoveExistingEntry(title_id); | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * \brief Removes all DLC for a game | ||
| 50 | * \param system Raw pointer to the system instance | ||
| 51 | * \param program_id Program ID for the game that will have all of its DLC removed | ||
| 52 | * \return Number of DLC removed | ||
| 53 | */ | ||
| 54 | inline size_t RemoveAllDLC(Core::System* system, const u64 program_id) { | ||
| 55 | size_t count{}; | ||
| 56 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 57 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( | ||
| 58 | FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | ||
| 59 | std::vector<u64> program_dlc_entries; | ||
| 60 | |||
| 61 | for (const auto& entry : dlc_entries) { | ||
| 62 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id) { | ||
| 63 | program_dlc_entries.push_back(entry.title_id); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | for (const auto& entry : program_dlc_entries) { | ||
| 68 | if (RemoveDLC(fs_controller, entry)) { | ||
| 69 | ++count; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | return count; | ||
| 73 | } | ||
| 74 | |||
| 75 | /** | ||
| 76 | * \brief Removes the installed update for a game | ||
| 77 | * \param fs_controller [FileSystemController] reference from the Core::System instance | ||
| 78 | * \param program_id Program ID for the game that will have its installed update removed | ||
| 79 | * \return 'true' if successful | ||
| 80 | */ | ||
| 81 | inline bool RemoveUpdate(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 82 | const u64 program_id) { | ||
| 83 | const auto update_id = program_id | 0x800; | ||
| 84 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || | ||
| 85 | fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id); | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * \brief Removes the base content for a game | ||
| 90 | * \param fs_controller [FileSystemController] reference from the Core::System instance | ||
| 91 | * \param program_id Program ID for the game that will have its base content removed | ||
| 92 | * \return 'true' if successful | ||
| 93 | */ | ||
| 94 | inline bool RemoveBaseContent(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 95 | const u64 program_id) { | ||
| 96 | return fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || | ||
| 97 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * \brief Removes a mod for a game | ||
| 102 | * \param fs_controller [FileSystemController] reference from the Core::System instance | ||
| 103 | * \param program_id Program ID for the game where [mod_name] will be removed | ||
| 104 | * \param mod_name The name of a mod as given by FileSys::PatchManager::GetPatches. This corresponds | ||
| 105 | * with the name of the mod's directory in a game's load folder. | ||
| 106 | * \return 'true' if successful | ||
| 107 | */ | ||
| 108 | inline bool RemoveMod(const Service::FileSystem::FileSystemController& fs_controller, | ||
| 109 | const u64 program_id, const std::string& mod_name) { | ||
| 110 | // Check general Mods (LayeredFS and IPS) | ||
| 111 | const auto mod_dir = fs_controller.GetModificationLoadRoot(program_id); | ||
| 112 | if (mod_dir != nullptr) { | ||
| 113 | return mod_dir->DeleteSubdirectoryRecursive(mod_name); | ||
| 114 | } | ||
| 115 | |||
| 116 | // Check SDMC mod directory (RomFS LayeredFS) | ||
| 117 | const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(program_id); | ||
| 118 | if (sdmc_mod_dir != nullptr) { | ||
| 119 | return sdmc_mod_dir->DeleteSubdirectoryRecursive(mod_name); | ||
| 120 | } | ||
| 121 | |||
| 122 | return false; | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * \brief Installs an NSP | ||
| 127 | * \param system Raw pointer to the system instance | ||
| 128 | * \param vfs Raw pointer to the VfsFilesystem instance in Core::System | ||
| 129 | * \param filename Path to the NSP file | ||
| 130 | * \param callback Callback to report the progress of the installation. The first size_t | ||
| 131 | * parameter is the total size of the virtual file and the second is the current progress. If you | ||
| 132 | * return true to the callback, it will cancel the installation as soon as possible. | ||
| 133 | * \return [InstallResult] representing how the installation finished | ||
| 134 | */ | ||
| 135 | inline InstallResult InstallNSP(Core::System* system, FileSys::VfsFilesystem* vfs, | ||
| 136 | const std::string& filename, | ||
| 137 | const std::function<bool(size_t, size_t)>& callback) { | ||
| 138 | const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 139 | std::size_t block_size) { | ||
| 140 | if (src == nullptr || dest == nullptr) { | ||
| 141 | return false; | ||
| 142 | } | ||
| 143 | if (!dest->Resize(src->GetSize())) { | ||
| 144 | return false; | ||
| 145 | } | ||
| 146 | |||
| 147 | using namespace Common::Literals; | ||
| 148 | std::vector<u8> buffer(1_MiB); | ||
| 149 | |||
| 150 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 151 | if (callback(src->GetSize(), i)) { | ||
| 152 | dest->Resize(0); | ||
| 153 | return false; | ||
| 154 | } | ||
| 155 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 156 | dest->Write(buffer.data(), read, i); | ||
| 157 | } | ||
| 158 | return true; | ||
| 159 | }; | ||
| 160 | |||
| 161 | std::shared_ptr<FileSys::NSP> nsp; | ||
| 162 | FileSys::VirtualFile file = vfs->OpenFile(filename, FileSys::Mode::Read); | ||
| 163 | if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) { | ||
| 164 | nsp = std::make_shared<FileSys::NSP>(file); | ||
| 165 | if (nsp->IsExtractedType()) { | ||
| 166 | return InstallResult::Failure; | ||
| 167 | } | ||
| 168 | } else { | ||
| 169 | return InstallResult::Failure; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 173 | return InstallResult::Failure; | ||
| 174 | } | ||
| 175 | const auto res = | ||
| 176 | system->GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true, copy); | ||
| 177 | switch (res) { | ||
| 178 | case FileSys::InstallResult::Success: | ||
| 179 | return InstallResult::Success; | ||
| 180 | case FileSys::InstallResult::OverwriteExisting: | ||
| 181 | return InstallResult::Overwrite; | ||
| 182 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 183 | return InstallResult::BaseInstallAttempted; | ||
| 184 | default: | ||
| 185 | return InstallResult::Failure; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * \brief Installs an NCA | ||
| 191 | * \param vfs Raw pointer to the VfsFilesystem instance in Core::System | ||
| 192 | * \param filename Path to the NCA file | ||
| 193 | * \param registered_cache Raw pointer to the registered cache that the NCA will be installed to | ||
| 194 | * \param title_type Type of NCA package to install | ||
| 195 | * \param callback Callback to report the progress of the installation. The first size_t | ||
| 196 | * parameter is the total size of the virtual file and the second is the current progress. If you | ||
| 197 | * return true to the callback, it will cancel the installation as soon as possible. | ||
| 198 | * \return [InstallResult] representing how the installation finished | ||
| 199 | */ | ||
| 200 | inline InstallResult InstallNCA(FileSys::VfsFilesystem* vfs, const std::string& filename, | ||
| 201 | FileSys::RegisteredCache* registered_cache, | ||
| 202 | const FileSys::TitleType title_type, | ||
| 203 | const std::function<bool(size_t, size_t)>& callback) { | ||
| 204 | const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, | ||
| 205 | std::size_t block_size) { | ||
| 206 | if (src == nullptr || dest == nullptr) { | ||
| 207 | return false; | ||
| 208 | } | ||
| 209 | if (!dest->Resize(src->GetSize())) { | ||
| 210 | return false; | ||
| 211 | } | ||
| 212 | |||
| 213 | using namespace Common::Literals; | ||
| 214 | std::vector<u8> buffer(1_MiB); | ||
| 215 | |||
| 216 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 217 | if (callback(src->GetSize(), i)) { | ||
| 218 | dest->Resize(0); | ||
| 219 | return false; | ||
| 220 | } | ||
| 221 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 222 | dest->Write(buffer.data(), read, i); | ||
| 223 | } | ||
| 224 | return true; | ||
| 225 | }; | ||
| 226 | |||
| 227 | const auto nca = std::make_shared<FileSys::NCA>(vfs->OpenFile(filename, FileSys::Mode::Read)); | ||
| 228 | const auto id = nca->GetStatus(); | ||
| 229 | |||
| 230 | // Game updates necessary are missing base RomFS | ||
| 231 | if (id != Loader::ResultStatus::Success && | ||
| 232 | id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 233 | return InstallResult::Failure; | ||
| 234 | } | ||
| 235 | |||
| 236 | const auto res = registered_cache->InstallEntry(*nca, title_type, true, copy); | ||
| 237 | if (res == FileSys::InstallResult::Success) { | ||
| 238 | return InstallResult::Success; | ||
| 239 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | ||
| 240 | return InstallResult::Overwrite; | ||
| 241 | } else { | ||
| 242 | return InstallResult::Failure; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | /** | ||
| 247 | * \brief Verifies the installed contents for a given ManualContentProvider | ||
| 248 | * \param system Raw pointer to the system instance | ||
| 249 | * \param provider Raw pointer to the content provider that's tracking indexed games | ||
| 250 | * \param callback Callback to report the progress of the installation. The first size_t | ||
| 251 | * parameter is the total size of the installed contents and the second is the current progress. If | ||
| 252 | * you return true to the callback, it will cancel the installation as soon as possible. | ||
| 253 | * \return A list of entries that failed to install. Returns an empty vector if successful. | ||
| 254 | */ | ||
| 255 | inline std::vector<std::string> VerifyInstalledContents( | ||
| 256 | Core::System* system, FileSys::ManualContentProvider* provider, | ||
| 257 | const std::function<bool(size_t, size_t)>& callback) { | ||
| 258 | // Get content registries. | ||
| 259 | auto bis_contents = system->GetFileSystemController().GetSystemNANDContents(); | ||
| 260 | auto user_contents = system->GetFileSystemController().GetUserNANDContents(); | ||
| 261 | |||
| 262 | std::vector<FileSys::RegisteredCache*> content_providers; | ||
| 263 | if (bis_contents) { | ||
| 264 | content_providers.push_back(bis_contents); | ||
| 265 | } | ||
| 266 | if (user_contents) { | ||
| 267 | content_providers.push_back(user_contents); | ||
| 268 | } | ||
| 269 | |||
| 270 | // Get associated NCA files. | ||
| 271 | std::vector<FileSys::VirtualFile> nca_files; | ||
| 272 | |||
| 273 | // Get all installed IDs. | ||
| 274 | size_t total_size = 0; | ||
| 275 | for (auto nca_provider : content_providers) { | ||
| 276 | const auto entries = nca_provider->ListEntriesFilter(); | ||
| 277 | |||
| 278 | for (const auto& entry : entries) { | ||
| 279 | auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type); | ||
| 280 | if (!nca_file) { | ||
| 281 | continue; | ||
| 282 | } | ||
| 283 | |||
| 284 | total_size += nca_file->GetSize(); | ||
| 285 | nca_files.push_back(std::move(nca_file)); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | // Declare a list of file names which failed to verify. | ||
| 290 | std::vector<std::string> failed; | ||
| 291 | |||
| 292 | size_t processed_size = 0; | ||
| 293 | bool cancelled = false; | ||
| 294 | auto nca_callback = [&](size_t nca_processed, size_t nca_total) { | ||
| 295 | cancelled = callback(total_size, processed_size + nca_processed); | ||
| 296 | return !cancelled; | ||
| 297 | }; | ||
| 298 | |||
| 299 | // Using the NCA loader, determine if all NCAs are valid. | ||
| 300 | for (auto& nca_file : nca_files) { | ||
| 301 | Loader::AppLoader_NCA nca_loader(nca_file); | ||
| 302 | |||
| 303 | auto status = nca_loader.VerifyIntegrity(nca_callback); | ||
| 304 | if (cancelled) { | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | if (status != Loader::ResultStatus::Success) { | ||
| 308 | FileSys::NCA nca(nca_file); | ||
| 309 | const auto title_id = nca.GetTitleId(); | ||
| 310 | std::string title_name = "unknown"; | ||
| 311 | |||
| 312 | const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id), | ||
| 313 | FileSys::ContentRecordType::Control); | ||
| 314 | if (control && control->GetStatus() == Loader::ResultStatus::Success) { | ||
| 315 | const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), | ||
| 316 | *provider}; | ||
| 317 | const auto [nacp, logo] = pm.ParseControlNCA(*control); | ||
| 318 | if (nacp) { | ||
| 319 | title_name = nacp->GetApplicationName(); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | if (title_id > 0) { | ||
| 324 | failed.push_back( | ||
| 325 | fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name)); | ||
| 326 | } else { | ||
| 327 | failed.push_back(fmt::format("{} (unknown)", nca_file->GetName())); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | processed_size += nca_file->GetSize(); | ||
| 332 | } | ||
| 333 | return failed; | ||
| 334 | } | ||
| 335 | |||
| 336 | /** | ||
| 337 | * \brief Verifies the contents of a given game | ||
| 338 | * \param system Raw pointer to the system instance | ||
| 339 | * \param game_path Patch to the game file | ||
| 340 | * \param callback Callback to report the progress of the installation. The first size_t | ||
| 341 | * parameter is the total size of the installed contents and the second is the current progress. If | ||
| 342 | * you return true to the callback, it will cancel the installation as soon as possible. | ||
| 343 | * \return GameVerificationResult representing how the verification process finished | ||
| 344 | */ | ||
| 345 | inline GameVerificationResult VerifyGameContents( | ||
| 346 | Core::System* system, const std::string& game_path, | ||
| 347 | const std::function<bool(size_t, size_t)>& callback) { | ||
| 348 | const auto loader = Loader::GetLoader( | ||
| 349 | *system, system->GetFilesystem()->OpenFile(game_path, FileSys::Mode::Read)); | ||
| 350 | if (loader == nullptr) { | ||
| 351 | return GameVerificationResult::NotImplemented; | ||
| 352 | } | ||
| 353 | |||
| 354 | bool cancelled = false; | ||
| 355 | auto loader_callback = [&](size_t processed, size_t total) { | ||
| 356 | cancelled = callback(total, processed); | ||
| 357 | return !cancelled; | ||
| 358 | }; | ||
| 359 | |||
| 360 | const auto status = loader->VerifyIntegrity(loader_callback); | ||
| 361 | if (cancelled || status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) { | ||
| 362 | return GameVerificationResult::NotImplemented; | ||
| 363 | } | ||
| 364 | |||
| 365 | if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) { | ||
| 366 | return GameVerificationResult::Failed; | ||
| 367 | } | ||
| 368 | return GameVerificationResult::Success; | ||
| 369 | } | ||
| 370 | |||
| 371 | } // namespace ContentManager | ||
diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 2ab93402d..e12e5a77e 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp | |||
| @@ -110,6 +110,7 @@ void EmulatedController::ReloadFromSettings() { | |||
| 110 | original_npad_type = npad_type; | 110 | original_npad_type = npad_type; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Active); | ||
| 113 | Disconnect(); | 114 | Disconnect(); |
| 114 | if (player.connected) { | 115 | if (player.connected) { |
| 115 | Connect(); | 116 | Connect(); |
| @@ -144,8 +145,8 @@ void EmulatedController::ReloadColorsFromSettings() { | |||
| 144 | 145 | ||
| 145 | void EmulatedController::LoadDevices() { | 146 | void EmulatedController::LoadDevices() { |
| 146 | // TODO(german77): Use more buttons to detect the correct device | 147 | // TODO(german77): Use more buttons to detect the correct device |
| 147 | const auto left_joycon = button_params[Settings::NativeButton::DRight]; | 148 | const auto& left_joycon = button_params[Settings::NativeButton::DRight]; |
| 148 | const auto right_joycon = button_params[Settings::NativeButton::A]; | 149 | const auto& right_joycon = button_params[Settings::NativeButton::A]; |
| 149 | 150 | ||
| 150 | // Triggers for GC controllers | 151 | // Triggers for GC controllers |
| 151 | trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; | 152 | trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; |
| @@ -1208,16 +1209,44 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) { | |||
| 1208 | controller.nfc_state = controller.nfc_values; | 1209 | controller.nfc_state = controller.nfc_values; |
| 1209 | } | 1210 | } |
| 1210 | 1211 | ||
| 1211 | bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { | 1212 | bool EmulatedController::SetVibration(bool should_vibrate) { |
| 1213 | VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 1214 | if (should_vibrate) { | ||
| 1215 | vibration_value.high_amplitude = 1.0f; | ||
| 1216 | vibration_value.low_amplitude = 1.0f; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | return SetVibration(DeviceIndex::Left, vibration_value); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | bool EmulatedController::SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command) { | ||
| 1223 | VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE; | ||
| 1224 | if (erm_command == Core::HID::VibrationGcErmCommand::Start) { | ||
| 1225 | vibration_value.high_amplitude = 1.0f; | ||
| 1226 | vibration_value.low_amplitude = 1.0f; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | return SetVibration(DeviceIndex::Left, vibration_value); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationValue& vibration) { | ||
| 1212 | if (!is_initialized) { | 1233 | if (!is_initialized) { |
| 1213 | return false; | 1234 | return false; |
| 1214 | } | 1235 | } |
| 1215 | if (device_index >= output_devices.size()) { | 1236 | if (device_index >= DeviceIndex::MaxDeviceIndex) { |
| 1216 | return false; | 1237 | return false; |
| 1217 | } | 1238 | } |
| 1218 | if (!output_devices[device_index]) { | 1239 | const std::size_t index = static_cast<std::size_t>(device_index); |
| 1240 | if (!output_devices[index]) { | ||
| 1241 | return false; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | last_vibration_value = vibration; | ||
| 1245 | |||
| 1246 | if (!Settings::values.vibration_enabled) { | ||
| 1219 | return false; | 1247 | return false; |
| 1220 | } | 1248 | } |
| 1249 | |||
| 1221 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); | 1250 | const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); |
| 1222 | const auto& player = Settings::values.players.GetValue()[player_index]; | 1251 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 1223 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; | 1252 | const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; |
| @@ -1239,8 +1268,11 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v | |||
| 1239 | .high_frequency = vibration.high_frequency, | 1268 | .high_frequency = vibration.high_frequency, |
| 1240 | .type = type, | 1269 | .type = type, |
| 1241 | }; | 1270 | }; |
| 1242 | return output_devices[device_index]->SetVibration(status) == | 1271 | return output_devices[index]->SetVibration(status) == Common::Input::DriverResult::Success; |
| 1243 | Common::Input::DriverResult::Success; | 1272 | } |
| 1273 | |||
| 1274 | VibrationValue EmulatedController::GetActualVibrationValue(DeviceIndex device_index) const { | ||
| 1275 | return last_vibration_value; | ||
| 1244 | } | 1276 | } |
| 1245 | 1277 | ||
| 1246 | bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { | 1278 | bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { |
diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h index 90e536e07..168abe089 100644 --- a/src/hid_core/frontend/emulated_controller.h +++ b/src/hid_core/frontend/emulated_controller.h | |||
| @@ -356,10 +356,27 @@ public: | |||
| 356 | const NfcState& GetNfc() const; | 356 | const NfcState& GetNfc() const; |
| 357 | 357 | ||
| 358 | /** | 358 | /** |
| 359 | * Sends an on/off vibration to the left device | ||
| 360 | * @return true if vibration had no errors | ||
| 361 | */ | ||
| 362 | bool SetVibration(bool should_vibrate); | ||
| 363 | |||
| 364 | /** | ||
| 365 | * Sends an GC vibration to the left device | ||
| 366 | * @return true if vibration had no errors | ||
| 367 | */ | ||
| 368 | bool SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command); | ||
| 369 | |||
| 370 | /** | ||
| 359 | * Sends a specific vibration to the output device | 371 | * Sends a specific vibration to the output device |
| 360 | * @return true if vibration had no errors | 372 | * @return true if vibration had no errors |
| 361 | */ | 373 | */ |
| 362 | bool SetVibration(std::size_t device_index, VibrationValue vibration); | 374 | bool SetVibration(DeviceIndex device_index, const VibrationValue& vibration); |
| 375 | |||
| 376 | /** | ||
| 377 | * @return The last sent vibration | ||
| 378 | */ | ||
| 379 | VibrationValue GetActualVibrationValue(DeviceIndex device_index) const; | ||
| 363 | 380 | ||
| 364 | /** | 381 | /** |
| 365 | * Sends a small vibration to the output device | 382 | * Sends a small vibration to the output device |
| @@ -564,6 +581,7 @@ private: | |||
| 564 | f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; | 581 | f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; |
| 565 | u32 turbo_button_state{0}; | 582 | u32 turbo_button_state{0}; |
| 566 | std::size_t nfc_handles{0}; | 583 | std::size_t nfc_handles{0}; |
| 584 | VibrationValue last_vibration_value{DEFAULT_VIBRATION_VALUE}; | ||
| 567 | 585 | ||
| 568 | // Temporary values to avoid doing changes while the controller is in configuring mode | 586 | // Temporary values to avoid doing changes while the controller is in configuring mode |
| 569 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; | 587 | NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; |
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp index 2c5fe6d51..ca824b4a3 100644 --- a/src/hid_core/resource_manager.cpp +++ b/src/hid_core/resource_manager.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/hle/kernel/k_shared_memory.h" | 7 | #include "core/hle/kernel/k_shared_memory.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "hid_core/hid_core.h" | 9 | #include "hid_core/hid_core.h" |
| 10 | #include "hid_core/hid_util.h" | ||
| 10 | #include "hid_core/resource_manager.h" | 11 | #include "hid_core/resource_manager.h" |
| 11 | 12 | ||
| 12 | #include "hid_core/resources/applet_resource.h" | 13 | #include "hid_core/resources/applet_resource.h" |
| @@ -27,6 +28,10 @@ | |||
| 27 | #include "hid_core/resources/touch_screen/gesture.h" | 28 | #include "hid_core/resources/touch_screen/gesture.h" |
| 28 | #include "hid_core/resources/touch_screen/touch_screen.h" | 29 | #include "hid_core/resources/touch_screen/touch_screen.h" |
| 29 | #include "hid_core/resources/unique_pad/unique_pad.h" | 30 | #include "hid_core/resources/unique_pad/unique_pad.h" |
| 31 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 32 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 33 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 34 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 30 | 35 | ||
| 31 | namespace Service::HID { | 36 | namespace Service::HID { |
| 32 | 37 | ||
| @@ -52,6 +57,7 @@ void ResourceManager::Initialize() { | |||
| 52 | 57 | ||
| 53 | system.HIDCore().ReloadInputDevices(); | 58 | system.HIDCore().ReloadInputDevices(); |
| 54 | 59 | ||
| 60 | handheld_config = std::make_shared<HandheldConfig>(); | ||
| 55 | InitializeHidCommonSampler(); | 61 | InitializeHidCommonSampler(); |
| 56 | InitializeTouchScreenSampler(); | 62 | InitializeTouchScreenSampler(); |
| 57 | InitializeConsoleSixAxisSampler(); | 63 | InitializeConsoleSixAxisSampler(); |
| @@ -174,7 +180,7 @@ void ResourceManager::InitializeHidCommonSampler() { | |||
| 174 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); | 180 | debug_pad->SetAppletResource(applet_resource, &shared_mutex); |
| 175 | digitizer->SetAppletResource(applet_resource, &shared_mutex); | 181 | digitizer->SetAppletResource(applet_resource, &shared_mutex); |
| 176 | keyboard->SetAppletResource(applet_resource, &shared_mutex); | 182 | keyboard->SetAppletResource(applet_resource, &shared_mutex); |
| 177 | npad->SetNpadExternals(applet_resource, &shared_mutex); | 183 | npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config); |
| 178 | six_axis->SetAppletResource(applet_resource, &shared_mutex); | 184 | six_axis->SetAppletResource(applet_resource, &shared_mutex); |
| 179 | mouse->SetAppletResource(applet_resource, &shared_mutex); | 185 | mouse->SetAppletResource(applet_resource, &shared_mutex); |
| 180 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); | 186 | debug_mouse->SetAppletResource(applet_resource, &shared_mutex); |
| @@ -257,6 +263,121 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) { | |||
| 257 | applet_resource->EnableTouchScreen(aruid, is_enabled); | 263 | applet_resource->EnableTouchScreen(aruid, is_enabled); |
| 258 | } | 264 | } |
| 259 | 265 | ||
| 266 | NpadVibrationBase* ResourceManager::GetVibrationDevice( | ||
| 267 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 268 | return npad->GetVibrationDevice(handle); | ||
| 269 | } | ||
| 270 | |||
| 271 | NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice( | ||
| 272 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 273 | return npad->GetN64VibrationDevice(handle); | ||
| 274 | } | ||
| 275 | |||
| 276 | NpadVibrationDevice* ResourceManager::GetNSVibrationDevice( | ||
| 277 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 278 | return npad->GetNSVibrationDevice(handle); | ||
| 279 | } | ||
| 280 | |||
| 281 | NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice( | ||
| 282 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 283 | return npad->GetGcVibrationDevice(handle); | ||
| 284 | } | ||
| 285 | |||
| 286 | Result ResourceManager::SetAruidValidForVibration(u64 aruid, bool is_enabled) { | ||
| 287 | std::scoped_lock lock{shared_mutex}; | ||
| 288 | const bool has_changed = applet_resource->SetAruidValidForVibration(aruid, is_enabled); | ||
| 289 | |||
| 290 | if (has_changed) { | ||
| 291 | auto devices = npad->GetAllVibrationDevices(); | ||
| 292 | for ([[maybe_unused]] auto* device : devices) { | ||
| 293 | // TODO | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | auto* vibration_handler = npad->GetVibrationHandler(); | ||
| 298 | if (aruid != vibration_handler->GetSessionAruid()) { | ||
| 299 | vibration_handler->EndPermitVibrationSession(); | ||
| 300 | } | ||
| 301 | |||
| 302 | return ResultSuccess; | ||
| 303 | } | ||
| 304 | |||
| 305 | void ResourceManager::SetForceHandheldStyleVibration(bool is_forced) { | ||
| 306 | handheld_config->is_force_handheld_style_vibration = is_forced; | ||
| 307 | } | ||
| 308 | |||
| 309 | Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) const { | ||
| 310 | std::scoped_lock lock{shared_mutex}; | ||
| 311 | is_active = applet_resource->IsVibrationAruidActive(aruid); | ||
| 312 | return ResultSuccess; | ||
| 313 | } | ||
| 314 | |||
| 315 | Result ResourceManager::GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, | ||
| 316 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 317 | bool check_device_index = false; | ||
| 318 | |||
| 319 | const Result is_valid = IsVibrationHandleValid(handle); | ||
| 320 | if (is_valid.IsError()) { | ||
| 321 | return is_valid; | ||
| 322 | } | ||
| 323 | |||
| 324 | switch (handle.npad_type) { | ||
| 325 | case Core::HID::NpadStyleIndex::Fullkey: | ||
| 326 | case Core::HID::NpadStyleIndex::Handheld: | ||
| 327 | case Core::HID::NpadStyleIndex::JoyconDual: | ||
| 328 | case Core::HID::NpadStyleIndex::JoyconLeft: | ||
| 329 | case Core::HID::NpadStyleIndex::JoyconRight: | ||
| 330 | device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator; | ||
| 331 | check_device_index = true; | ||
| 332 | break; | ||
| 333 | case Core::HID::NpadStyleIndex::GameCube: | ||
| 334 | device_info.type = Core::HID::VibrationDeviceType::GcErm; | ||
| 335 | break; | ||
| 336 | case Core::HID::NpadStyleIndex::N64: | ||
| 337 | device_info.type = Core::HID::VibrationDeviceType::N64; | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | device_info.type = Core::HID::VibrationDeviceType::Unknown; | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | |||
| 344 | device_info.position = Core::HID::VibrationDevicePosition::None; | ||
| 345 | if (check_device_index) { | ||
| 346 | switch (handle.device_index) { | ||
| 347 | case Core::HID::DeviceIndex::Left: | ||
| 348 | device_info.position = Core::HID::VibrationDevicePosition::Left; | ||
| 349 | break; | ||
| 350 | case Core::HID::DeviceIndex::Right: | ||
| 351 | device_info.position = Core::HID::VibrationDevicePosition::Right; | ||
| 352 | break; | ||
| 353 | case Core::HID::DeviceIndex::None: | ||
| 354 | default: | ||
| 355 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | return ResultSuccess; | ||
| 360 | } | ||
| 361 | |||
| 362 | Result ResourceManager::SendVibrationValue(u64 aruid, | ||
| 363 | const Core::HID::VibrationDeviceHandle& handle, | ||
| 364 | const Core::HID::VibrationValue& value) { | ||
| 365 | bool has_active_aruid{}; | ||
| 366 | NpadVibrationDevice* device{nullptr}; | ||
| 367 | Result result = IsVibrationAruidActive(aruid, has_active_aruid); | ||
| 368 | |||
| 369 | if (result.IsSuccess() && has_active_aruid) { | ||
| 370 | result = IsVibrationHandleValid(handle); | ||
| 371 | } | ||
| 372 | if (result.IsSuccess() && has_active_aruid) { | ||
| 373 | device = GetNSVibrationDevice(handle); | ||
| 374 | } | ||
| 375 | if (device != nullptr) { | ||
| 376 | result = device->SendVibrationValue(value); | ||
| 377 | } | ||
| 378 | return result; | ||
| 379 | } | ||
| 380 | |||
| 260 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { | 381 | void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { |
| 261 | auto& core_timing = system.CoreTiming(); | 382 | auto& core_timing = system.CoreTiming(); |
| 262 | debug_pad->OnUpdate(core_timing); | 383 | debug_pad->OnUpdate(core_timing); |
diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h index 7a21d8eb8..128e00125 100644 --- a/src/hid_core/resource_manager.h +++ b/src/hid_core/resource_manager.h | |||
| @@ -10,6 +10,12 @@ namespace Core { | |||
| 10 | class System; | 10 | class System; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Core::HID { | ||
| 14 | struct VibrationDeviceHandle; | ||
| 15 | struct VibrationValue; | ||
| 16 | struct VibrationDeviceInfo; | ||
| 17 | } // namespace Core::HID | ||
| 18 | |||
| 13 | namespace Core::Timing { | 19 | namespace Core::Timing { |
| 14 | struct EventType; | 20 | struct EventType; |
| 15 | } | 21 | } |
| @@ -37,6 +43,11 @@ class SixAxis; | |||
| 37 | class SleepButton; | 43 | class SleepButton; |
| 38 | class TouchScreen; | 44 | class TouchScreen; |
| 39 | class UniquePad; | 45 | class UniquePad; |
| 46 | class NpadVibrationBase; | ||
| 47 | class NpadN64VibrationDevice; | ||
| 48 | class NpadGcVibrationDevice; | ||
| 49 | class NpadVibrationDevice; | ||
| 50 | struct HandheldConfig; | ||
| 40 | 51 | ||
| 41 | class ResourceManager { | 52 | class ResourceManager { |
| 42 | 53 | ||
| @@ -79,6 +90,18 @@ public: | |||
| 79 | void EnablePadInput(u64 aruid, bool is_enabled); | 90 | void EnablePadInput(u64 aruid, bool is_enabled); |
| 80 | void EnableTouchScreen(u64 aruid, bool is_enabled); | 91 | void EnableTouchScreen(u64 aruid, bool is_enabled); |
| 81 | 92 | ||
| 93 | NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 94 | NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 95 | NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 96 | NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); | ||
| 97 | Result SetAruidValidForVibration(u64 aruid, bool is_enabled); | ||
| 98 | void SetForceHandheldStyleVibration(bool is_forced); | ||
| 99 | Result IsVibrationAruidActive(u64 aruid, bool& is_active) const; | ||
| 100 | Result GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info, | ||
| 101 | const Core::HID::VibrationDeviceHandle& handle); | ||
| 102 | Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle, | ||
| 103 | const Core::HID::VibrationValue& value); | ||
| 104 | |||
| 82 | void UpdateControllers(std::chrono::nanoseconds ns_late); | 105 | void UpdateControllers(std::chrono::nanoseconds ns_late); |
| 83 | void UpdateNpad(std::chrono::nanoseconds ns_late); | 106 | void UpdateNpad(std::chrono::nanoseconds ns_late); |
| 84 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); | 107 | void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); |
| @@ -113,6 +136,8 @@ private: | |||
| 113 | std::shared_ptr<TouchScreen> touch_screen = nullptr; | 136 | std::shared_ptr<TouchScreen> touch_screen = nullptr; |
| 114 | std::shared_ptr<UniquePad> unique_pad = nullptr; | 137 | std::shared_ptr<UniquePad> unique_pad = nullptr; |
| 115 | 138 | ||
| 139 | std::shared_ptr<HandheldConfig> handheld_config = nullptr; | ||
| 140 | |||
| 116 | // TODO: Create these resources | 141 | // TODO: Create these resources |
| 117 | // std::shared_ptr<AudioControl> audio_control = nullptr; | 142 | // std::shared_ptr<AudioControl> audio_control = nullptr; |
| 118 | // std::shared_ptr<ButtonConfig> button_config = nullptr; | 143 | // std::shared_ptr<ButtonConfig> button_config = nullptr; |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp index d4e4181bf..e399edfd7 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp | |||
| @@ -115,7 +115,7 @@ Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle) | |||
| 115 | if (sensor_state < NpadIrSensorState::Available) { | 115 | if (sensor_state < NpadIrSensorState::Available) { |
| 116 | return ResultIrSensorIsNotReady; | 116 | return ResultIrSensorIsNotReady; |
| 117 | } | 117 | } |
| 118 | handle = xcd_handle; | 118 | // handle = xcd_handle; |
| 119 | return ResultSuccess; | 119 | return ResultSuccess; |
| 120 | } | 120 | } |
| 121 | 121 | ||
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h index fe8e005af..997811511 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include "core/hle/result.h" | 7 | #include "core/hle/result.h" |
| 8 | #include "hid_core/hid_types.h" | 8 | #include "hid_core/hid_types.h" |
| 9 | 9 | ||
| 10 | namespace Core::HID { | ||
| 11 | class EmulatedController; | ||
| 12 | } | ||
| 13 | |||
| 10 | namespace Kernel { | 14 | namespace Kernel { |
| 11 | class KEvent; | 15 | class KEvent; |
| 12 | class KReadableEvent; | 16 | class KReadableEvent; |
| @@ -50,7 +54,7 @@ private: | |||
| 50 | 54 | ||
| 51 | s32 ref_counter{}; | 55 | s32 ref_counter{}; |
| 52 | Kernel::KEvent* ir_sensor_event{nullptr}; | 56 | Kernel::KEvent* ir_sensor_event{nullptr}; |
| 53 | u64 xcd_handle{}; | 57 | Core::HID::EmulatedController* xcd_handle{}; |
| 54 | NpadIrSensorState sensor_state{}; | 58 | NpadIrSensorState sensor_state{}; |
| 55 | }; | 59 | }; |
| 56 | } // namespace Service::HID | 60 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp index 2c7691d7c..435b095f0 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/hid_core.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" | 6 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" |
| 6 | #include "hid_core/resources/applet_resource.h" | 7 | #include "hid_core/resources/applet_resource.h" |
| @@ -16,7 +17,7 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, | |||
| 16 | CaptureButtonResource* capture_button_resource, | 17 | CaptureButtonResource* capture_button_resource, |
| 17 | HomeButtonResource* home_button_resource, | 18 | HomeButtonResource* home_button_resource, |
| 18 | SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, | 19 | SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, |
| 19 | VibrationHandler* vibration) { | 20 | NpadVibration* vibration, Core::HID::HIDCore* core) { |
| 20 | applet_resource_holder = applet_resource; | 21 | applet_resource_holder = applet_resource; |
| 21 | 22 | ||
| 22 | properties_handler.SetAppletResource(applet_resource_holder); | 23 | properties_handler.SetAppletResource(applet_resource_holder); |
| @@ -35,13 +36,14 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource, | |||
| 35 | mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); | 36 | mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| 36 | mcu_handler.SetPropertiesHandler(&properties_handler); | 37 | mcu_handler.SetPropertiesHandler(&properties_handler); |
| 37 | 38 | ||
| 38 | std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right}; | ||
| 39 | vibration_handler.SetAppletResource(applet_resource_holder); | 39 | vibration_handler.SetAppletResource(applet_resource_holder); |
| 40 | vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); | 40 | vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| 41 | vibration_handler.SetPropertiesHandler(&properties_handler); | 41 | vibration_handler.SetPropertiesHandler(&properties_handler); |
| 42 | vibration_handler.SetN64Vibration(&vibration_n64); | 42 | vibration_handler.SetN64Vibration(&vibration_n64); |
| 43 | vibration_handler.SetVibration(vibration_devices); | 43 | vibration_handler.SetVibration(&vibration_left, &vibration_right); |
| 44 | vibration_handler.SetGcVibration(&vibration_gc); | 44 | vibration_handler.SetGcVibration(&vibration_gc); |
| 45 | vibration_handler.SetVibrationHandler(vibration); | ||
| 46 | vibration_handler.SetHidCore(core); | ||
| 45 | 47 | ||
| 46 | sixaxis_handler.SetAppletResource(applet_resource_holder); | 48 | sixaxis_handler.SetAppletResource(applet_resource_holder); |
| 47 | sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); | 49 | sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); |
| @@ -239,11 +241,6 @@ NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex devi | |||
| 239 | return &vibration_left; | 241 | return &vibration_left; |
| 240 | } | 242 | } |
| 241 | 243 | ||
| 242 | void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) { | ||
| 243 | list.emplace_back(&vibration_left); | ||
| 244 | list.emplace_back(&vibration_right); | ||
| 245 | } | ||
| 246 | |||
| 247 | NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { | 244 | NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { |
| 248 | return &vibration_gc; | 245 | return &vibration_gc; |
| 249 | } | 246 | } |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h index cbdf84af7..329792457 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_pad.h +++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h | |||
| @@ -32,7 +32,6 @@ class AppletResource; | |||
| 32 | class SixAxisResource; | 32 | class SixAxisResource; |
| 33 | class PalmaResource; | 33 | class PalmaResource; |
| 34 | class NPadResource; | 34 | class NPadResource; |
| 35 | class AbstractPad; | ||
| 36 | class NpadLastActiveHandler; | 35 | class NpadLastActiveHandler; |
| 37 | class NpadIrNfcHandler; | 36 | class NpadIrNfcHandler; |
| 38 | class UniquePads; | 37 | class UniquePads; |
| @@ -44,7 +43,6 @@ class NpadGcVibration; | |||
| 44 | 43 | ||
| 45 | class CaptureButtonResource; | 44 | class CaptureButtonResource; |
| 46 | class HomeButtonResource; | 45 | class HomeButtonResource; |
| 47 | class VibrationHandler; | ||
| 48 | 46 | ||
| 49 | struct HandheldConfig; | 47 | struct HandheldConfig; |
| 50 | 48 | ||
| @@ -57,7 +55,8 @@ public: | |||
| 57 | void SetExternals(AppletResourceHolder* applet_resource, | 55 | void SetExternals(AppletResourceHolder* applet_resource, |
| 58 | CaptureButtonResource* capture_button_resource, | 56 | CaptureButtonResource* capture_button_resource, |
| 59 | HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, | 57 | HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, |
| 60 | PalmaResource* palma_resource, VibrationHandler* vibration); | 58 | PalmaResource* palma_resource, NpadVibration* vibration, |
| 59 | Core::HID::HIDCore* core); | ||
| 61 | void SetNpadId(Core::HID::NpadIdType npad_id); | 60 | void SetNpadId(Core::HID::NpadIdType npad_id); |
| 62 | 61 | ||
| 63 | Result Activate(); | 62 | Result Activate(); |
| @@ -78,7 +77,6 @@ public: | |||
| 78 | 77 | ||
| 79 | NpadN64VibrationDevice* GetN64VibrationDevice(); | 78 | NpadN64VibrationDevice* GetN64VibrationDevice(); |
| 80 | NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); | 79 | NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); |
| 81 | void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list); | ||
| 82 | NpadGcVibrationDevice* GetGCVibrationDevice(); | 80 | NpadGcVibrationDevice* GetGCVibrationDevice(); |
| 83 | 81 | ||
| 84 | Core::HID::NpadIdType GetLastActiveNpad(); | 82 | Core::HID::NpadIdType GetLastActiveNpad(); |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp index a00d6c9de..ca64b0a43 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 5 | #include "hid_core/hid_core.h" | ||
| 4 | #include "hid_core/hid_result.h" | 6 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/hid_util.h" | 7 | #include "hid_core/hid_util.h" |
| 6 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" | 8 | #include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" |
| @@ -30,14 +32,22 @@ void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHa | |||
| 30 | properties_handler = handler; | 32 | properties_handler = handler; |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 35 | void NpadAbstractVibrationHandler::SetVibrationHandler(NpadVibration* handler) { | ||
| 36 | vibration_handler = handler; | ||
| 37 | } | ||
| 38 | |||
| 39 | void NpadAbstractVibrationHandler::SetHidCore(Core::HID::HIDCore* core) { | ||
| 40 | hid_core = core; | ||
| 41 | } | ||
| 42 | |||
| 33 | void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { | 43 | void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { |
| 34 | n64_vibration_device = n64_device; | 44 | n64_vibration_device = n64_device; |
| 35 | } | 45 | } |
| 36 | 46 | ||
| 37 | void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) { | 47 | void NpadAbstractVibrationHandler::SetVibration(NpadVibrationDevice* left_device, |
| 38 | for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { | 48 | NpadVibrationDevice* right_device) { |
| 39 | vibration_device[i] = device[i]; | 49 | left_vibration_device = left_device; |
| 40 | } | 50 | right_vibration_device = right_device; |
| 41 | } | 51 | } |
| 42 | 52 | ||
| 43 | void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { | 53 | void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { |
| @@ -69,5 +79,29 @@ void NpadAbstractVibrationHandler::UpdateVibrationState() { | |||
| 69 | if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { | 79 | if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { |
| 70 | // TODO | 80 | // TODO |
| 71 | } | 81 | } |
| 82 | |||
| 83 | // TODO: This function isn't accurate. It's supposed to get 5 abstracted pads from the | ||
| 84 | // NpadAbstractPropertiesHandler but this handler isn't fully implemented yet | ||
| 85 | IAbstractedPad abstracted_pad{}; | ||
| 86 | const auto npad_id = properties_handler->GetNpadId(); | ||
| 87 | abstracted_pad.xcd_handle = hid_core->GetEmulatedController(npad_id); | ||
| 88 | abstracted_pad.internal_flags.is_connected.Assign(abstracted_pad.xcd_handle->IsConnected()); | ||
| 89 | |||
| 90 | if (abstracted_pad.internal_flags.is_connected) { | ||
| 91 | left_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Left, | ||
| 92 | vibration_handler); | ||
| 93 | right_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Right, | ||
| 94 | vibration_handler); | ||
| 95 | gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); | ||
| 96 | gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler); | ||
| 97 | n64_vibration_device->Mount(abstracted_pad, vibration_handler); | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | left_vibration_device->Unmount(); | ||
| 102 | right_vibration_device->Unmount(); | ||
| 103 | gc_vibration_device->Unmount(); | ||
| 104 | gc_vibration_device->Unmount(); | ||
| 105 | n64_vibration_device->Unmount(); | ||
| 72 | } | 106 | } |
| 73 | } // namespace Service::HID | 107 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h index aeb07ce86..8bc8129c2 100644 --- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h +++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h | |||
| @@ -9,6 +9,10 @@ | |||
| 9 | #include "core/hle/result.h" | 9 | #include "core/hle/result.h" |
| 10 | #include "hid_core/hid_types.h" | 10 | #include "hid_core/hid_types.h" |
| 11 | 11 | ||
| 12 | namespace Core::HID { | ||
| 13 | class HIDCore; | ||
| 14 | } | ||
| 15 | |||
| 12 | namespace Service::HID { | 16 | namespace Service::HID { |
| 13 | struct AppletResourceHolder; | 17 | struct AppletResourceHolder; |
| 14 | class NpadAbstractedPadHolder; | 18 | class NpadAbstractedPadHolder; |
| @@ -27,9 +31,11 @@ public: | |||
| 27 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); | 31 | void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); |
| 28 | void SetAppletResource(AppletResourceHolder* applet_resource); | 32 | void SetAppletResource(AppletResourceHolder* applet_resource); |
| 29 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); | 33 | void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); |
| 34 | void SetVibrationHandler(NpadVibration* handler); | ||
| 35 | void SetHidCore(Core::HID::HIDCore* core); | ||
| 30 | 36 | ||
| 31 | void SetN64Vibration(NpadN64VibrationDevice* n64_device); | 37 | void SetN64Vibration(NpadN64VibrationDevice* n64_device); |
| 32 | void SetVibration(std::span<NpadVibrationDevice*> device); | 38 | void SetVibration(NpadVibrationDevice* left_device, NpadVibrationDevice* right_device); |
| 33 | void SetGcVibration(NpadGcVibrationDevice* gc_device); | 39 | void SetGcVibration(NpadGcVibrationDevice* gc_device); |
| 34 | 40 | ||
| 35 | Result IncrementRefCounter(); | 41 | Result IncrementRefCounter(); |
| @@ -41,9 +47,11 @@ private: | |||
| 41 | AppletResourceHolder* applet_resource_holder{nullptr}; | 47 | AppletResourceHolder* applet_resource_holder{nullptr}; |
| 42 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; | 48 | NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; |
| 43 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; | 49 | NpadAbstractPropertiesHandler* properties_handler{nullptr}; |
| 50 | Core::HID::HIDCore* hid_core{nullptr}; | ||
| 44 | 51 | ||
| 45 | NpadN64VibrationDevice* n64_vibration_device{nullptr}; | 52 | NpadN64VibrationDevice* n64_vibration_device{nullptr}; |
| 46 | std::array<NpadVibrationDevice*, 2> vibration_device{}; | 53 | NpadVibrationDevice* left_vibration_device{}; |
| 54 | NpadVibrationDevice* right_vibration_device{}; | ||
| 47 | NpadGcVibrationDevice* gc_vibration_device{nullptr}; | 55 | NpadGcVibrationDevice* gc_vibration_device{nullptr}; |
| 48 | NpadVibration* vibration_handler{nullptr}; | 56 | NpadVibration* vibration_handler{nullptr}; |
| 49 | s32 ref_counter{}; | 57 | s32 ref_counter{}; |
diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp index a84826050..db4134037 100644 --- a/src/hid_core/resources/applet_resource.cpp +++ b/src/hid_core/resources/applet_resource.cpp | |||
| @@ -200,6 +200,25 @@ void AppletResource::EnableInput(u64 aruid, bool is_enabled) { | |||
| 200 | data[index].flag.enable_touchscreen.Assign(is_enabled); | 200 | data[index].flag.enable_touchscreen.Assign(is_enabled); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | bool AppletResource::SetAruidValidForVibration(u64 aruid, bool is_enabled) { | ||
| 204 | const u64 index = GetIndexFromAruid(aruid); | ||
| 205 | if (index >= AruidIndexMax) { | ||
| 206 | return false; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (!is_enabled && aruid == active_vibration_aruid) { | ||
| 210 | active_vibration_aruid = SystemAruid; | ||
| 211 | return true; | ||
| 212 | } | ||
| 213 | |||
| 214 | if (is_enabled && aruid != active_vibration_aruid) { | ||
| 215 | active_vibration_aruid = aruid; | ||
| 216 | return true; | ||
| 217 | } | ||
| 218 | |||
| 219 | return false; | ||
| 220 | } | ||
| 221 | |||
| 203 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { | 222 | void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { |
| 204 | const u64 index = GetIndexFromAruid(aruid); | 223 | const u64 index = GetIndexFromAruid(aruid); |
| 205 | if (index >= AruidIndexMax) { | 224 | if (index >= AruidIndexMax) { |
diff --git a/src/hid_core/resources/applet_resource.h b/src/hid_core/resources/applet_resource.h index f3f32bac1..e9710d306 100644 --- a/src/hid_core/resources/applet_resource.h +++ b/src/hid_core/resources/applet_resource.h | |||
| @@ -101,6 +101,7 @@ public: | |||
| 101 | Result DestroySevenSixAxisTransferMemory(); | 101 | Result DestroySevenSixAxisTransferMemory(); |
| 102 | 102 | ||
| 103 | void EnableInput(u64 aruid, bool is_enabled); | 103 | void EnableInput(u64 aruid, bool is_enabled); |
| 104 | bool SetAruidValidForVibration(u64 aruid, bool is_enabled); | ||
| 104 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); | 105 | void EnableSixAxisSensor(u64 aruid, bool is_enabled); |
| 105 | void EnablePadInput(u64 aruid, bool is_enabled); | 106 | void EnablePadInput(u64 aruid, bool is_enabled); |
| 106 | void EnableTouchScreen(u64 aruid, bool is_enabled); | 107 | void EnableTouchScreen(u64 aruid, bool is_enabled); |
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index 97537a2e2..d13a489c9 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include "hid_core/hid_util.h" | 21 | #include "hid_core/hid_util.h" |
| 22 | #include "hid_core/resources/applet_resource.h" | 22 | #include "hid_core/resources/applet_resource.h" |
| 23 | #include "hid_core/resources/npad/npad.h" | 23 | #include "hid_core/resources/npad/npad.h" |
| 24 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 24 | #include "hid_core/resources/shared_memory_format.h" | 25 | #include "hid_core/resources/shared_memory_format.h" |
| 25 | 26 | ||
| 26 | namespace Service::HID { | 27 | namespace Service::HID { |
| @@ -31,10 +32,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service | |||
| 31 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { | 32 | for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { |
| 32 | auto& controller = controller_data[aruid_index][i]; | 33 | auto& controller = controller_data[aruid_index][i]; |
| 33 | controller.device = hid_core.GetEmulatedControllerByIndex(i); | 34 | controller.device = hid_core.GetEmulatedControllerByIndex(i); |
| 34 | controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = | ||
| 35 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 36 | controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex] | ||
| 37 | .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 38 | Core::HID::ControllerUpdateCallback engine_callback{ | 35 | Core::HID::ControllerUpdateCallback engine_callback{ |
| 39 | .on_change = | 36 | .on_change = |
| 40 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, | 37 | [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, |
| @@ -43,6 +40,10 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service | |||
| 43 | controller.callback_key = controller.device->SetCallback(engine_callback); | 40 | controller.callback_key = controller.device->SetCallback(engine_callback); |
| 44 | } | 41 | } |
| 45 | } | 42 | } |
| 43 | for (std::size_t i = 0; i < abstracted_pads.size(); ++i) { | ||
| 44 | abstracted_pads[i] = AbstractPad{}; | ||
| 45 | abstracted_pads[i].SetNpadId(IndexToNpadIdType(i)); | ||
| 46 | } | ||
| 46 | } | 47 | } |
| 47 | 48 | ||
| 48 | NPad::~NPad() { | 49 | NPad::~NPad() { |
| @@ -359,6 +360,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) { | |||
| 359 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); | 360 | npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); |
| 360 | WriteEmptyEntry(controller.shared_memory); | 361 | WriteEmptyEntry(controller.shared_memory); |
| 361 | hid_core.SetLastActiveController(npad_id); | 362 | hid_core.SetLastActiveController(npad_id); |
| 363 | abstracted_pads[NpadIdTypeToIndex(npad_id)].Update(); | ||
| 362 | } | 364 | } |
| 363 | 365 | ||
| 364 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { | 366 | void NPad::WriteEmptyEntry(NpadInternalState* npad) { |
| @@ -478,6 +480,10 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) { | |||
| 478 | continue; | 480 | continue; |
| 479 | } | 481 | } |
| 480 | 482 | ||
| 483 | if (!data->flag.enable_pad_input) { | ||
| 484 | continue; | ||
| 485 | } | ||
| 486 | |||
| 481 | RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); | 487 | RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); |
| 482 | auto& pad_state = controller.npad_pad_state; | 488 | auto& pad_state = controller.npad_pad_state; |
| 483 | auto& libnx_state = controller.npad_libnx_state; | 489 | auto& libnx_state = controller.npad_libnx_state; |
| @@ -740,171 +746,6 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID: | |||
| 740 | return true; | 746 | return true; |
| 741 | } | 747 | } |
| 742 | 748 | ||
| 743 | bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 744 | std::size_t device_index, | ||
| 745 | const Core::HID::VibrationValue& vibration_value) { | ||
| 746 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 747 | if (!controller.device->IsConnected()) { | ||
| 748 | return false; | ||
| 749 | } | ||
| 750 | |||
| 751 | if (!controller.device->IsVibrationEnabled(device_index)) { | ||
| 752 | if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || | ||
| 753 | controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { | ||
| 754 | // Send an empty vibration to stop any vibrations. | ||
| 755 | Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; | ||
| 756 | controller.device->SetVibration(device_index, vibration); | ||
| 757 | // Then reset the vibration value to its default value. | ||
| 758 | controller.vibration[device_index].latest_vibration_value = | ||
| 759 | Core::HID::DEFAULT_VIBRATION_VALUE; | ||
| 760 | } | ||
| 761 | |||
| 762 | return false; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (!Settings::values.enable_accurate_vibrations.GetValue()) { | ||
| 766 | using std::chrono::duration_cast; | ||
| 767 | using std::chrono::milliseconds; | ||
| 768 | using std::chrono::steady_clock; | ||
| 769 | |||
| 770 | const auto now = steady_clock::now(); | ||
| 771 | |||
| 772 | // Filter out non-zero vibrations that are within 15ms of each other. | ||
| 773 | if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) && | ||
| 774 | duration_cast<milliseconds>( | ||
| 775 | now - controller.vibration[device_index].last_vibration_timepoint) < | ||
| 776 | milliseconds(15)) { | ||
| 777 | return false; | ||
| 778 | } | ||
| 779 | |||
| 780 | controller.vibration[device_index].last_vibration_timepoint = now; | ||
| 781 | } | ||
| 782 | |||
| 783 | Core::HID::VibrationValue vibration{ | ||
| 784 | vibration_value.low_amplitude, vibration_value.low_frequency, | ||
| 785 | vibration_value.high_amplitude, vibration_value.high_frequency}; | ||
| 786 | return controller.device->SetVibration(device_index, vibration); | ||
| 787 | } | ||
| 788 | |||
| 789 | void NPad::VibrateController(u64 aruid, | ||
| 790 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 791 | const Core::HID::VibrationValue& vibration_value) { | ||
| 792 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 793 | return; | ||
| 794 | } | ||
| 795 | |||
| 796 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 801 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 802 | |||
| 803 | if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) { | ||
| 804 | return; | ||
| 805 | } | ||
| 806 | |||
| 807 | if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { | ||
| 808 | ASSERT_MSG(false, "DeviceIndex should never be None!"); | ||
| 809 | return; | ||
| 810 | } | ||
| 811 | |||
| 812 | // Some games try to send mismatched parameters in the device handle, block these. | ||
| 813 | if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft && | ||
| 814 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight || | ||
| 815 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) || | ||
| 816 | (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight && | ||
| 817 | (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft || | ||
| 818 | vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) { | ||
| 819 | return; | ||
| 820 | } | ||
| 821 | |||
| 822 | // Filter out vibrations with equivalent values to reduce unnecessary state changes. | ||
| 823 | if (vibration_value.low_amplitude == | ||
| 824 | controller.vibration[device_index].latest_vibration_value.low_amplitude && | ||
| 825 | vibration_value.high_amplitude == | ||
| 826 | controller.vibration[device_index].latest_vibration_value.high_amplitude) { | ||
| 827 | return; | ||
| 828 | } | ||
| 829 | |||
| 830 | if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index, | ||
| 831 | vibration_value)) { | ||
| 832 | controller.vibration[device_index].latest_vibration_value = vibration_value; | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | void NPad::VibrateControllers( | ||
| 837 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 838 | std::span<const Core::HID::VibrationValue> vibration_values) { | ||
| 839 | if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { | ||
| 840 | return; | ||
| 841 | } | ||
| 842 | |||
| 843 | ASSERT_OR_EXECUTE_MSG( | ||
| 844 | vibration_device_handles.size() == vibration_values.size(), { return; }, | ||
| 845 | "The amount of device handles does not match with the amount of vibration values," | ||
| 846 | "this is undefined behavior!"); | ||
| 847 | |||
| 848 | for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) { | ||
| 849 | VibrateController(aruid, vibration_device_handles[i], vibration_values[i]); | ||
| 850 | } | ||
| 851 | } | ||
| 852 | |||
| 853 | Core::HID::VibrationValue NPad::GetLastVibration( | ||
| 854 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 855 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 856 | return {}; | ||
| 857 | } | ||
| 858 | |||
| 859 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 860 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 861 | return controller.vibration[device_index].latest_vibration_value; | ||
| 862 | } | ||
| 863 | |||
| 864 | void NPad::InitializeVibrationDevice( | ||
| 865 | const Core::HID::VibrationDeviceHandle& vibration_device_handle) { | ||
| 866 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 867 | return; | ||
| 868 | } | ||
| 869 | |||
| 870 | const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid(); | ||
| 871 | const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id); | ||
| 872 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 873 | |||
| 874 | if (aruid == 0) { | ||
| 875 | return; | ||
| 876 | } | ||
| 877 | |||
| 878 | InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index); | ||
| 879 | } | ||
| 880 | |||
| 881 | void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 882 | std::size_t device_index) { | ||
| 883 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | ||
| 884 | if (!Settings::values.vibration_enabled.GetValue()) { | ||
| 885 | controller.vibration[device_index].device_mounted = false; | ||
| 886 | return; | ||
| 887 | } | ||
| 888 | |||
| 889 | controller.vibration[device_index].device_mounted = | ||
| 890 | controller.device->IsVibrationEnabled(device_index); | ||
| 891 | } | ||
| 892 | |||
| 893 | void NPad::SetPermitVibrationSession(bool permit_vibration_session) { | ||
| 894 | permit_vibration_session_enabled = permit_vibration_session; | ||
| 895 | } | ||
| 896 | |||
| 897 | bool NPad::IsVibrationDeviceMounted( | ||
| 898 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const { | ||
| 899 | if (IsVibrationHandleValid(vibration_device_handle).IsError()) { | ||
| 900 | return false; | ||
| 901 | } | ||
| 902 | |||
| 903 | const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle); | ||
| 904 | const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index); | ||
| 905 | return controller.vibration[device_index].device_mounted; | ||
| 906 | } | ||
| 907 | |||
| 908 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | 749 | Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, |
| 909 | Core::HID::NpadIdType npad_id) { | 750 | Core::HID::NpadIdType npad_id) { |
| 910 | std::scoped_lock lock{mutex}; | 751 | std::scoped_lock lock{mutex}; |
| @@ -936,11 +777,6 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) { | |||
| 936 | 777 | ||
| 937 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); | 778 | LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); |
| 938 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); | 779 | auto& controller = GetControllerFromNpadIdType(aruid, npad_id); |
| 939 | for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) { | ||
| 940 | // Send an empty vibration to stop any vibrations. | ||
| 941 | VibrateControllerAtIndex(aruid, npad_id, device_idx, {}); | ||
| 942 | controller.vibration[device_idx].device_mounted = false; | ||
| 943 | } | ||
| 944 | 780 | ||
| 945 | auto* shared_memory = controller.shared_memory; | 781 | auto* shared_memory = controller.shared_memory; |
| 946 | // Don't reset shared_memory->assignment_mode this value is persistent | 782 | // Don't reset shared_memory->assignment_mode this value is persistent |
| @@ -1232,26 +1068,28 @@ Result NPad::RegisterAppletResourceUserId(u64 aruid) { | |||
| 1232 | } | 1068 | } |
| 1233 | 1069 | ||
| 1234 | void NPad::UnregisterAppletResourceUserId(u64 aruid) { | 1070 | void NPad::UnregisterAppletResourceUserId(u64 aruid) { |
| 1071 | // TODO: Remove this once abstract pad is emulated properly | ||
| 1072 | const auto aruid_index = npad_resource.GetIndexFromAruid(aruid); | ||
| 1073 | for (auto& controller : controller_data[aruid_index]) { | ||
| 1074 | controller.is_connected = false; | ||
| 1075 | controller.shared_memory = nullptr; | ||
| 1076 | } | ||
| 1077 | |||
| 1235 | npad_resource.UnregisterAppletResourceUserId(aruid); | 1078 | npad_resource.UnregisterAppletResourceUserId(aruid); |
| 1236 | } | 1079 | } |
| 1237 | 1080 | ||
| 1238 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, | 1081 | void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 1239 | std::recursive_mutex* shared_mutex) { | 1082 | std::recursive_mutex* shared_mutex, |
| 1083 | std::shared_ptr<HandheldConfig> handheld_config) { | ||
| 1240 | applet_resource_holder.applet_resource = resource; | 1084 | applet_resource_holder.applet_resource = resource; |
| 1241 | applet_resource_holder.shared_mutex = shared_mutex; | 1085 | applet_resource_holder.shared_mutex = shared_mutex; |
| 1242 | applet_resource_holder.shared_npad_resource = &npad_resource; | 1086 | applet_resource_holder.shared_npad_resource = &npad_resource; |
| 1243 | } | 1087 | applet_resource_holder.handheld_config = handheld_config; |
| 1244 | |||
| 1245 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | ||
| 1246 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) { | ||
| 1247 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | ||
| 1248 | return GetControllerFromNpadIdType(aruid, npad_id); | ||
| 1249 | } | ||
| 1250 | 1088 | ||
| 1251 | const NPad::NpadControllerData& NPad::GetControllerFromHandle( | 1089 | for (auto& abstract_pad : abstracted_pads) { |
| 1252 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { | 1090 | abstract_pad.SetExternals(&applet_resource_holder, nullptr, nullptr, nullptr, nullptr, |
| 1253 | const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); | 1091 | &vibration_handler, &hid_core); |
| 1254 | return GetControllerFromNpadIdType(aruid, npad_id); | 1092 | } |
| 1255 | } | 1093 | } |
| 1256 | 1094 | ||
| 1257 | NPad::NpadControllerData& NPad::GetControllerFromHandle( | 1095 | NPad::NpadControllerData& NPad::GetControllerFromHandle( |
| @@ -1389,4 +1227,106 @@ Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const { | |||
| 1389 | return ResultSuccess; | 1227 | return ResultSuccess; |
| 1390 | } | 1228 | } |
| 1391 | 1229 | ||
| 1230 | NpadVibration* NPad::GetVibrationHandler() { | ||
| 1231 | return &vibration_handler; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | std::vector<NpadVibrationBase*> NPad::GetAllVibrationDevices() { | ||
| 1235 | std::vector<NpadVibrationBase*> vibration_devices; | ||
| 1236 | |||
| 1237 | for (auto& abstract_pad : abstracted_pads) { | ||
| 1238 | auto* left_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Left); | ||
| 1239 | auto* right_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Right); | ||
| 1240 | auto* n64_device = abstract_pad.GetGCVibrationDevice(); | ||
| 1241 | auto* gc_device = abstract_pad.GetGCVibrationDevice(); | ||
| 1242 | |||
| 1243 | if (left_device != nullptr) { | ||
| 1244 | vibration_devices.emplace_back(left_device); | ||
| 1245 | } | ||
| 1246 | if (right_device != nullptr) { | ||
| 1247 | vibration_devices.emplace_back(right_device); | ||
| 1248 | } | ||
| 1249 | if (n64_device != nullptr) { | ||
| 1250 | vibration_devices.emplace_back(n64_device); | ||
| 1251 | } | ||
| 1252 | if (gc_device != nullptr) { | ||
| 1253 | vibration_devices.emplace_back(gc_device); | ||
| 1254 | } | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | return vibration_devices; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | NpadVibrationBase* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1261 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1262 | return nullptr; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1266 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1267 | if (style_inde == Core::HID::NpadStyleIndex::GameCube) { | ||
| 1268 | return abstracted_pads[npad_index].GetGCVibrationDevice(); | ||
| 1269 | } | ||
| 1270 | if (style_inde == Core::HID::NpadStyleIndex::N64) { | ||
| 1271 | return abstracted_pads[npad_index].GetN64VibrationDevice(); | ||
| 1272 | } | ||
| 1273 | return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | NpadN64VibrationDevice* NPad::GetN64VibrationDevice( | ||
| 1277 | const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1278 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1279 | return nullptr; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1283 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1284 | if (style_inde != Core::HID::NpadStyleIndex::N64) { | ||
| 1285 | return nullptr; | ||
| 1286 | } | ||
| 1287 | return abstracted_pads[npad_index].GetN64VibrationDevice(); | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | NpadVibrationDevice* NPad::GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1291 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1292 | return nullptr; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1296 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1297 | if (style_inde == Core::HID::NpadStyleIndex::GameCube || | ||
| 1298 | style_inde == Core::HID::NpadStyleIndex::N64) { | ||
| 1299 | return nullptr; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index); | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | NpadGcVibrationDevice* NPad::GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) { | ||
| 1306 | if (IsVibrationHandleValid(handle).IsError()) { | ||
| 1307 | return nullptr; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id)); | ||
| 1311 | const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type); | ||
| 1312 | if (style_inde != Core::HID::NpadStyleIndex::GameCube) { | ||
| 1313 | return nullptr; | ||
| 1314 | } | ||
| 1315 | return abstracted_pads[npad_index].GetGCVibrationDevice(); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | void NPad::UpdateHandheldAbstractState() { | ||
| 1319 | std::scoped_lock lock{mutex}; | ||
| 1320 | abstracted_pads[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update(); | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | void NPad::EnableAppletToGetInput(u64 aruid) { | ||
| 1324 | std::scoped_lock lock{mutex}; | ||
| 1325 | std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex}; | ||
| 1326 | |||
| 1327 | for (auto& abstract_pad : abstracted_pads) { | ||
| 1328 | abstract_pad.EnableAppletToGetInput(aruid); | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1392 | } // namespace Service::HID | 1332 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h index 01f3dabb1..88289fa2b 100644 --- a/src/hid_core/resources/npad/npad.h +++ b/src/hid_core/resources/npad/npad.h | |||
| @@ -10,9 +10,15 @@ | |||
| 10 | 10 | ||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "hid_core/hid_types.h" | 12 | #include "hid_core/hid_types.h" |
| 13 | #include "hid_core/resources/abstracted_pad/abstract_pad.h" | ||
| 13 | #include "hid_core/resources/controller_base.h" | 14 | #include "hid_core/resources/controller_base.h" |
| 14 | #include "hid_core/resources/npad/npad_resource.h" | 15 | #include "hid_core/resources/npad/npad_resource.h" |
| 15 | #include "hid_core/resources/npad/npad_types.h" | 16 | #include "hid_core/resources/npad/npad_types.h" |
| 17 | #include "hid_core/resources/npad/npad_vibration.h" | ||
| 18 | #include "hid_core/resources/vibration/gc_vibration_device.h" | ||
| 19 | #include "hid_core/resources/vibration/n64_vibration_device.h" | ||
| 20 | #include "hid_core/resources/vibration/vibration_base.h" | ||
| 21 | #include "hid_core/resources/vibration/vibration_device.h" | ||
| 16 | 22 | ||
| 17 | namespace Core::HID { | 23 | namespace Core::HID { |
| 18 | class EmulatedController; | 24 | class EmulatedController; |
| @@ -32,6 +38,7 @@ union Result; | |||
| 32 | 38 | ||
| 33 | namespace Service::HID { | 39 | namespace Service::HID { |
| 34 | class AppletResource; | 40 | class AppletResource; |
| 41 | struct HandheldConfig; | ||
| 35 | struct NpadInternalState; | 42 | struct NpadInternalState; |
| 36 | struct NpadSixAxisSensorLifo; | 43 | struct NpadSixAxisSensorLifo; |
| 37 | struct NpadSharedMemoryFormat; | 44 | struct NpadSharedMemoryFormat; |
| @@ -68,31 +75,6 @@ public: | |||
| 68 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, | 75 | bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, |
| 69 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); | 76 | NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); |
| 70 | 77 | ||
| 71 | bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 72 | std::size_t device_index, | ||
| 73 | const Core::HID::VibrationValue& vibration_value); | ||
| 74 | |||
| 75 | void VibrateController(u64 aruid, | ||
| 76 | const Core::HID::VibrationDeviceHandle& vibration_device_handle, | ||
| 77 | const Core::HID::VibrationValue& vibration_value); | ||
| 78 | |||
| 79 | void VibrateControllers( | ||
| 80 | u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles, | ||
| 81 | std::span<const Core::HID::VibrationValue> vibration_values); | ||
| 82 | |||
| 83 | Core::HID::VibrationValue GetLastVibration( | ||
| 84 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 85 | |||
| 86 | void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle); | ||
| 87 | |||
| 88 | void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id, | ||
| 89 | std::size_t device_index); | ||
| 90 | |||
| 91 | void SetPermitVibrationSession(bool permit_vibration_session); | ||
| 92 | |||
| 93 | bool IsVibrationDeviceMounted( | ||
| 94 | u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; | ||
| 95 | |||
| 96 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, | 78 | Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, |
| 97 | Core::HID::NpadIdType npad_id); | 79 | Core::HID::NpadIdType npad_id); |
| 98 | 80 | ||
| @@ -145,7 +127,8 @@ public: | |||
| 145 | Result RegisterAppletResourceUserId(u64 aruid); | 127 | Result RegisterAppletResourceUserId(u64 aruid); |
| 146 | void UnregisterAppletResourceUserId(u64 aruid); | 128 | void UnregisterAppletResourceUserId(u64 aruid); |
| 147 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, | 129 | void SetNpadExternals(std::shared_ptr<AppletResource> resource, |
| 148 | std::recursive_mutex* shared_mutex); | 130 | std::recursive_mutex* shared_mutex, |
| 131 | std::shared_ptr<HandheldConfig> handheld_config); | ||
| 149 | 132 | ||
| 150 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); | 133 | AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); |
| 151 | 134 | ||
| @@ -161,18 +144,22 @@ public: | |||
| 161 | 144 | ||
| 162 | Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; | 145 | Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; |
| 163 | 146 | ||
| 164 | private: | 147 | NpadVibration* GetVibrationHandler(); |
| 165 | struct VibrationData { | 148 | std::vector<NpadVibrationBase*> GetAllVibrationDevices(); |
| 166 | bool device_mounted{}; | 149 | NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 167 | Core::HID::VibrationValue latest_vibration_value{}; | 150 | NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 168 | std::chrono::steady_clock::time_point last_vibration_timepoint{}; | 151 | NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 169 | }; | 152 | NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle); |
| 153 | |||
| 154 | void UpdateHandheldAbstractState(); | ||
| 155 | |||
| 156 | void EnableAppletToGetInput(u64 aruid); | ||
| 170 | 157 | ||
| 158 | private: | ||
| 171 | struct NpadControllerData { | 159 | struct NpadControllerData { |
| 172 | NpadInternalState* shared_memory = nullptr; | 160 | NpadInternalState* shared_memory = nullptr; |
| 173 | Core::HID::EmulatedController* device = nullptr; | 161 | Core::HID::EmulatedController* device = nullptr; |
| 174 | 162 | ||
| 175 | std::array<VibrationData, 2> vibration{}; | ||
| 176 | bool is_connected{}; | 163 | bool is_connected{}; |
| 177 | 164 | ||
| 178 | // Dual joycons can have only one side connected | 165 | // Dual joycons can have only one side connected |
| @@ -192,10 +179,6 @@ private: | |||
| 192 | void WriteEmptyEntry(NpadInternalState* npad); | 179 | void WriteEmptyEntry(NpadInternalState* npad); |
| 193 | 180 | ||
| 194 | NpadControllerData& GetControllerFromHandle( | 181 | NpadControllerData& GetControllerFromHandle( |
| 195 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle); | ||
| 196 | const NpadControllerData& GetControllerFromHandle( | ||
| 197 | u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const; | ||
| 198 | NpadControllerData& GetControllerFromHandle( | ||
| 199 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); | 182 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); |
| 200 | const NpadControllerData& GetControllerFromHandle( | 183 | const NpadControllerData& GetControllerFromHandle( |
| 201 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; | 184 | u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; |
| @@ -215,11 +198,13 @@ private: | |||
| 215 | mutable std::mutex mutex; | 198 | mutable std::mutex mutex; |
| 216 | NPadResource npad_resource; | 199 | NPadResource npad_resource; |
| 217 | AppletResourceHolder applet_resource_holder{}; | 200 | AppletResourceHolder applet_resource_holder{}; |
| 201 | std::array<AbstractPad, MaxSupportedNpadIdTypes> abstracted_pads; | ||
| 202 | NpadVibration vibration_handler{}; | ||
| 203 | |||
| 218 | Kernel::KEvent* input_event{nullptr}; | 204 | Kernel::KEvent* input_event{nullptr}; |
| 219 | std::mutex* input_mutex{nullptr}; | 205 | std::mutex* input_mutex{nullptr}; |
| 220 | 206 | ||
| 221 | std::atomic<u64> press_state{}; | 207 | std::atomic<u64> press_state{}; |
| 222 | bool permit_vibration_session_enabled; | ||
| 223 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> | 208 | std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> |
| 224 | controller_data{}; | 209 | controller_data{}; |
| 225 | }; | 210 | }; |
diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h index fd86c8e40..92700d69a 100644 --- a/src/hid_core/resources/npad/npad_types.h +++ b/src/hid_core/resources/npad/npad_types.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "hid_core/hid_types.h" | 9 | #include "hid_core/hid_types.h" |
| 10 | 10 | ||
| 11 | namespace Core::HID { | ||
| 12 | class EmulatedController; | ||
| 13 | } | ||
| 14 | |||
| 11 | namespace Service::HID { | 15 | namespace Service::HID { |
| 12 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; | 16 | static constexpr std::size_t MaxSupportedNpadIdTypes = 10; |
| 13 | static constexpr std::size_t StyleIndexCount = 7; | 17 | static constexpr std::size_t StyleIndexCount = 7; |
| @@ -348,7 +352,7 @@ struct IAbstractedPad { | |||
| 348 | u8 indicator; | 352 | u8 indicator; |
| 349 | std::vector<f32> virtual_six_axis_sensor_acceleration; | 353 | std::vector<f32> virtual_six_axis_sensor_acceleration; |
| 350 | std::vector<f32> virtual_six_axis_sensor_angle; | 354 | std::vector<f32> virtual_six_axis_sensor_angle; |
| 351 | u64 xcd_handle; | 355 | Core::HID::EmulatedController* xcd_handle; |
| 352 | u64 color; | 356 | u64 color; |
| 353 | }; | 357 | }; |
| 354 | } // namespace Service::HID | 358 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp index 7056e8eab..05aad4c54 100644 --- a/src/hid_core/resources/npad/npad_vibration.cpp +++ b/src/hid_core/resources/npad/npad_vibration.cpp | |||
| @@ -77,4 +77,8 @@ Result NpadVibration::EndPermitVibrationSession() { | |||
| 77 | return ResultSuccess; | 77 | return ResultSuccess; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | u64 NpadVibration::GetSessionAruid() const { | ||
| 81 | return session_aruid; | ||
| 82 | } | ||
| 83 | |||
| 80 | } // namespace Service::HID | 84 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h index 0748aeffc..d5a95f2a0 100644 --- a/src/hid_core/resources/npad/npad_vibration.h +++ b/src/hid_core/resources/npad/npad_vibration.h | |||
| @@ -25,6 +25,8 @@ public: | |||
| 25 | Result BeginPermitVibrationSession(u64 aruid); | 25 | Result BeginPermitVibrationSession(u64 aruid); |
| 26 | Result EndPermitVibrationSession(); | 26 | Result EndPermitVibrationSession(); |
| 27 | 27 | ||
| 28 | u64 GetSessionAruid() const; | ||
| 29 | |||
| 28 | private: | 30 | private: |
| 29 | f32 volume{}; | 31 | f32 volume{}; |
| 30 | u64 session_aruid{}; | 32 | u64 session_aruid{}; |
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp index f01f81b9a..ad42b9d66 100644 --- a/src/hid_core/resources/vibration/gc_vibration_device.cpp +++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,24 +11,25 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadGcVibrationDevice::NpadGcVibrationDevice() {} | 12 | NpadGcVibrationDevice::NpadGcVibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadGcVibrationDevice::IncrementRefCounter() { | 14 | Result NpadGcVibrationDevice::Activate() { |
| 14 | if (ref_counter == 0 && is_mounted) { | 15 | if (ref_counter == 0 && is_mounted) { |
| 15 | f32 volume = 1.0f; | 16 | f32 volume = 1.0f; |
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | 17 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 17 | if (result.IsSuccess()) { | 18 | if (result.IsSuccess()) { |
| 18 | // TODO: SendVibrationGcErmCommand | 19 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); |
| 19 | } | 20 | } |
| 20 | } | 21 | } |
| 22 | |||
| 21 | ref_counter++; | 23 | ref_counter++; |
| 22 | return ResultSuccess; | 24 | return ResultSuccess; |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | Result NpadGcVibrationDevice::DecrementRefCounter() { | 27 | Result NpadGcVibrationDevice::Deactivate() { |
| 26 | if (ref_counter == 1 && !is_mounted) { | 28 | if (ref_counter == 1 && is_mounted) { |
| 27 | f32 volume = 1.0f; | 29 | f32 volume = 1.0f; |
| 28 | const auto result = vibration_handler->GetVibrationVolume(volume); | 30 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 29 | if (result.IsSuccess()) { | 31 | if (result.IsSuccess()) { |
| 30 | // TODO: SendVibrationGcErmCommand | 32 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); |
| 31 | } | 33 | } |
| 32 | } | 34 | } |
| 33 | 35 | ||
| @@ -38,6 +40,48 @@ Result NpadGcVibrationDevice::DecrementRefCounter() { | |||
| 38 | return ResultSuccess; | 40 | return ResultSuccess; |
| 39 | } | 41 | } |
| 40 | 42 | ||
| 43 | Result NpadGcVibrationDevice::Mount(IAbstractedPad& abstracted_pad, u32 slot, | ||
| 44 | NpadVibration* handler) { | ||
| 45 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 46 | return ResultSuccess; | ||
| 47 | } | ||
| 48 | |||
| 49 | // TODO: This device doesn't use a xcd handle instead has an GC adapter handle. This is just to | ||
| 50 | // keep compatibility with the front end. | ||
| 51 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 52 | adapter_slot = slot; | ||
| 53 | vibration_handler = handler; | ||
| 54 | is_mounted = true; | ||
| 55 | |||
| 56 | if (ref_counter == 0) { | ||
| 57 | return ResultSuccess; | ||
| 58 | } | ||
| 59 | |||
| 60 | f32 volume{1.0f}; | ||
| 61 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 62 | if (result.IsSuccess()) { | ||
| 63 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); | ||
| 64 | } | ||
| 65 | |||
| 66 | return ResultSuccess; | ||
| 67 | } | ||
| 68 | |||
| 69 | Result NpadGcVibrationDevice::Unmount() { | ||
| 70 | if (ref_counter == 0 || !is_mounted) { | ||
| 71 | is_mounted = false; | ||
| 72 | return ResultSuccess; | ||
| 73 | } | ||
| 74 | |||
| 75 | f32 volume{1.0f}; | ||
| 76 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 77 | if (result.IsSuccess()) { | ||
| 78 | xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop); | ||
| 79 | } | ||
| 80 | |||
| 81 | is_mounted = false; | ||
| 82 | return ResultSuccess; | ||
| 83 | } | ||
| 84 | |||
| 41 | Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { | 85 | Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { |
| 42 | if (!is_mounted) { | 86 | if (!is_mounted) { |
| 43 | return ResultSuccess; | 87 | return ResultSuccess; |
| @@ -55,7 +99,7 @@ Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcEr | |||
| 55 | return ResultSuccess; | 99 | return ResultSuccess; |
| 56 | } | 100 | } |
| 57 | } | 101 | } |
| 58 | // TODO: SendVibrationGcErmCommand | 102 | xcd_handle->SetVibration(adapter_slot, command); |
| 59 | return ResultSuccess; | 103 | return ResultSuccess; |
| 60 | } | 104 | } |
| 61 | 105 | ||
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h index 87abca57d..c624cbb28 100644 --- a/src/hid_core/resources/vibration/gc_vibration_device.h +++ b/src/hid_core/resources/vibration/gc_vibration_device.h | |||
| @@ -20,12 +20,18 @@ class NpadGcVibrationDevice final : public NpadVibrationBase { | |||
| 20 | public: | 20 | public: |
| 21 | explicit NpadGcVibrationDevice(); | 21 | explicit NpadGcVibrationDevice(); |
| 22 | 22 | ||
| 23 | Result IncrementRefCounter() override; | 23 | Result Activate() override; |
| 24 | Result DecrementRefCounter() override; | 24 | Result Deactivate() override; |
| 25 | |||
| 26 | Result Mount(IAbstractedPad& abstracted_pad, u32 slot, NpadVibration* handler); | ||
| 27 | Result Unmount(); | ||
| 25 | 28 | ||
| 26 | Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); | 29 | Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); |
| 27 | 30 | ||
| 28 | Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); | 31 | Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); |
| 29 | Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); | 32 | Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); |
| 33 | |||
| 34 | private: | ||
| 35 | u32 adapter_slot; | ||
| 30 | }; | 36 | }; |
| 31 | } // namespace Service::HID | 37 | } // namespace Service::HID |
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp index 639f87abf..94ad37c8f 100644 --- a/src/hid_core/resources/vibration/n64_vibration_device.cpp +++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,12 +11,12 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadN64VibrationDevice::NpadN64VibrationDevice() {} | 12 | NpadN64VibrationDevice::NpadN64VibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadN64VibrationDevice::IncrementRefCounter() { | 14 | Result NpadN64VibrationDevice::Activate() { |
| 14 | if (ref_counter == 0 && is_mounted) { | 15 | if (ref_counter == 0 && is_mounted) { |
| 15 | f32 volume = 1.0f; | 16 | f32 volume = 1.0f; |
| 16 | const auto result = vibration_handler->GetVibrationVolume(volume); | 17 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 17 | if (result.IsSuccess()) { | 18 | if (result.IsSuccess()) { |
| 18 | // TODO: SendVibrationInBool | 19 | xcd_handle->SetVibration(false); |
| 19 | } | 20 | } |
| 20 | } | 21 | } |
| 21 | 22 | ||
| @@ -23,19 +24,12 @@ Result NpadN64VibrationDevice::IncrementRefCounter() { | |||
| 23 | return ResultSuccess; | 24 | return ResultSuccess; |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | Result NpadN64VibrationDevice::DecrementRefCounter() { | 27 | Result NpadN64VibrationDevice::Deactivate() { |
| 27 | if (ref_counter == 1) { | 28 | if (ref_counter == 1 && is_mounted) { |
| 28 | if (!is_mounted) { | ||
| 29 | ref_counter = 0; | ||
| 30 | if (is_mounted != false) { | ||
| 31 | // TODO: SendVibrationInBool | ||
| 32 | } | ||
| 33 | return ResultSuccess; | ||
| 34 | } | ||
| 35 | f32 volume = 1.0f; | 29 | f32 volume = 1.0f; |
| 36 | const auto result = vibration_handler->GetVibrationVolume(volume); | 30 | const auto result = vibration_handler->GetVibrationVolume(volume); |
| 37 | if (result.IsSuccess()) { | 31 | if (result.IsSuccess()) { |
| 38 | // TODO | 32 | xcd_handle->SetVibration(false); |
| 39 | } | 33 | } |
| 40 | } | 34 | } |
| 41 | 35 | ||
| @@ -46,6 +40,43 @@ Result NpadN64VibrationDevice::DecrementRefCounter() { | |||
| 46 | return ResultSuccess; | 40 | return ResultSuccess; |
| 47 | } | 41 | } |
| 48 | 42 | ||
| 43 | Result NpadN64VibrationDevice::Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler) { | ||
| 44 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 45 | return ResultSuccess; | ||
| 46 | } | ||
| 47 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 48 | vibration_handler = handler; | ||
| 49 | is_mounted = true; | ||
| 50 | |||
| 51 | if (ref_counter == 0) { | ||
| 52 | return ResultSuccess; | ||
| 53 | } | ||
| 54 | |||
| 55 | f32 volume{1.0f}; | ||
| 56 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 57 | if (result.IsSuccess()) { | ||
| 58 | xcd_handle->SetVibration(false); | ||
| 59 | } | ||
| 60 | |||
| 61 | return ResultSuccess; | ||
| 62 | } | ||
| 63 | |||
| 64 | Result NpadN64VibrationDevice::Unmount() { | ||
| 65 | if (ref_counter == 0 || !is_mounted) { | ||
| 66 | is_mounted = false; | ||
| 67 | return ResultSuccess; | ||
| 68 | } | ||
| 69 | |||
| 70 | f32 volume{1.0f}; | ||
| 71 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 72 | if (result.IsSuccess()) { | ||
| 73 | xcd_handle->SetVibration(false); | ||
| 74 | } | ||
| 75 | |||
| 76 | is_mounted = false; | ||
| 77 | return ResultSuccess; | ||
| 78 | } | ||
| 79 | |||
| 49 | Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { | 80 | Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { |
| 50 | if (ref_counter < 1) { | 81 | if (ref_counter < 1) { |
| 51 | return ResultVibrationNotInitialized; | 82 | return ResultVibrationNotInitialized; |
| @@ -56,7 +87,7 @@ Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { | |||
| 56 | if (result.IsError()) { | 87 | if (result.IsError()) { |
| 57 | return result; | 88 | return result; |
| 58 | } | 89 | } |
| 59 | // TODO: SendVibrationInBool | 90 | xcd_handle->SetVibration(false); |
| 60 | } | 91 | } |
| 61 | return ResultSuccess; | 92 | return ResultSuccess; |
| 62 | } | 93 | } |
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h index 54e6efc1a..09de7701c 100644 --- a/src/hid_core/resources/vibration/n64_vibration_device.h +++ b/src/hid_core/resources/vibration/n64_vibration_device.h | |||
| @@ -14,14 +14,18 @@ | |||
| 14 | 14 | ||
| 15 | namespace Service::HID { | 15 | namespace Service::HID { |
| 16 | class NpadVibration; | 16 | class NpadVibration; |
| 17 | struct IAbstractedPad; | ||
| 17 | 18 | ||
| 18 | /// Handles Npad request from HID interfaces | 19 | /// Handles Npad request from HID interfaces |
| 19 | class NpadN64VibrationDevice final : public NpadVibrationBase { | 20 | class NpadN64VibrationDevice final : public NpadVibrationBase { |
| 20 | public: | 21 | public: |
| 21 | explicit NpadN64VibrationDevice(); | 22 | explicit NpadN64VibrationDevice(); |
| 22 | 23 | ||
| 23 | Result IncrementRefCounter() override; | 24 | Result Activate() override; |
| 24 | Result DecrementRefCounter() override; | 25 | Result Deactivate() override; |
| 26 | |||
| 27 | Result Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler); | ||
| 28 | Result Unmount(); | ||
| 25 | 29 | ||
| 26 | Result SendValueInBool(bool is_vibrating); | 30 | Result SendValueInBool(bool is_vibrating); |
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | 31 | Result SendVibrationNotificationPattern(u32 pattern); |
diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp index 350f349c2..f28d30406 100644 --- a/src/hid_core/resources/vibration/vibration_base.cpp +++ b/src/hid_core/resources/vibration/vibration_base.cpp | |||
| @@ -10,12 +10,12 @@ namespace Service::HID { | |||
| 10 | 10 | ||
| 11 | NpadVibrationBase::NpadVibrationBase() {} | 11 | NpadVibrationBase::NpadVibrationBase() {} |
| 12 | 12 | ||
| 13 | Result NpadVibrationBase::IncrementRefCounter() { | 13 | Result NpadVibrationBase::Activate() { |
| 14 | ref_counter++; | 14 | ref_counter++; |
| 15 | return ResultSuccess; | 15 | return ResultSuccess; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | Result NpadVibrationBase::DecrementRefCounter() { | 18 | Result NpadVibrationBase::Deactivate() { |
| 19 | if (ref_counter > 0) { | 19 | if (ref_counter > 0) { |
| 20 | ref_counter--; | 20 | ref_counter--; |
| 21 | } | 21 | } |
diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h index c6c5fc4d9..69c26e669 100644 --- a/src/hid_core/resources/vibration/vibration_base.h +++ b/src/hid_core/resources/vibration/vibration_base.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "core/hle/result.h" | 7 | #include "core/hle/result.h" |
| 8 | 8 | ||
| 9 | namespace Core::HID { | ||
| 10 | class EmulatedController; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Service::HID { | 13 | namespace Service::HID { |
| 10 | class NpadVibration; | 14 | class NpadVibration; |
| 11 | 15 | ||
| @@ -14,13 +18,13 @@ class NpadVibrationBase { | |||
| 14 | public: | 18 | public: |
| 15 | explicit NpadVibrationBase(); | 19 | explicit NpadVibrationBase(); |
| 16 | 20 | ||
| 17 | virtual Result IncrementRefCounter(); | 21 | virtual Result Activate(); |
| 18 | virtual Result DecrementRefCounter(); | 22 | virtual Result Deactivate(); |
| 19 | 23 | ||
| 20 | bool IsVibrationMounted() const; | 24 | bool IsVibrationMounted() const; |
| 21 | 25 | ||
| 22 | protected: | 26 | protected: |
| 23 | u64 xcd_handle{}; | 27 | Core::HID::EmulatedController* xcd_handle{nullptr}; |
| 24 | s32 ref_counter{}; | 28 | s32 ref_counter{}; |
| 25 | bool is_mounted{}; | 29 | bool is_mounted{}; |
| 26 | NpadVibration* vibration_handler{nullptr}; | 30 | NpadVibration* vibration_handler{nullptr}; |
diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp index 888c3a7ed..08b14591f 100644 --- a/src/hid_core/resources/vibration/vibration_device.cpp +++ b/src/hid_core/resources/vibration/vibration_device.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include "hid_core/frontend/emulated_controller.h" | ||
| 4 | #include "hid_core/hid_result.h" | 5 | #include "hid_core/hid_result.h" |
| 5 | #include "hid_core/resources/npad/npad_types.h" | 6 | #include "hid_core/resources/npad/npad_types.h" |
| 6 | #include "hid_core/resources/npad/npad_vibration.h" | 7 | #include "hid_core/resources/npad/npad_vibration.h" |
| @@ -10,12 +11,30 @@ namespace Service::HID { | |||
| 10 | 11 | ||
| 11 | NpadVibrationDevice::NpadVibrationDevice() {} | 12 | NpadVibrationDevice::NpadVibrationDevice() {} |
| 12 | 13 | ||
| 13 | Result NpadVibrationDevice::IncrementRefCounter() { | 14 | Result NpadVibrationDevice::Activate() { |
| 15 | if (ref_counter == 0 && is_mounted) { | ||
| 16 | f32 volume = 1.0f; | ||
| 17 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 18 | if (result.IsSuccess()) { | ||
| 19 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 20 | // TODO: SendNotificationPattern; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 14 | ref_counter++; | 24 | ref_counter++; |
| 15 | return ResultSuccess; | 25 | return ResultSuccess; |
| 16 | } | 26 | } |
| 17 | 27 | ||
| 18 | Result NpadVibrationDevice::DecrementRefCounter() { | 28 | Result NpadVibrationDevice::Deactivate() { |
| 29 | if (ref_counter == 1 && is_mounted) { | ||
| 30 | f32 volume = 1.0f; | ||
| 31 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 32 | if (result.IsSuccess()) { | ||
| 33 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 34 | // TODO: SendNotificationPattern; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 19 | if (ref_counter > 0) { | 38 | if (ref_counter > 0) { |
| 20 | ref_counter--; | 39 | ref_counter--; |
| 21 | } | 40 | } |
| @@ -23,6 +42,45 @@ Result NpadVibrationDevice::DecrementRefCounter() { | |||
| 23 | return ResultSuccess; | 42 | return ResultSuccess; |
| 24 | } | 43 | } |
| 25 | 44 | ||
| 45 | Result NpadVibrationDevice::Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, | ||
| 46 | NpadVibration* handler) { | ||
| 47 | if (!abstracted_pad.internal_flags.is_connected) { | ||
| 48 | return ResultSuccess; | ||
| 49 | } | ||
| 50 | xcd_handle = abstracted_pad.xcd_handle; | ||
| 51 | device_index = index; | ||
| 52 | vibration_handler = handler; | ||
| 53 | is_mounted = true; | ||
| 54 | |||
| 55 | if (ref_counter == 0) { | ||
| 56 | return ResultSuccess; | ||
| 57 | } | ||
| 58 | |||
| 59 | f32 volume{1.0f}; | ||
| 60 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 61 | if (result.IsSuccess()) { | ||
| 62 | xcd_handle->SetVibration(false); | ||
| 63 | } | ||
| 64 | |||
| 65 | return ResultSuccess; | ||
| 66 | } | ||
| 67 | |||
| 68 | Result NpadVibrationDevice::Unmount() { | ||
| 69 | if (ref_counter == 0 || !is_mounted) { | ||
| 70 | is_mounted = false; | ||
| 71 | return ResultSuccess; | ||
| 72 | } | ||
| 73 | |||
| 74 | f32 volume{1.0f}; | ||
| 75 | const auto result = vibration_handler->GetVibrationVolume(volume); | ||
| 76 | if (result.IsSuccess()) { | ||
| 77 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); | ||
| 78 | } | ||
| 79 | |||
| 80 | is_mounted = false; | ||
| 81 | return ResultSuccess; | ||
| 82 | } | ||
| 83 | |||
| 26 | Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { | 84 | Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { |
| 27 | if (ref_counter == 0) { | 85 | if (ref_counter == 0) { |
| 28 | return ResultVibrationNotInitialized; | 86 | return ResultVibrationNotInitialized; |
| @@ -37,7 +95,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& | |||
| 37 | return result; | 95 | return result; |
| 38 | } | 96 | } |
| 39 | if (volume <= 0.0f) { | 97 | if (volume <= 0.0f) { |
| 40 | // TODO: SendVibrationValue | 98 | xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 41 | return ResultSuccess; | 99 | return ResultSuccess; |
| 42 | } | 100 | } |
| 43 | 101 | ||
| @@ -45,7 +103,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& | |||
| 45 | vibration_value.high_amplitude *= volume; | 103 | vibration_value.high_amplitude *= volume; |
| 46 | vibration_value.low_amplitude *= volume; | 104 | vibration_value.low_amplitude *= volume; |
| 47 | 105 | ||
| 48 | // TODO: SendVibrationValue | 106 | xcd_handle->SetVibration(device_index, vibration_value); |
| 49 | return ResultSuccess; | 107 | return ResultSuccess; |
| 50 | } | 108 | } |
| 51 | 109 | ||
| @@ -63,11 +121,11 @@ Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u3 | |||
| 63 | pattern = 0; | 121 | pattern = 0; |
| 64 | } | 122 | } |
| 65 | 123 | ||
| 66 | // return xcd_handle->SendVibrationNotificationPattern(pattern); | 124 | // TODO: SendVibrationNotificationPattern; |
| 67 | return ResultSuccess; | 125 | return ResultSuccess; |
| 68 | } | 126 | } |
| 69 | 127 | ||
| 70 | Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) { | 128 | Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) const { |
| 71 | if (ref_counter < 1) { | 129 | if (ref_counter < 1) { |
| 72 | return ResultVibrationNotInitialized; | 130 | return ResultVibrationNotInitialized; |
| 73 | } | 131 | } |
| @@ -77,7 +135,7 @@ Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& o | |||
| 77 | return ResultSuccess; | 135 | return ResultSuccess; |
| 78 | } | 136 | } |
| 79 | 137 | ||
| 80 | // TODO: SendVibrationValue | 138 | out_value = xcd_handle->GetActualVibrationValue(device_index); |
| 81 | return ResultSuccess; | 139 | return ResultSuccess; |
| 82 | } | 140 | } |
| 83 | 141 | ||
diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h index 3574ad60b..c2f9891d3 100644 --- a/src/hid_core/resources/vibration/vibration_device.h +++ b/src/hid_core/resources/vibration/vibration_device.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "hid_core/resources/npad/npad_types.h" | 12 | #include "hid_core/resources/npad/npad_types.h" |
| 13 | #include "hid_core/resources/vibration/vibration_base.h" | 13 | #include "hid_core/resources/vibration/vibration_base.h" |
| 14 | 14 | ||
| 15 | namespace Core::HID { | ||
| 16 | enum class DeviceIndex : u8; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Service::HID { | 19 | namespace Service::HID { |
| 16 | class NpadVibration; | 20 | class NpadVibration; |
| 17 | 21 | ||
| @@ -20,16 +24,20 @@ class NpadVibrationDevice final : public NpadVibrationBase { | |||
| 20 | public: | 24 | public: |
| 21 | explicit NpadVibrationDevice(); | 25 | explicit NpadVibrationDevice(); |
| 22 | 26 | ||
| 23 | Result IncrementRefCounter(); | 27 | Result Activate(); |
| 24 | Result DecrementRefCounter(); | 28 | Result Deactivate(); |
| 29 | |||
| 30 | Result Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index, | ||
| 31 | NpadVibration* handler); | ||
| 32 | Result Unmount(); | ||
| 25 | 33 | ||
| 26 | Result SendVibrationValue(const Core::HID::VibrationValue& value); | 34 | Result SendVibrationValue(const Core::HID::VibrationValue& value); |
| 27 | Result SendVibrationNotificationPattern(u32 pattern); | 35 | Result SendVibrationNotificationPattern(u32 pattern); |
| 28 | 36 | ||
| 29 | Result GetActualVibrationValue(Core::HID::VibrationValue& out_value); | 37 | Result GetActualVibrationValue(Core::HID::VibrationValue& out_value) const; |
| 30 | 38 | ||
| 31 | private: | 39 | private: |
| 32 | u32 device_index{}; | 40 | Core::HID::DeviceIndex device_index{}; |
| 33 | }; | 41 | }; |
| 34 | 42 | ||
| 35 | } // namespace Service::HID | 43 | } // namespace Service::HID |
diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp index f15fefe2d..45b1a91dc 100644 --- a/src/tests/video_core/memory_tracker.cpp +++ b/src/tests/video_core/memory_tracker.cpp | |||
| @@ -24,9 +24,8 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE; | |||
| 24 | class RasterizerInterface { | 24 | class RasterizerInterface { |
| 25 | public: | 25 | public: |
| 26 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { | 26 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { |
| 27 | const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS}; | 27 | const u64 page_start{addr >> Core::DEVICE_PAGEBITS}; |
| 28 | const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >> | 28 | const u64 page_end{(addr + size + Core::DEVICE_PAGESIZE - 1) >> Core::DEVICE_PAGEBITS}; |
| 29 | Core::Memory::YUZU_PAGEBITS}; | ||
| 30 | for (u64 page = page_start; page < page_end; ++page) { | 29 | for (u64 page = page_start; page < page_end; ++page) { |
| 31 | int& value = page_table[page]; | 30 | int& value = page_table[page]; |
| 32 | value += delta; | 31 | value += delta; |
| @@ -40,7 +39,7 @@ public: | |||
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | [[nodiscard]] int Count(VAddr addr) const noexcept { | 41 | [[nodiscard]] int Count(VAddr addr) const noexcept { |
| 43 | const auto it = page_table.find(addr >> Core::Memory::YUZU_PAGEBITS); | 42 | const auto it = page_table.find(addr >> Core::DEVICE_PAGEBITS); |
| 44 | return it == page_table.end() ? 0 : it->second; | 43 | return it == page_table.end() ? 0 : it->second; |
| 45 | } | 44 | } |
| 46 | 45 | ||
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index c22c7631c..5ed0ad0ed 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -71,6 +71,8 @@ add_library(video_core STATIC | |||
| 71 | host1x/ffmpeg/ffmpeg.h | 71 | host1x/ffmpeg/ffmpeg.h |
| 72 | host1x/control.cpp | 72 | host1x/control.cpp |
| 73 | host1x/control.h | 73 | host1x/control.h |
| 74 | host1x/gpu_device_memory_manager.cpp | ||
| 75 | host1x/gpu_device_memory_manager.h | ||
| 74 | host1x/host1x.cpp | 76 | host1x/host1x.cpp |
| 75 | host1x/host1x.h | 77 | host1x/host1x.h |
| 76 | host1x/nvdec.cpp | 78 | host1x/nvdec.cpp |
| @@ -93,6 +95,7 @@ add_library(video_core STATIC | |||
| 93 | gpu.h | 95 | gpu.h |
| 94 | gpu_thread.cpp | 96 | gpu_thread.cpp |
| 95 | gpu_thread.h | 97 | gpu_thread.h |
| 98 | guest_memory.h | ||
| 96 | invalidation_accumulator.h | 99 | invalidation_accumulator.h |
| 97 | memory_manager.cpp | 100 | memory_manager.cpp |
| 98 | memory_manager.h | 101 | memory_manager.h |
| @@ -105,8 +108,6 @@ add_library(video_core STATIC | |||
| 105 | query_cache/query_stream.h | 108 | query_cache/query_stream.h |
| 106 | query_cache/types.h | 109 | query_cache/types.h |
| 107 | query_cache.h | 110 | query_cache.h |
| 108 | rasterizer_accelerated.cpp | ||
| 109 | rasterizer_accelerated.h | ||
| 110 | rasterizer_interface.h | 111 | rasterizer_interface.h |
| 111 | renderer_base.cpp | 112 | renderer_base.cpp |
| 112 | renderer_base.h | 113 | renderer_base.h |
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index 0bb3bf8ae..40e98e395 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h | |||
| @@ -33,13 +33,12 @@ struct NullBufferParams {}; | |||
| 33 | * | 33 | * |
| 34 | * The buffer size and address is forcefully aligned to CPU page boundaries. | 34 | * The buffer size and address is forcefully aligned to CPU page boundaries. |
| 35 | */ | 35 | */ |
| 36 | template <class RasterizerInterface> | ||
| 37 | class BufferBase { | 36 | class BufferBase { |
| 38 | public: | 37 | public: |
| 39 | static constexpr u64 BASE_PAGE_BITS = 16; | 38 | static constexpr u64 BASE_PAGE_BITS = 16; |
| 40 | static constexpr u64 BASE_PAGE_SIZE = 1ULL << BASE_PAGE_BITS; | 39 | static constexpr u64 BASE_PAGE_SIZE = 1ULL << BASE_PAGE_BITS; |
| 41 | 40 | ||
| 42 | explicit BufferBase(RasterizerInterface& rasterizer_, VAddr cpu_addr_, u64 size_bytes_) | 41 | explicit BufferBase(VAddr cpu_addr_, u64 size_bytes_) |
| 43 | : cpu_addr{cpu_addr_}, size_bytes{size_bytes_} {} | 42 | : cpu_addr{cpu_addr_}, size_bytes{size_bytes_} {} |
| 44 | 43 | ||
| 45 | explicit BufferBase(NullBufferParams) {} | 44 | explicit BufferBase(NullBufferParams) {} |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6d1fc3887..b4bf369d1 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -8,16 +8,16 @@ | |||
| 8 | #include <numeric> | 8 | #include <numeric> |
| 9 | 9 | ||
| 10 | #include "video_core/buffer_cache/buffer_cache_base.h" | 10 | #include "video_core/buffer_cache/buffer_cache_base.h" |
| 11 | #include "video_core/guest_memory.h" | ||
| 12 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 11 | 13 | ||
| 12 | namespace VideoCommon { | 14 | namespace VideoCommon { |
| 13 | 15 | ||
| 14 | using Core::Memory::YUZU_PAGESIZE; | 16 | using Core::DEVICE_PAGESIZE; |
| 15 | 17 | ||
| 16 | template <class P> | 18 | template <class P> |
| 17 | BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_, | 19 | BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, Runtime& runtime_) |
| 18 | Core::Memory::Memory& cpu_memory_, Runtime& runtime_) | 20 | : runtime{runtime_}, device_memory{device_memory_}, memory_tracker{device_memory} { |
| 19 | : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, memory_tracker{ | ||
| 20 | rasterizer} { | ||
| 21 | // Ensure the first slot is used for the null buffer | 21 | // Ensure the first slot is used for the null buffer |
| 22 | void(slot_buffers.insert(runtime, NullBufferParams{})); | 22 | void(slot_buffers.insert(runtime, NullBufferParams{})); |
| 23 | common_ranges.clear(); | 23 | common_ranges.clear(); |
| @@ -29,17 +29,17 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_, | |||
| 29 | return; | 29 | return; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); | 32 | const s64 device_local_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); |
| 33 | const s64 min_spacing_expected = device_memory - 1_GiB; | 33 | const s64 min_spacing_expected = device_local_memory - 1_GiB; |
| 34 | const s64 min_spacing_critical = device_memory - 512_MiB; | 34 | const s64 min_spacing_critical = device_local_memory - 512_MiB; |
| 35 | const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD); | 35 | const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); |
| 36 | const s64 min_vacancy_expected = (6 * mem_threshold) / 10; | 36 | const s64 min_vacancy_expected = (6 * mem_threshold) / 10; |
| 37 | const s64 min_vacancy_critical = (3 * mem_threshold) / 10; | 37 | const s64 min_vacancy_critical = (3 * mem_threshold) / 10; |
| 38 | minimum_memory = static_cast<u64>( | 38 | minimum_memory = static_cast<u64>( |
| 39 | std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected), | 39 | std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), |
| 40 | DEFAULT_EXPECTED_MEMORY)); | 40 | DEFAULT_EXPECTED_MEMORY)); |
| 41 | critical_memory = static_cast<u64>( | 41 | critical_memory = static_cast<u64>( |
| 42 | std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical), | 42 | std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical), |
| 43 | DEFAULT_CRITICAL_MEMORY)); | 43 | DEFAULT_CRITICAL_MEMORY)); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| @@ -105,71 +105,71 @@ void BufferCache<P>::TickFrame() { | |||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | template <class P> | 107 | template <class P> |
| 108 | void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) { | 108 | void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) { |
| 109 | if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) { | 109 | if (memory_tracker.IsRegionGpuModified(device_addr, size)) { |
| 110 | const IntervalType subtract_interval{cpu_addr, cpu_addr + size}; | 110 | const IntervalType subtract_interval{device_addr, device_addr + size}; |
| 111 | ClearDownload(subtract_interval); | 111 | ClearDownload(subtract_interval); |
| 112 | common_ranges.subtract(subtract_interval); | 112 | common_ranges.subtract(subtract_interval); |
| 113 | } | 113 | } |
| 114 | memory_tracker.MarkRegionAsCpuModified(cpu_addr, size); | 114 | memory_tracker.MarkRegionAsCpuModified(device_addr, size); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | template <class P> | 117 | template <class P> |
| 118 | void BufferCache<P>::CachedWriteMemory(VAddr cpu_addr, u64 size) { | 118 | void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) { |
| 119 | const bool is_dirty = IsRegionRegistered(cpu_addr, size); | 119 | const bool is_dirty = IsRegionRegistered(device_addr, size); |
| 120 | if (!is_dirty) { | 120 | if (!is_dirty) { |
| 121 | return; | 121 | return; |
| 122 | } | 122 | } |
| 123 | VAddr aligned_start = Common::AlignDown(cpu_addr, YUZU_PAGESIZE); | 123 | DAddr aligned_start = Common::AlignDown(device_addr, DEVICE_PAGESIZE); |
| 124 | VAddr aligned_end = Common::AlignUp(cpu_addr + size, YUZU_PAGESIZE); | 124 | DAddr aligned_end = Common::AlignUp(device_addr + size, DEVICE_PAGESIZE); |
| 125 | if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { | 125 | if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { |
| 126 | WriteMemory(cpu_addr, size); | 126 | WriteMemory(device_addr, size); |
| 127 | return; | 127 | return; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | tmp_buffer.resize_destructive(size); | 130 | tmp_buffer.resize_destructive(size); |
| 131 | cpu_memory.ReadBlockUnsafe(cpu_addr, tmp_buffer.data(), size); | 131 | device_memory.ReadBlockUnsafe(device_addr, tmp_buffer.data(), size); |
| 132 | 132 | ||
| 133 | InlineMemoryImplementation(cpu_addr, size, tmp_buffer); | 133 | InlineMemoryImplementation(device_addr, size, tmp_buffer); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | template <class P> | 136 | template <class P> |
| 137 | bool BufferCache<P>::OnCPUWrite(VAddr cpu_addr, u64 size) { | 137 | bool BufferCache<P>::OnCPUWrite(DAddr device_addr, u64 size) { |
| 138 | const bool is_dirty = IsRegionRegistered(cpu_addr, size); | 138 | const bool is_dirty = IsRegionRegistered(device_addr, size); |
| 139 | if (!is_dirty) { | 139 | if (!is_dirty) { |
| 140 | return false; | 140 | return false; |
| 141 | } | 141 | } |
| 142 | if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) { | 142 | if (memory_tracker.IsRegionGpuModified(device_addr, size)) { |
| 143 | return true; | 143 | return true; |
| 144 | } | 144 | } |
| 145 | WriteMemory(cpu_addr, size); | 145 | WriteMemory(device_addr, size); |
| 146 | return false; | 146 | return false; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | template <class P> | 149 | template <class P> |
| 150 | std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(VAddr cpu_addr, | 150 | std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(DAddr device_addr, |
| 151 | u64 size) { | 151 | u64 size) { |
| 152 | std::optional<VideoCore::RasterizerDownloadArea> area{}; | 152 | std::optional<VideoCore::RasterizerDownloadArea> area{}; |
| 153 | area.emplace(); | 153 | area.emplace(); |
| 154 | VAddr cpu_addr_start_aligned = Common::AlignDown(cpu_addr, Core::Memory::YUZU_PAGESIZE); | 154 | DAddr device_addr_start_aligned = Common::AlignDown(device_addr, Core::DEVICE_PAGESIZE); |
| 155 | VAddr cpu_addr_end_aligned = Common::AlignUp(cpu_addr + size, Core::Memory::YUZU_PAGESIZE); | 155 | DAddr device_addr_end_aligned = Common::AlignUp(device_addr + size, Core::DEVICE_PAGESIZE); |
| 156 | area->start_address = cpu_addr_start_aligned; | 156 | area->start_address = device_addr_start_aligned; |
| 157 | area->end_address = cpu_addr_end_aligned; | 157 | area->end_address = device_addr_end_aligned; |
| 158 | if (memory_tracker.IsRegionPreflushable(cpu_addr, size)) { | 158 | if (memory_tracker.IsRegionPreflushable(device_addr, size)) { |
| 159 | area->preemtive = true; | 159 | area->preemtive = true; |
| 160 | return area; | 160 | return area; |
| 161 | }; | 161 | }; |
| 162 | area->preemtive = | 162 | area->preemtive = !IsRegionGpuModified(device_addr_start_aligned, |
| 163 | !IsRegionGpuModified(cpu_addr_start_aligned, cpu_addr_end_aligned - cpu_addr_start_aligned); | 163 | device_addr_end_aligned - device_addr_start_aligned); |
| 164 | memory_tracker.MarkRegionAsPreflushable(cpu_addr_start_aligned, | 164 | memory_tracker.MarkRegionAsPreflushable(device_addr_start_aligned, |
| 165 | cpu_addr_end_aligned - cpu_addr_start_aligned); | 165 | device_addr_end_aligned - device_addr_start_aligned); |
| 166 | return area; | 166 | return area; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | template <class P> | 169 | template <class P> |
| 170 | void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) { | 170 | void BufferCache<P>::DownloadMemory(DAddr device_addr, u64 size) { |
| 171 | ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { | 171 | ForEachBufferInRange(device_addr, size, [&](BufferId, Buffer& buffer) { |
| 172 | DownloadBufferMemory(buffer, cpu_addr, size); | 172 | DownloadBufferMemory(buffer, device_addr, size); |
| 173 | }); | 173 | }); |
| 174 | } | 174 | } |
| 175 | 175 | ||
| @@ -184,8 +184,8 @@ void BufferCache<P>::ClearDownload(IntervalType subtract_interval) { | |||
| 184 | 184 | ||
| 185 | template <class P> | 185 | template <class P> |
| 186 | bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { | 186 | bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { |
| 187 | const std::optional<VAddr> cpu_src_address = gpu_memory->GpuToCpuAddress(src_address); | 187 | const std::optional<DAddr> cpu_src_address = gpu_memory->GpuToCpuAddress(src_address); |
| 188 | const std::optional<VAddr> cpu_dest_address = gpu_memory->GpuToCpuAddress(dest_address); | 188 | const std::optional<DAddr> cpu_dest_address = gpu_memory->GpuToCpuAddress(dest_address); |
| 189 | if (!cpu_src_address || !cpu_dest_address) { | 189 | if (!cpu_src_address || !cpu_dest_address) { |
| 190 | return false; | 190 | return false; |
| 191 | } | 191 | } |
| @@ -216,10 +216,10 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am | |||
| 216 | }}; | 216 | }}; |
| 217 | 217 | ||
| 218 | boost::container::small_vector<IntervalType, 4> tmp_intervals; | 218 | boost::container::small_vector<IntervalType, 4> tmp_intervals; |
| 219 | auto mirror = [&](VAddr base_address, VAddr base_address_end) { | 219 | auto mirror = [&](DAddr base_address, DAddr base_address_end) { |
| 220 | const u64 size = base_address_end - base_address; | 220 | const u64 size = base_address_end - base_address; |
| 221 | const VAddr diff = base_address - *cpu_src_address; | 221 | const DAddr diff = base_address - *cpu_src_address; |
| 222 | const VAddr new_base_address = *cpu_dest_address + diff; | 222 | const DAddr new_base_address = *cpu_dest_address + diff; |
| 223 | const IntervalType add_interval{new_base_address, new_base_address + size}; | 223 | const IntervalType add_interval{new_base_address, new_base_address + size}; |
| 224 | tmp_intervals.push_back(add_interval); | 224 | tmp_intervals.push_back(add_interval); |
| 225 | uncommitted_ranges.add(add_interval); | 225 | uncommitted_ranges.add(add_interval); |
| @@ -239,15 +239,15 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am | |||
| 239 | memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount); | 239 | memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | Core::Memory::CpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadWrite> tmp( | 242 | Tegra::Memory::DeviceGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadWrite> |
| 243 | cpu_memory, *cpu_src_address, amount, &tmp_buffer); | 243 | tmp(device_memory, *cpu_src_address, amount, &tmp_buffer); |
| 244 | tmp.SetAddressAndSize(*cpu_dest_address, amount); | 244 | tmp.SetAddressAndSize(*cpu_dest_address, amount); |
| 245 | return true; | 245 | return true; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | template <class P> | 248 | template <class P> |
| 249 | bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) { | 249 | bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) { |
| 250 | const std::optional<VAddr> cpu_dst_address = gpu_memory->GpuToCpuAddress(dst_address); | 250 | const std::optional<DAddr> cpu_dst_address = gpu_memory->GpuToCpuAddress(dst_address); |
| 251 | if (!cpu_dst_address) { | 251 | if (!cpu_dst_address) { |
| 252 | return false; | 252 | return false; |
| 253 | } | 253 | } |
| @@ -273,23 +273,23 @@ template <class P> | |||
| 273 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size, | 273 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size, |
| 274 | ObtainBufferSynchronize sync_info, | 274 | ObtainBufferSynchronize sync_info, |
| 275 | ObtainBufferOperation post_op) { | 275 | ObtainBufferOperation post_op) { |
| 276 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 276 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 277 | if (!cpu_addr) { | 277 | if (!device_addr) { |
| 278 | return {&slot_buffers[NULL_BUFFER_ID], 0}; | 278 | return {&slot_buffers[NULL_BUFFER_ID], 0}; |
| 279 | } | 279 | } |
| 280 | return ObtainCPUBuffer(*cpu_addr, size, sync_info, post_op); | 280 | return ObtainCPUBuffer(*device_addr, size, sync_info, post_op); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | template <class P> | 283 | template <class P> |
| 284 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( | 284 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( |
| 285 | VAddr cpu_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) { | 285 | DAddr device_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) { |
| 286 | const BufferId buffer_id = FindBuffer(cpu_addr, size); | 286 | const BufferId buffer_id = FindBuffer(device_addr, size); |
| 287 | Buffer& buffer = slot_buffers[buffer_id]; | 287 | Buffer& buffer = slot_buffers[buffer_id]; |
| 288 | 288 | ||
| 289 | // synchronize op | 289 | // synchronize op |
| 290 | switch (sync_info) { | 290 | switch (sync_info) { |
| 291 | case ObtainBufferSynchronize::FullSynchronize: | 291 | case ObtainBufferSynchronize::FullSynchronize: |
| 292 | SynchronizeBuffer(buffer, cpu_addr, size); | 292 | SynchronizeBuffer(buffer, device_addr, size); |
| 293 | break; | 293 | break; |
| 294 | default: | 294 | default: |
| 295 | break; | 295 | break; |
| @@ -297,12 +297,12 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( | |||
| 297 | 297 | ||
| 298 | switch (post_op) { | 298 | switch (post_op) { |
| 299 | case ObtainBufferOperation::MarkAsWritten: | 299 | case ObtainBufferOperation::MarkAsWritten: |
| 300 | MarkWrittenBuffer(buffer_id, cpu_addr, size); | 300 | MarkWrittenBuffer(buffer_id, device_addr, size); |
| 301 | break; | 301 | break; |
| 302 | case ObtainBufferOperation::DiscardWrite: { | 302 | case ObtainBufferOperation::DiscardWrite: { |
| 303 | VAddr cpu_addr_start = Common::AlignDown(cpu_addr, 64); | 303 | DAddr device_addr_start = Common::AlignDown(device_addr, 64); |
| 304 | VAddr cpu_addr_end = Common::AlignUp(cpu_addr + size, 64); | 304 | DAddr device_addr_end = Common::AlignUp(device_addr + size, 64); |
| 305 | IntervalType interval{cpu_addr_start, cpu_addr_end}; | 305 | IntervalType interval{device_addr_start, device_addr_end}; |
| 306 | ClearDownload(interval); | 306 | ClearDownload(interval); |
| 307 | common_ranges.subtract(interval); | 307 | common_ranges.subtract(interval); |
| 308 | break; | 308 | break; |
| @@ -311,15 +311,15 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( | |||
| 311 | break; | 311 | break; |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | return {&buffer, buffer.Offset(cpu_addr)}; | 314 | return {&buffer, buffer.Offset(device_addr)}; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | template <class P> | 317 | template <class P> |
| 318 | void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, | 318 | void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, |
| 319 | u32 size) { | 319 | u32 size) { |
| 320 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 320 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 321 | const Binding binding{ | 321 | const Binding binding{ |
| 322 | .cpu_addr = *cpu_addr, | 322 | .device_addr = *device_addr, |
| 323 | .size = size, | 323 | .size = size, |
| 324 | .buffer_id = BufferId{}, | 324 | .buffer_id = BufferId{}, |
| 325 | }; | 325 | }; |
| @@ -555,16 +555,17 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 555 | for (const IntervalSet& intervals : committed_ranges) { | 555 | for (const IntervalSet& intervals : committed_ranges) { |
| 556 | for (auto& interval : intervals) { | 556 | for (auto& interval : intervals) { |
| 557 | const std::size_t size = interval.upper() - interval.lower(); | 557 | const std::size_t size = interval.upper() - interval.lower(); |
| 558 | const VAddr cpu_addr = interval.lower(); | 558 | const DAddr device_addr = interval.lower(); |
| 559 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { | 559 | ForEachBufferInRange(device_addr, size, [&](BufferId buffer_id, Buffer& buffer) { |
| 560 | const VAddr buffer_start = buffer.CpuAddr(); | 560 | const DAddr buffer_start = buffer.CpuAddr(); |
| 561 | const VAddr buffer_end = buffer_start + buffer.SizeBytes(); | 561 | const DAddr buffer_end = buffer_start + buffer.SizeBytes(); |
| 562 | const VAddr new_start = std::max(buffer_start, cpu_addr); | 562 | const DAddr new_start = std::max(buffer_start, device_addr); |
| 563 | const VAddr new_end = std::min(buffer_end, cpu_addr + size); | 563 | const DAddr new_end = std::min(buffer_end, device_addr + size); |
| 564 | memory_tracker.ForEachDownloadRange( | 564 | memory_tracker.ForEachDownloadRange( |
| 565 | new_start, new_end - new_start, false, [&](u64 cpu_addr_out, u64 range_size) { | 565 | new_start, new_end - new_start, false, |
| 566 | const VAddr buffer_addr = buffer.CpuAddr(); | 566 | [&](u64 device_addr_out, u64 range_size) { |
| 567 | const auto add_download = [&](VAddr start, VAddr end) { | 567 | const DAddr buffer_addr = buffer.CpuAddr(); |
| 568 | const auto add_download = [&](DAddr start, DAddr end) { | ||
| 568 | const u64 new_offset = start - buffer_addr; | 569 | const u64 new_offset = start - buffer_addr; |
| 569 | const u64 new_size = end - start; | 570 | const u64 new_size = end - start; |
| 570 | downloads.push_back({ | 571 | downloads.push_back({ |
| @@ -582,7 +583,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 582 | largest_copy = std::max(largest_copy, new_size); | 583 | largest_copy = std::max(largest_copy, new_size); |
| 583 | }; | 584 | }; |
| 584 | 585 | ||
| 585 | ForEachInRangeSet(common_ranges, cpu_addr_out, range_size, add_download); | 586 | ForEachInRangeSet(common_ranges, device_addr_out, range_size, add_download); |
| 586 | }); | 587 | }); |
| 587 | }); | 588 | }); |
| 588 | } | 589 | } |
| @@ -605,8 +606,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 605 | BufferCopy second_copy{copy}; | 606 | BufferCopy second_copy{copy}; |
| 606 | Buffer& buffer = slot_buffers[buffer_id]; | 607 | Buffer& buffer = slot_buffers[buffer_id]; |
| 607 | second_copy.src_offset = static_cast<size_t>(buffer.CpuAddr()) + copy.src_offset; | 608 | second_copy.src_offset = static_cast<size_t>(buffer.CpuAddr()) + copy.src_offset; |
| 608 | VAddr orig_cpu_addr = static_cast<VAddr>(second_copy.src_offset); | 609 | DAddr orig_device_addr = static_cast<DAddr>(second_copy.src_offset); |
| 609 | const IntervalType base_interval{orig_cpu_addr, orig_cpu_addr + copy.size}; | 610 | const IntervalType base_interval{orig_device_addr, orig_device_addr + copy.size}; |
| 610 | async_downloads += std::make_pair(base_interval, 1); | 611 | async_downloads += std::make_pair(base_interval, 1); |
| 611 | buffer.MarkUsage(copy.src_offset, copy.size); | 612 | buffer.MarkUsage(copy.src_offset, copy.size); |
| 612 | runtime.CopyBuffer(download_staging.buffer, buffer, copies, false); | 613 | runtime.CopyBuffer(download_staging.buffer, buffer, copies, false); |
| @@ -635,11 +636,11 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 635 | runtime.Finish(); | 636 | runtime.Finish(); |
| 636 | for (const auto& [copy, buffer_id] : downloads) { | 637 | for (const auto& [copy, buffer_id] : downloads) { |
| 637 | const Buffer& buffer = slot_buffers[buffer_id]; | 638 | const Buffer& buffer = slot_buffers[buffer_id]; |
| 638 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; | 639 | const DAddr device_addr = buffer.CpuAddr() + copy.src_offset; |
| 639 | // Undo the modified offset | 640 | // Undo the modified offset |
| 640 | const u64 dst_offset = copy.dst_offset - download_staging.offset; | 641 | const u64 dst_offset = copy.dst_offset - download_staging.offset; |
| 641 | const u8* read_mapped_memory = download_staging.mapped_span.data() + dst_offset; | 642 | const u8* read_mapped_memory = download_staging.mapped_span.data() + dst_offset; |
| 642 | cpu_memory.WriteBlockUnsafe(cpu_addr, read_mapped_memory, copy.size); | 643 | device_memory.WriteBlockUnsafe(device_addr, read_mapped_memory, copy.size); |
| 643 | } | 644 | } |
| 644 | } else { | 645 | } else { |
| 645 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); | 646 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); |
| @@ -647,8 +648,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 647 | Buffer& buffer = slot_buffers[buffer_id]; | 648 | Buffer& buffer = slot_buffers[buffer_id]; |
| 648 | buffer.ImmediateDownload(copy.src_offset, | 649 | buffer.ImmediateDownload(copy.src_offset, |
| 649 | immediate_buffer.subspan(0, copy.size)); | 650 | immediate_buffer.subspan(0, copy.size)); |
| 650 | const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; | 651 | const DAddr device_addr = buffer.CpuAddr() + copy.src_offset; |
| 651 | cpu_memory.WriteBlockUnsafe(cpu_addr, immediate_buffer.data(), copy.size); | 652 | device_memory.WriteBlockUnsafe(device_addr, immediate_buffer.data(), copy.size); |
| 652 | } | 653 | } |
| 653 | } | 654 | } |
| 654 | } | 655 | } |
| @@ -681,19 +682,19 @@ void BufferCache<P>::PopAsyncBuffers() { | |||
| 681 | u8* base = async_buffer->mapped_span.data(); | 682 | u8* base = async_buffer->mapped_span.data(); |
| 682 | const size_t base_offset = async_buffer->offset; | 683 | const size_t base_offset = async_buffer->offset; |
| 683 | for (const auto& copy : downloads) { | 684 | for (const auto& copy : downloads) { |
| 684 | const VAddr cpu_addr = static_cast<VAddr>(copy.src_offset); | 685 | const DAddr device_addr = static_cast<DAddr>(copy.src_offset); |
| 685 | const u64 dst_offset = copy.dst_offset - base_offset; | 686 | const u64 dst_offset = copy.dst_offset - base_offset; |
| 686 | const u8* read_mapped_memory = base + dst_offset; | 687 | const u8* read_mapped_memory = base + dst_offset; |
| 687 | ForEachInOverlapCounter( | 688 | ForEachInOverlapCounter( |
| 688 | async_downloads, cpu_addr, copy.size, [&](VAddr start, VAddr end, int count) { | 689 | async_downloads, device_addr, copy.size, [&](DAddr start, DAddr end, int count) { |
| 689 | cpu_memory.WriteBlockUnsafe(start, &read_mapped_memory[start - cpu_addr], | 690 | device_memory.WriteBlockUnsafe(start, &read_mapped_memory[start - device_addr], |
| 690 | end - start); | 691 | end - start); |
| 691 | if (count == 1) { | 692 | if (count == 1) { |
| 692 | const IntervalType base_interval{start, end}; | 693 | const IntervalType base_interval{start, end}; |
| 693 | common_ranges.subtract(base_interval); | 694 | common_ranges.subtract(base_interval); |
| 694 | } | 695 | } |
| 695 | }); | 696 | }); |
| 696 | const IntervalType subtract_interval{cpu_addr, cpu_addr + copy.size}; | 697 | const IntervalType subtract_interval{device_addr, device_addr + copy.size}; |
| 697 | RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1); | 698 | RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1); |
| 698 | } | 699 | } |
| 699 | async_buffers_death_ring.emplace_back(*async_buffer); | 700 | async_buffers_death_ring.emplace_back(*async_buffer); |
| @@ -703,15 +704,15 @@ void BufferCache<P>::PopAsyncBuffers() { | |||
| 703 | } | 704 | } |
| 704 | 705 | ||
| 705 | template <class P> | 706 | template <class P> |
| 706 | bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { | 707 | bool BufferCache<P>::IsRegionGpuModified(DAddr addr, size_t size) { |
| 707 | bool is_dirty = false; | 708 | bool is_dirty = false; |
| 708 | ForEachInRangeSet(common_ranges, addr, size, [&](VAddr, VAddr) { is_dirty = true; }); | 709 | ForEachInRangeSet(common_ranges, addr, size, [&](DAddr, DAddr) { is_dirty = true; }); |
| 709 | return is_dirty; | 710 | return is_dirty; |
| 710 | } | 711 | } |
| 711 | 712 | ||
| 712 | template <class P> | 713 | template <class P> |
| 713 | bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) { | 714 | bool BufferCache<P>::IsRegionRegistered(DAddr addr, size_t size) { |
| 714 | const VAddr end_addr = addr + size; | 715 | const DAddr end_addr = addr + size; |
| 715 | const u64 page_end = Common::DivCeil(end_addr, CACHING_PAGESIZE); | 716 | const u64 page_end = Common::DivCeil(end_addr, CACHING_PAGESIZE); |
| 716 | for (u64 page = addr >> CACHING_PAGEBITS; page < page_end;) { | 717 | for (u64 page = addr >> CACHING_PAGEBITS; page < page_end;) { |
| 717 | const BufferId buffer_id = page_table[page]; | 718 | const BufferId buffer_id = page_table[page]; |
| @@ -720,8 +721,8 @@ bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) { | |||
| 720 | continue; | 721 | continue; |
| 721 | } | 722 | } |
| 722 | Buffer& buffer = slot_buffers[buffer_id]; | 723 | Buffer& buffer = slot_buffers[buffer_id]; |
| 723 | const VAddr buf_start_addr = buffer.CpuAddr(); | 724 | const DAddr buf_start_addr = buffer.CpuAddr(); |
| 724 | const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); | 725 | const DAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); |
| 725 | if (buf_start_addr < end_addr && addr < buf_end_addr) { | 726 | if (buf_start_addr < end_addr && addr < buf_end_addr) { |
| 726 | return true; | 727 | return true; |
| 727 | } | 728 | } |
| @@ -731,7 +732,7 @@ bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) { | |||
| 731 | } | 732 | } |
| 732 | 733 | ||
| 733 | template <class P> | 734 | template <class P> |
| 734 | bool BufferCache<P>::IsRegionCpuModified(VAddr addr, size_t size) { | 735 | bool BufferCache<P>::IsRegionCpuModified(DAddr addr, size_t size) { |
| 735 | return memory_tracker.IsRegionCpuModified(addr, size); | 736 | return memory_tracker.IsRegionCpuModified(addr, size); |
| 736 | } | 737 | } |
| 737 | 738 | ||
| @@ -739,7 +740,7 @@ template <class P> | |||
| 739 | void BufferCache<P>::BindHostIndexBuffer() { | 740 | void BufferCache<P>::BindHostIndexBuffer() { |
| 740 | Buffer& buffer = slot_buffers[channel_state->index_buffer.buffer_id]; | 741 | Buffer& buffer = slot_buffers[channel_state->index_buffer.buffer_id]; |
| 741 | TouchBuffer(buffer, channel_state->index_buffer.buffer_id); | 742 | TouchBuffer(buffer, channel_state->index_buffer.buffer_id); |
| 742 | const u32 offset = buffer.Offset(channel_state->index_buffer.cpu_addr); | 743 | const u32 offset = buffer.Offset(channel_state->index_buffer.device_addr); |
| 743 | const u32 size = channel_state->index_buffer.size; | 744 | const u32 size = channel_state->index_buffer.size; |
| 744 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); | 745 | const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); |
| 745 | if (!draw_state.inline_index_draw_indexes.empty()) [[unlikely]] { | 746 | if (!draw_state.inline_index_draw_indexes.empty()) [[unlikely]] { |
| @@ -754,7 +755,7 @@ void BufferCache<P>::BindHostIndexBuffer() { | |||
| 754 | buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes); | 755 | buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes); |
| 755 | } | 756 | } |
| 756 | } else { | 757 | } else { |
| 757 | SynchronizeBuffer(buffer, channel_state->index_buffer.cpu_addr, size); | 758 | SynchronizeBuffer(buffer, channel_state->index_buffer.device_addr, size); |
| 758 | } | 759 | } |
| 759 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { | 760 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { |
| 760 | const u32 new_offset = | 761 | const u32 new_offset = |
| @@ -777,7 +778,7 @@ void BufferCache<P>::BindHostVertexBuffers() { | |||
| 777 | const Binding& binding = channel_state->vertex_buffers[index]; | 778 | const Binding& binding = channel_state->vertex_buffers[index]; |
| 778 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 779 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 779 | TouchBuffer(buffer, binding.buffer_id); | 780 | TouchBuffer(buffer, binding.buffer_id); |
| 780 | SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); | 781 | SynchronizeBuffer(buffer, binding.device_addr, binding.size); |
| 781 | if (!flags[Dirty::VertexBuffer0 + index]) { | 782 | if (!flags[Dirty::VertexBuffer0 + index]) { |
| 782 | continue; | 783 | continue; |
| 783 | } | 784 | } |
| @@ -797,7 +798,7 @@ void BufferCache<P>::BindHostVertexBuffers() { | |||
| 797 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 798 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 798 | 799 | ||
| 799 | const u32 stride = maxwell3d->regs.vertex_streams[index].stride; | 800 | const u32 stride = maxwell3d->regs.vertex_streams[index].stride; |
| 800 | const u32 offset = buffer.Offset(binding.cpu_addr); | 801 | const u32 offset = buffer.Offset(binding.device_addr); |
| 801 | buffer.MarkUsage(offset, binding.size); | 802 | buffer.MarkUsage(offset, binding.size); |
| 802 | 803 | ||
| 803 | host_bindings.buffers.push_back(&buffer); | 804 | host_bindings.buffers.push_back(&buffer); |
| @@ -814,7 +815,7 @@ void BufferCache<P>::BindHostDrawIndirectBuffers() { | |||
| 814 | const auto bind_buffer = [this](const Binding& binding) { | 815 | const auto bind_buffer = [this](const Binding& binding) { |
| 815 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 816 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 816 | TouchBuffer(buffer, binding.buffer_id); | 817 | TouchBuffer(buffer, binding.buffer_id); |
| 817 | SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); | 818 | SynchronizeBuffer(buffer, binding.device_addr, binding.size); |
| 818 | }; | 819 | }; |
| 819 | if (current_draw_indirect->include_count) { | 820 | if (current_draw_indirect->include_count) { |
| 820 | bind_buffer(channel_state->count_buffer_binding); | 821 | bind_buffer(channel_state->count_buffer_binding); |
| @@ -842,13 +843,13 @@ template <class P> | |||
| 842 | void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, | 843 | void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, |
| 843 | bool needs_bind) { | 844 | bool needs_bind) { |
| 844 | const Binding& binding = channel_state->uniform_buffers[stage][index]; | 845 | const Binding& binding = channel_state->uniform_buffers[stage][index]; |
| 845 | const VAddr cpu_addr = binding.cpu_addr; | 846 | const DAddr device_addr = binding.device_addr; |
| 846 | const u32 size = std::min(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); | 847 | const u32 size = std::min(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); |
| 847 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 848 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 848 | TouchBuffer(buffer, binding.buffer_id); | 849 | TouchBuffer(buffer, binding.buffer_id); |
| 849 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && | 850 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && |
| 850 | size <= channel_state->uniform_buffer_skip_cache_size && | 851 | size <= channel_state->uniform_buffer_skip_cache_size && |
| 851 | !memory_tracker.IsRegionGpuModified(cpu_addr, size); | 852 | !memory_tracker.IsRegionGpuModified(device_addr, size); |
| 852 | if (use_fast_buffer) { | 853 | if (use_fast_buffer) { |
| 853 | if constexpr (IS_OPENGL) { | 854 | if constexpr (IS_OPENGL) { |
| 854 | if (runtime.HasFastBufferSubData()) { | 855 | if (runtime.HasFastBufferSubData()) { |
| @@ -862,7 +863,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 862 | channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size; | 863 | channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size; |
| 863 | runtime.BindFastUniformBuffer(stage, binding_index, size); | 864 | runtime.BindFastUniformBuffer(stage, binding_index, size); |
| 864 | } | 865 | } |
| 865 | const auto span = ImmediateBufferWithData(cpu_addr, size); | 866 | const auto span = ImmediateBufferWithData(device_addr, size); |
| 866 | runtime.PushFastUniformBuffer(stage, binding_index, span); | 867 | runtime.PushFastUniformBuffer(stage, binding_index, span); |
| 867 | return; | 868 | return; |
| 868 | } | 869 | } |
| @@ -873,11 +874,11 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 873 | } | 874 | } |
| 874 | // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan | 875 | // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan |
| 875 | const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); | 876 | const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); |
| 876 | cpu_memory.ReadBlockUnsafe(cpu_addr, span.data(), size); | 877 | device_memory.ReadBlockUnsafe(device_addr, span.data(), size); |
| 877 | return; | 878 | return; |
| 878 | } | 879 | } |
| 879 | // Classic cached path | 880 | // Classic cached path |
| 880 | const bool sync_cached = SynchronizeBuffer(buffer, cpu_addr, size); | 881 | const bool sync_cached = SynchronizeBuffer(buffer, device_addr, size); |
| 881 | if (sync_cached) { | 882 | if (sync_cached) { |
| 882 | ++channel_state->uniform_cache_hits[0]; | 883 | ++channel_state->uniform_cache_hits[0]; |
| 883 | } | 884 | } |
| @@ -892,7 +893,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 892 | if (!needs_bind) { | 893 | if (!needs_bind) { |
| 893 | return; | 894 | return; |
| 894 | } | 895 | } |
| 895 | const u32 offset = buffer.Offset(cpu_addr); | 896 | const u32 offset = buffer.Offset(device_addr); |
| 896 | if constexpr (IS_OPENGL) { | 897 | if constexpr (IS_OPENGL) { |
| 897 | // Fast buffer will be unbound | 898 | // Fast buffer will be unbound |
| 898 | channel_state->fast_bound_uniform_buffers[stage] &= ~(1U << binding_index); | 899 | channel_state->fast_bound_uniform_buffers[stage] &= ~(1U << binding_index); |
| @@ -920,14 +921,14 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) { | |||
| 920 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 921 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 921 | TouchBuffer(buffer, binding.buffer_id); | 922 | TouchBuffer(buffer, binding.buffer_id); |
| 922 | const u32 size = binding.size; | 923 | const u32 size = binding.size; |
| 923 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 924 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 924 | 925 | ||
| 925 | const u32 offset = buffer.Offset(binding.cpu_addr); | 926 | const u32 offset = buffer.Offset(binding.device_addr); |
| 926 | buffer.MarkUsage(offset, size); | 927 | buffer.MarkUsage(offset, size); |
| 927 | const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0; | 928 | const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0; |
| 928 | 929 | ||
| 929 | if (is_written) { | 930 | if (is_written) { |
| 930 | MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); | 931 | MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); |
| 931 | } | 932 | } |
| 932 | 933 | ||
| 933 | if constexpr (NEEDS_BIND_STORAGE_INDEX) { | 934 | if constexpr (NEEDS_BIND_STORAGE_INDEX) { |
| @@ -945,14 +946,14 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) { | |||
| 945 | const TextureBufferBinding& binding = channel_state->texture_buffers[stage][index]; | 946 | const TextureBufferBinding& binding = channel_state->texture_buffers[stage][index]; |
| 946 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 947 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 947 | const u32 size = binding.size; | 948 | const u32 size = binding.size; |
| 948 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 949 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 949 | 950 | ||
| 950 | const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0; | 951 | const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0; |
| 951 | if (is_written) { | 952 | if (is_written) { |
| 952 | MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); | 953 | MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); |
| 953 | } | 954 | } |
| 954 | 955 | ||
| 955 | const u32 offset = buffer.Offset(binding.cpu_addr); | 956 | const u32 offset = buffer.Offset(binding.device_addr); |
| 956 | const PixelFormat format = binding.format; | 957 | const PixelFormat format = binding.format; |
| 957 | buffer.MarkUsage(offset, size); | 958 | buffer.MarkUsage(offset, size); |
| 958 | if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { | 959 | if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { |
| @@ -982,11 +983,11 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() { | |||
| 982 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 983 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 983 | TouchBuffer(buffer, binding.buffer_id); | 984 | TouchBuffer(buffer, binding.buffer_id); |
| 984 | const u32 size = binding.size; | 985 | const u32 size = binding.size; |
| 985 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 986 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 986 | 987 | ||
| 987 | MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); | 988 | MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); |
| 988 | 989 | ||
| 989 | const u32 offset = buffer.Offset(binding.cpu_addr); | 990 | const u32 offset = buffer.Offset(binding.device_addr); |
| 990 | buffer.MarkUsage(offset, size); | 991 | buffer.MarkUsage(offset, size); |
| 991 | host_bindings.buffers.push_back(&buffer); | 992 | host_bindings.buffers.push_back(&buffer); |
| 992 | host_bindings.offsets.push_back(offset); | 993 | host_bindings.offsets.push_back(offset); |
| @@ -1011,9 +1012,9 @@ void BufferCache<P>::BindHostComputeUniformBuffers() { | |||
| 1011 | TouchBuffer(buffer, binding.buffer_id); | 1012 | TouchBuffer(buffer, binding.buffer_id); |
| 1012 | const u32 size = | 1013 | const u32 size = |
| 1013 | std::min(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); | 1014 | std::min(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); |
| 1014 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 1015 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 1015 | 1016 | ||
| 1016 | const u32 offset = buffer.Offset(binding.cpu_addr); | 1017 | const u32 offset = buffer.Offset(binding.device_addr); |
| 1017 | buffer.MarkUsage(offset, size); | 1018 | buffer.MarkUsage(offset, size); |
| 1018 | if constexpr (NEEDS_BIND_UNIFORM_INDEX) { | 1019 | if constexpr (NEEDS_BIND_UNIFORM_INDEX) { |
| 1019 | runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size); | 1020 | runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size); |
| @@ -1032,15 +1033,15 @@ void BufferCache<P>::BindHostComputeStorageBuffers() { | |||
| 1032 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 1033 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 1033 | TouchBuffer(buffer, binding.buffer_id); | 1034 | TouchBuffer(buffer, binding.buffer_id); |
| 1034 | const u32 size = binding.size; | 1035 | const u32 size = binding.size; |
| 1035 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 1036 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 1036 | 1037 | ||
| 1037 | const u32 offset = buffer.Offset(binding.cpu_addr); | 1038 | const u32 offset = buffer.Offset(binding.device_addr); |
| 1038 | buffer.MarkUsage(offset, size); | 1039 | buffer.MarkUsage(offset, size); |
| 1039 | const bool is_written = | 1040 | const bool is_written = |
| 1040 | ((channel_state->written_compute_storage_buffers >> index) & 1) != 0; | 1041 | ((channel_state->written_compute_storage_buffers >> index) & 1) != 0; |
| 1041 | 1042 | ||
| 1042 | if (is_written) { | 1043 | if (is_written) { |
| 1043 | MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); | 1044 | MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); |
| 1044 | } | 1045 | } |
| 1045 | 1046 | ||
| 1046 | if constexpr (NEEDS_BIND_STORAGE_INDEX) { | 1047 | if constexpr (NEEDS_BIND_STORAGE_INDEX) { |
| @@ -1058,15 +1059,15 @@ void BufferCache<P>::BindHostComputeTextureBuffers() { | |||
| 1058 | const TextureBufferBinding& binding = channel_state->compute_texture_buffers[index]; | 1059 | const TextureBufferBinding& binding = channel_state->compute_texture_buffers[index]; |
| 1059 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 1060 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 1060 | const u32 size = binding.size; | 1061 | const u32 size = binding.size; |
| 1061 | SynchronizeBuffer(buffer, binding.cpu_addr, size); | 1062 | SynchronizeBuffer(buffer, binding.device_addr, size); |
| 1062 | 1063 | ||
| 1063 | const bool is_written = | 1064 | const bool is_written = |
| 1064 | ((channel_state->written_compute_texture_buffers >> index) & 1) != 0; | 1065 | ((channel_state->written_compute_texture_buffers >> index) & 1) != 0; |
| 1065 | if (is_written) { | 1066 | if (is_written) { |
| 1066 | MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); | 1067 | MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size); |
| 1067 | } | 1068 | } |
| 1068 | 1069 | ||
| 1069 | const u32 offset = buffer.Offset(binding.cpu_addr); | 1070 | const u32 offset = buffer.Offset(binding.device_addr); |
| 1070 | const PixelFormat format = binding.format; | 1071 | const PixelFormat format = binding.format; |
| 1071 | buffer.MarkUsage(offset, size); | 1072 | buffer.MarkUsage(offset, size); |
| 1072 | if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { | 1073 | if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { |
| @@ -1131,7 +1132,7 @@ void BufferCache<P>::UpdateIndexBuffer() { | |||
| 1131 | inline_buffer_id = CreateBuffer(0, buffer_size); | 1132 | inline_buffer_id = CreateBuffer(0, buffer_size); |
| 1132 | } | 1133 | } |
| 1133 | channel_state->index_buffer = Binding{ | 1134 | channel_state->index_buffer = Binding{ |
| 1134 | .cpu_addr = 0, | 1135 | .device_addr = 0, |
| 1135 | .size = inline_index_size, | 1136 | .size = inline_index_size, |
| 1136 | .buffer_id = inline_buffer_id, | 1137 | .buffer_id = inline_buffer_id, |
| 1137 | }; | 1138 | }; |
| @@ -1140,19 +1141,19 @@ void BufferCache<P>::UpdateIndexBuffer() { | |||
| 1140 | 1141 | ||
| 1141 | const GPUVAddr gpu_addr_begin = index_buffer_ref.StartAddress(); | 1142 | const GPUVAddr gpu_addr_begin = index_buffer_ref.StartAddress(); |
| 1142 | const GPUVAddr gpu_addr_end = index_buffer_ref.EndAddress(); | 1143 | const GPUVAddr gpu_addr_end = index_buffer_ref.EndAddress(); |
| 1143 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); | 1144 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); |
| 1144 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); | 1145 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); |
| 1145 | const u32 draw_size = | 1146 | const u32 draw_size = |
| 1146 | (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes(); | 1147 | (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes(); |
| 1147 | const u32 size = std::min(address_size, draw_size); | 1148 | const u32 size = std::min(address_size, draw_size); |
| 1148 | if (size == 0 || !cpu_addr) { | 1149 | if (size == 0 || !device_addr) { |
| 1149 | channel_state->index_buffer = NULL_BINDING; | 1150 | channel_state->index_buffer = NULL_BINDING; |
| 1150 | return; | 1151 | return; |
| 1151 | } | 1152 | } |
| 1152 | channel_state->index_buffer = Binding{ | 1153 | channel_state->index_buffer = Binding{ |
| 1153 | .cpu_addr = *cpu_addr, | 1154 | .device_addr = *device_addr, |
| 1154 | .size = size, | 1155 | .size = size, |
| 1155 | .buffer_id = FindBuffer(*cpu_addr, size), | 1156 | .buffer_id = FindBuffer(*device_addr, size), |
| 1156 | }; | 1157 | }; |
| 1157 | } | 1158 | } |
| 1158 | 1159 | ||
| @@ -1178,19 +1179,19 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) { | |||
| 1178 | const auto& limit = maxwell3d->regs.vertex_stream_limits[index]; | 1179 | const auto& limit = maxwell3d->regs.vertex_stream_limits[index]; |
| 1179 | const GPUVAddr gpu_addr_begin = array.Address(); | 1180 | const GPUVAddr gpu_addr_begin = array.Address(); |
| 1180 | const GPUVAddr gpu_addr_end = limit.Address() + 1; | 1181 | const GPUVAddr gpu_addr_end = limit.Address() + 1; |
| 1181 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); | 1182 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); |
| 1182 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); | 1183 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); |
| 1183 | u32 size = address_size; // TODO: Analyze stride and number of vertices | 1184 | u32 size = address_size; // TODO: Analyze stride and number of vertices |
| 1184 | if (array.enable == 0 || size == 0 || !cpu_addr) { | 1185 | if (array.enable == 0 || size == 0 || !device_addr) { |
| 1185 | channel_state->vertex_buffers[index] = NULL_BINDING; | 1186 | channel_state->vertex_buffers[index] = NULL_BINDING; |
| 1186 | return; | 1187 | return; |
| 1187 | } | 1188 | } |
| 1188 | if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { | 1189 | if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { |
| 1189 | size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size)); | 1190 | size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size)); |
| 1190 | } | 1191 | } |
| 1191 | const BufferId buffer_id = FindBuffer(*cpu_addr, size); | 1192 | const BufferId buffer_id = FindBuffer(*device_addr, size); |
| 1192 | channel_state->vertex_buffers[index] = Binding{ | 1193 | channel_state->vertex_buffers[index] = Binding{ |
| 1193 | .cpu_addr = *cpu_addr, | 1194 | .device_addr = *device_addr, |
| 1194 | .size = size, | 1195 | .size = size, |
| 1195 | .buffer_id = buffer_id, | 1196 | .buffer_id = buffer_id, |
| 1196 | }; | 1197 | }; |
| @@ -1199,15 +1200,15 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) { | |||
| 1199 | template <class P> | 1200 | template <class P> |
| 1200 | void BufferCache<P>::UpdateDrawIndirect() { | 1201 | void BufferCache<P>::UpdateDrawIndirect() { |
| 1201 | const auto update = [this](GPUVAddr gpu_addr, size_t size, Binding& binding) { | 1202 | const auto update = [this](GPUVAddr gpu_addr, size_t size, Binding& binding) { |
| 1202 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1203 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1203 | if (!cpu_addr) { | 1204 | if (!device_addr) { |
| 1204 | binding = NULL_BINDING; | 1205 | binding = NULL_BINDING; |
| 1205 | return; | 1206 | return; |
| 1206 | } | 1207 | } |
| 1207 | binding = Binding{ | 1208 | binding = Binding{ |
| 1208 | .cpu_addr = *cpu_addr, | 1209 | .device_addr = *device_addr, |
| 1209 | .size = static_cast<u32>(size), | 1210 | .size = static_cast<u32>(size), |
| 1210 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), | 1211 | .buffer_id = FindBuffer(*device_addr, static_cast<u32>(size)), |
| 1211 | }; | 1212 | }; |
| 1212 | }; | 1213 | }; |
| 1213 | if (current_draw_indirect->include_count) { | 1214 | if (current_draw_indirect->include_count) { |
| @@ -1231,7 +1232,7 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) { | |||
| 1231 | channel_state->dirty_uniform_buffers[stage] |= 1U << index; | 1232 | channel_state->dirty_uniform_buffers[stage] |= 1U << index; |
| 1232 | } | 1233 | } |
| 1233 | // Resolve buffer | 1234 | // Resolve buffer |
| 1234 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1235 | binding.buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1235 | }); | 1236 | }); |
| 1236 | } | 1237 | } |
| 1237 | 1238 | ||
| @@ -1240,7 +1241,7 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) { | |||
| 1240 | ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) { | 1241 | ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) { |
| 1241 | // Resolve buffer | 1242 | // Resolve buffer |
| 1242 | Binding& binding = channel_state->storage_buffers[stage][index]; | 1243 | Binding& binding = channel_state->storage_buffers[stage][index]; |
| 1243 | const BufferId buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1244 | const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1244 | binding.buffer_id = buffer_id; | 1245 | binding.buffer_id = buffer_id; |
| 1245 | }); | 1246 | }); |
| 1246 | } | 1247 | } |
| @@ -1249,7 +1250,7 @@ template <class P> | |||
| 1249 | void BufferCache<P>::UpdateTextureBuffers(size_t stage) { | 1250 | void BufferCache<P>::UpdateTextureBuffers(size_t stage) { |
| 1250 | ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) { | 1251 | ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) { |
| 1251 | Binding& binding = channel_state->texture_buffers[stage][index]; | 1252 | Binding& binding = channel_state->texture_buffers[stage][index]; |
| 1252 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1253 | binding.buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1253 | }); | 1254 | }); |
| 1254 | } | 1255 | } |
| 1255 | 1256 | ||
| @@ -1268,14 +1269,14 @@ void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) { | |||
| 1268 | const auto& binding = maxwell3d->regs.transform_feedback.buffers[index]; | 1269 | const auto& binding = maxwell3d->regs.transform_feedback.buffers[index]; |
| 1269 | const GPUVAddr gpu_addr = binding.Address() + binding.start_offset; | 1270 | const GPUVAddr gpu_addr = binding.Address() + binding.start_offset; |
| 1270 | const u32 size = binding.size; | 1271 | const u32 size = binding.size; |
| 1271 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1272 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1272 | if (binding.enable == 0 || size == 0 || !cpu_addr) { | 1273 | if (binding.enable == 0 || size == 0 || !device_addr) { |
| 1273 | channel_state->transform_feedback_buffers[index] = NULL_BINDING; | 1274 | channel_state->transform_feedback_buffers[index] = NULL_BINDING; |
| 1274 | return; | 1275 | return; |
| 1275 | } | 1276 | } |
| 1276 | const BufferId buffer_id = FindBuffer(*cpu_addr, size); | 1277 | const BufferId buffer_id = FindBuffer(*device_addr, size); |
| 1277 | channel_state->transform_feedback_buffers[index] = Binding{ | 1278 | channel_state->transform_feedback_buffers[index] = Binding{ |
| 1278 | .cpu_addr = *cpu_addr, | 1279 | .device_addr = *device_addr, |
| 1279 | .size = size, | 1280 | .size = size, |
| 1280 | .buffer_id = buffer_id, | 1281 | .buffer_id = buffer_id, |
| 1281 | }; | 1282 | }; |
| @@ -1289,13 +1290,13 @@ void BufferCache<P>::UpdateComputeUniformBuffers() { | |||
| 1289 | const auto& launch_desc = kepler_compute->launch_description; | 1290 | const auto& launch_desc = kepler_compute->launch_description; |
| 1290 | if (((launch_desc.const_buffer_enable_mask >> index) & 1) != 0) { | 1291 | if (((launch_desc.const_buffer_enable_mask >> index) & 1) != 0) { |
| 1291 | const auto& cbuf = launch_desc.const_buffer_config[index]; | 1292 | const auto& cbuf = launch_desc.const_buffer_config[index]; |
| 1292 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(cbuf.Address()); | 1293 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(cbuf.Address()); |
| 1293 | if (cpu_addr) { | 1294 | if (device_addr) { |
| 1294 | binding.cpu_addr = *cpu_addr; | 1295 | binding.device_addr = *device_addr; |
| 1295 | binding.size = cbuf.size; | 1296 | binding.size = cbuf.size; |
| 1296 | } | 1297 | } |
| 1297 | } | 1298 | } |
| 1298 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1299 | binding.buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1299 | }); | 1300 | }); |
| 1300 | } | 1301 | } |
| 1301 | 1302 | ||
| @@ -1304,7 +1305,7 @@ void BufferCache<P>::UpdateComputeStorageBuffers() { | |||
| 1304 | ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) { | 1305 | ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) { |
| 1305 | // Resolve buffer | 1306 | // Resolve buffer |
| 1306 | Binding& binding = channel_state->compute_storage_buffers[index]; | 1307 | Binding& binding = channel_state->compute_storage_buffers[index]; |
| 1307 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1308 | binding.buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1308 | }); | 1309 | }); |
| 1309 | } | 1310 | } |
| 1310 | 1311 | ||
| @@ -1312,45 +1313,63 @@ template <class P> | |||
| 1312 | void BufferCache<P>::UpdateComputeTextureBuffers() { | 1313 | void BufferCache<P>::UpdateComputeTextureBuffers() { |
| 1313 | ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) { | 1314 | ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) { |
| 1314 | Binding& binding = channel_state->compute_texture_buffers[index]; | 1315 | Binding& binding = channel_state->compute_texture_buffers[index]; |
| 1315 | binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); | 1316 | binding.buffer_id = FindBuffer(binding.device_addr, binding.size); |
| 1316 | }); | 1317 | }); |
| 1317 | } | 1318 | } |
| 1318 | 1319 | ||
| 1319 | template <class P> | 1320 | template <class P> |
| 1320 | void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { | 1321 | void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size) { |
| 1321 | memory_tracker.MarkRegionAsGpuModified(cpu_addr, size); | 1322 | memory_tracker.MarkRegionAsGpuModified(device_addr, size); |
| 1322 | 1323 | ||
| 1323 | const IntervalType base_interval{cpu_addr, cpu_addr + size}; | 1324 | const IntervalType base_interval{device_addr, device_addr + size}; |
| 1324 | common_ranges.add(base_interval); | 1325 | common_ranges.add(base_interval); |
| 1325 | uncommitted_ranges.add(base_interval); | 1326 | uncommitted_ranges.add(base_interval); |
| 1326 | } | 1327 | } |
| 1327 | 1328 | ||
| 1328 | template <class P> | 1329 | template <class P> |
| 1329 | BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) { | 1330 | BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size) { |
| 1330 | if (cpu_addr == 0) { | 1331 | if (device_addr == 0) { |
| 1331 | return NULL_BUFFER_ID; | 1332 | return NULL_BUFFER_ID; |
| 1332 | } | 1333 | } |
| 1333 | const u64 page = cpu_addr >> CACHING_PAGEBITS; | 1334 | const u64 page = device_addr >> CACHING_PAGEBITS; |
| 1334 | const BufferId buffer_id = page_table[page]; | 1335 | const BufferId buffer_id = page_table[page]; |
| 1335 | if (!buffer_id) { | 1336 | if (!buffer_id) { |
| 1336 | return CreateBuffer(cpu_addr, size); | 1337 | return CreateBuffer(device_addr, size); |
| 1337 | } | 1338 | } |
| 1338 | const Buffer& buffer = slot_buffers[buffer_id]; | 1339 | const Buffer& buffer = slot_buffers[buffer_id]; |
| 1339 | if (buffer.IsInBounds(cpu_addr, size)) { | 1340 | if (buffer.IsInBounds(device_addr, size)) { |
| 1340 | return buffer_id; | 1341 | return buffer_id; |
| 1341 | } | 1342 | } |
| 1342 | return CreateBuffer(cpu_addr, size); | 1343 | return CreateBuffer(device_addr, size); |
| 1343 | } | 1344 | } |
| 1344 | 1345 | ||
| 1345 | template <class P> | 1346 | template <class P> |
| 1346 | typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr, | 1347 | typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(DAddr device_addr, |
| 1347 | u32 wanted_size) { | 1348 | u32 wanted_size) { |
| 1348 | static constexpr int STREAM_LEAP_THRESHOLD = 16; | 1349 | static constexpr int STREAM_LEAP_THRESHOLD = 16; |
| 1349 | boost::container::small_vector<BufferId, 16> overlap_ids; | 1350 | boost::container::small_vector<BufferId, 16> overlap_ids; |
| 1350 | VAddr begin = cpu_addr; | 1351 | DAddr begin = device_addr; |
| 1351 | VAddr end = cpu_addr + wanted_size; | 1352 | DAddr end = device_addr + wanted_size; |
| 1352 | int stream_score = 0; | 1353 | int stream_score = 0; |
| 1353 | bool has_stream_leap = false; | 1354 | bool has_stream_leap = false; |
| 1355 | auto expand_begin = [&](DAddr add_value) { | ||
| 1356 | static constexpr DAddr min_page = CACHING_PAGESIZE + Core::DEVICE_PAGESIZE; | ||
| 1357 | if (add_value > begin - min_page) { | ||
| 1358 | begin = min_page; | ||
| 1359 | device_addr = Core::DEVICE_PAGESIZE; | ||
| 1360 | return; | ||
| 1361 | } | ||
| 1362 | begin -= add_value; | ||
| 1363 | device_addr = begin - CACHING_PAGESIZE; | ||
| 1364 | }; | ||
| 1365 | auto expand_end = [&](DAddr add_value) { | ||
| 1366 | static constexpr DAddr max_page = 1ULL << Tegra::MaxwellDeviceMemoryManager::AS_BITS; | ||
| 1367 | if (add_value > max_page - end) { | ||
| 1368 | end = max_page; | ||
| 1369 | return; | ||
| 1370 | } | ||
| 1371 | end += add_value; | ||
| 1372 | }; | ||
| 1354 | if (begin == 0) { | 1373 | if (begin == 0) { |
| 1355 | return OverlapResult{ | 1374 | return OverlapResult{ |
| 1356 | .ids = std::move(overlap_ids), | 1375 | .ids = std::move(overlap_ids), |
| @@ -1359,9 +1378,9 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu | |||
| 1359 | .has_stream_leap = has_stream_leap, | 1378 | .has_stream_leap = has_stream_leap, |
| 1360 | }; | 1379 | }; |
| 1361 | } | 1380 | } |
| 1362 | for (; cpu_addr >> CACHING_PAGEBITS < Common::DivCeil(end, CACHING_PAGESIZE); | 1381 | for (; device_addr >> CACHING_PAGEBITS < Common::DivCeil(end, CACHING_PAGESIZE); |
| 1363 | cpu_addr += CACHING_PAGESIZE) { | 1382 | device_addr += CACHING_PAGESIZE) { |
| 1364 | const BufferId overlap_id = page_table[cpu_addr >> CACHING_PAGEBITS]; | 1383 | const BufferId overlap_id = page_table[device_addr >> CACHING_PAGEBITS]; |
| 1365 | if (!overlap_id) { | 1384 | if (!overlap_id) { |
| 1366 | continue; | 1385 | continue; |
| 1367 | } | 1386 | } |
| @@ -1371,12 +1390,12 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu | |||
| 1371 | } | 1390 | } |
| 1372 | overlap_ids.push_back(overlap_id); | 1391 | overlap_ids.push_back(overlap_id); |
| 1373 | overlap.Pick(); | 1392 | overlap.Pick(); |
| 1374 | const VAddr overlap_cpu_addr = overlap.CpuAddr(); | 1393 | const DAddr overlap_device_addr = overlap.CpuAddr(); |
| 1375 | const bool expands_left = overlap_cpu_addr < begin; | 1394 | const bool expands_left = overlap_device_addr < begin; |
| 1376 | if (expands_left) { | 1395 | if (expands_left) { |
| 1377 | begin = overlap_cpu_addr; | 1396 | begin = overlap_device_addr; |
| 1378 | } | 1397 | } |
| 1379 | const VAddr overlap_end = overlap_cpu_addr + overlap.SizeBytes(); | 1398 | const DAddr overlap_end = overlap_device_addr + overlap.SizeBytes(); |
| 1380 | const bool expands_right = overlap_end > end; | 1399 | const bool expands_right = overlap_end > end; |
| 1381 | if (overlap_end > end) { | 1400 | if (overlap_end > end) { |
| 1382 | end = overlap_end; | 1401 | end = overlap_end; |
| @@ -1387,11 +1406,10 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu | |||
| 1387 | // as a stream buffer. Increase the size to skip constantly recreating buffers. | 1406 | // as a stream buffer. Increase the size to skip constantly recreating buffers. |
| 1388 | has_stream_leap = true; | 1407 | has_stream_leap = true; |
| 1389 | if (expands_right) { | 1408 | if (expands_right) { |
| 1390 | begin -= CACHING_PAGESIZE * 256; | 1409 | expand_begin(CACHING_PAGESIZE * 128); |
| 1391 | cpu_addr = begin - CACHING_PAGESIZE; | ||
| 1392 | } | 1410 | } |
| 1393 | if (expands_left) { | 1411 | if (expands_left) { |
| 1394 | end += CACHING_PAGESIZE * 256; | 1412 | expand_end(CACHING_PAGESIZE * 128); |
| 1395 | } | 1413 | } |
| 1396 | } | 1414 | } |
| 1397 | } | 1415 | } |
| @@ -1424,13 +1442,13 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, | |||
| 1424 | } | 1442 | } |
| 1425 | 1443 | ||
| 1426 | template <class P> | 1444 | template <class P> |
| 1427 | BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { | 1445 | BufferId BufferCache<P>::CreateBuffer(DAddr device_addr, u32 wanted_size) { |
| 1428 | VAddr cpu_addr_end = Common::AlignUp(cpu_addr + wanted_size, CACHING_PAGESIZE); | 1446 | DAddr device_addr_end = Common::AlignUp(device_addr + wanted_size, CACHING_PAGESIZE); |
| 1429 | cpu_addr = Common::AlignDown(cpu_addr, CACHING_PAGESIZE); | 1447 | device_addr = Common::AlignDown(device_addr, CACHING_PAGESIZE); |
| 1430 | wanted_size = static_cast<u32>(cpu_addr_end - cpu_addr); | 1448 | wanted_size = static_cast<u32>(device_addr_end - device_addr); |
| 1431 | const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size); | 1449 | const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size); |
| 1432 | const u32 size = static_cast<u32>(overlap.end - overlap.begin); | 1450 | const u32 size = static_cast<u32>(overlap.end - overlap.begin); |
| 1433 | const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size); | 1451 | const BufferId new_buffer_id = slot_buffers.insert(runtime, overlap.begin, size); |
| 1434 | auto& new_buffer = slot_buffers[new_buffer_id]; | 1452 | auto& new_buffer = slot_buffers[new_buffer_id]; |
| 1435 | const size_t size_bytes = new_buffer.SizeBytes(); | 1453 | const size_t size_bytes = new_buffer.SizeBytes(); |
| 1436 | runtime.ClearBuffer(new_buffer, 0, size_bytes, 0); | 1454 | runtime.ClearBuffer(new_buffer, 0, size_bytes, 0); |
| @@ -1465,10 +1483,10 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) { | |||
| 1465 | total_used_memory -= Common::AlignUp(size, 1024); | 1483 | total_used_memory -= Common::AlignUp(size, 1024); |
| 1466 | lru_cache.Free(buffer.getLRUID()); | 1484 | lru_cache.Free(buffer.getLRUID()); |
| 1467 | } | 1485 | } |
| 1468 | const VAddr cpu_addr_begin = buffer.CpuAddr(); | 1486 | const DAddr device_addr_begin = buffer.CpuAddr(); |
| 1469 | const VAddr cpu_addr_end = cpu_addr_begin + size; | 1487 | const DAddr device_addr_end = device_addr_begin + size; |
| 1470 | const u64 page_begin = cpu_addr_begin / CACHING_PAGESIZE; | 1488 | const u64 page_begin = device_addr_begin / CACHING_PAGESIZE; |
| 1471 | const u64 page_end = Common::DivCeil(cpu_addr_end, CACHING_PAGESIZE); | 1489 | const u64 page_end = Common::DivCeil(device_addr_end, CACHING_PAGESIZE); |
| 1472 | for (u64 page = page_begin; page != page_end; ++page) { | 1490 | for (u64 page = page_begin; page != page_end; ++page) { |
| 1473 | if constexpr (insert) { | 1491 | if constexpr (insert) { |
| 1474 | page_table[page] = buffer_id; | 1492 | page_table[page] = buffer_id; |
| @@ -1486,15 +1504,15 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept { | |||
| 1486 | } | 1504 | } |
| 1487 | 1505 | ||
| 1488 | template <class P> | 1506 | template <class P> |
| 1489 | bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size) { | 1507 | bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) { |
| 1490 | boost::container::small_vector<BufferCopy, 4> copies; | 1508 | boost::container::small_vector<BufferCopy, 4> copies; |
| 1491 | u64 total_size_bytes = 0; | 1509 | u64 total_size_bytes = 0; |
| 1492 | u64 largest_copy = 0; | 1510 | u64 largest_copy = 0; |
| 1493 | VAddr buffer_start = buffer.CpuAddr(); | 1511 | DAddr buffer_start = buffer.CpuAddr(); |
| 1494 | memory_tracker.ForEachUploadRange(cpu_addr, size, [&](u64 cpu_addr_out, u64 range_size) { | 1512 | memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) { |
| 1495 | copies.push_back(BufferCopy{ | 1513 | copies.push_back(BufferCopy{ |
| 1496 | .src_offset = total_size_bytes, | 1514 | .src_offset = total_size_bytes, |
| 1497 | .dst_offset = cpu_addr_out - buffer_start, | 1515 | .dst_offset = device_addr_out - buffer_start, |
| 1498 | .size = range_size, | 1516 | .size = range_size, |
| 1499 | }); | 1517 | }); |
| 1500 | total_size_bytes += range_size; | 1518 | total_size_bytes += range_size; |
| @@ -1526,14 +1544,14 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer, | |||
| 1526 | std::span<u8> immediate_buffer; | 1544 | std::span<u8> immediate_buffer; |
| 1527 | for (const BufferCopy& copy : copies) { | 1545 | for (const BufferCopy& copy : copies) { |
| 1528 | std::span<const u8> upload_span; | 1546 | std::span<const u8> upload_span; |
| 1529 | const VAddr cpu_addr = buffer.CpuAddr() + copy.dst_offset; | 1547 | const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; |
| 1530 | if (IsRangeGranular(cpu_addr, copy.size)) { | 1548 | if (IsRangeGranular(device_addr, copy.size)) { |
| 1531 | upload_span = std::span(cpu_memory.GetPointer(cpu_addr), copy.size); | 1549 | upload_span = std::span(device_memory.GetPointer<u8>(device_addr), copy.size); |
| 1532 | } else { | 1550 | } else { |
| 1533 | if (immediate_buffer.empty()) { | 1551 | if (immediate_buffer.empty()) { |
| 1534 | immediate_buffer = ImmediateBuffer(largest_copy); | 1552 | immediate_buffer = ImmediateBuffer(largest_copy); |
| 1535 | } | 1553 | } |
| 1536 | cpu_memory.ReadBlockUnsafe(cpu_addr, immediate_buffer.data(), copy.size); | 1554 | device_memory.ReadBlockUnsafe(device_addr, immediate_buffer.data(), copy.size); |
| 1537 | upload_span = immediate_buffer.subspan(0, copy.size); | 1555 | upload_span = immediate_buffer.subspan(0, copy.size); |
| 1538 | } | 1556 | } |
| 1539 | buffer.ImmediateUpload(copy.dst_offset, upload_span); | 1557 | buffer.ImmediateUpload(copy.dst_offset, upload_span); |
| @@ -1550,8 +1568,8 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer, | |||
| 1550 | const std::span<u8> staging_pointer = upload_staging.mapped_span; | 1568 | const std::span<u8> staging_pointer = upload_staging.mapped_span; |
| 1551 | for (BufferCopy& copy : copies) { | 1569 | for (BufferCopy& copy : copies) { |
| 1552 | u8* const src_pointer = staging_pointer.data() + copy.src_offset; | 1570 | u8* const src_pointer = staging_pointer.data() + copy.src_offset; |
| 1553 | const VAddr cpu_addr = buffer.CpuAddr() + copy.dst_offset; | 1571 | const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; |
| 1554 | cpu_memory.ReadBlockUnsafe(cpu_addr, src_pointer, copy.size); | 1572 | device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size); |
| 1555 | 1573 | ||
| 1556 | // Apply the staging offset | 1574 | // Apply the staging offset |
| 1557 | copy.src_offset += upload_staging.offset; | 1575 | copy.src_offset += upload_staging.offset; |
| @@ -1562,14 +1580,14 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer, | |||
| 1562 | } | 1580 | } |
| 1563 | 1581 | ||
| 1564 | template <class P> | 1582 | template <class P> |
| 1565 | bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size, | 1583 | bool BufferCache<P>::InlineMemory(DAddr dest_address, size_t copy_size, |
| 1566 | std::span<const u8> inlined_buffer) { | 1584 | std::span<const u8> inlined_buffer) { |
| 1567 | const bool is_dirty = IsRegionRegistered(dest_address, copy_size); | 1585 | const bool is_dirty = IsRegionRegistered(dest_address, copy_size); |
| 1568 | if (!is_dirty) { | 1586 | if (!is_dirty) { |
| 1569 | return false; | 1587 | return false; |
| 1570 | } | 1588 | } |
| 1571 | VAddr aligned_start = Common::AlignDown(dest_address, YUZU_PAGESIZE); | 1589 | DAddr aligned_start = Common::AlignDown(dest_address, DEVICE_PAGESIZE); |
| 1572 | VAddr aligned_end = Common::AlignUp(dest_address + copy_size, YUZU_PAGESIZE); | 1590 | DAddr aligned_end = Common::AlignUp(dest_address + copy_size, DEVICE_PAGESIZE); |
| 1573 | if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { | 1591 | if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { |
| 1574 | return false; | 1592 | return false; |
| 1575 | } | 1593 | } |
| @@ -1580,7 +1598,7 @@ bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size, | |||
| 1580 | } | 1598 | } |
| 1581 | 1599 | ||
| 1582 | template <class P> | 1600 | template <class P> |
| 1583 | void BufferCache<P>::InlineMemoryImplementation(VAddr dest_address, size_t copy_size, | 1601 | void BufferCache<P>::InlineMemoryImplementation(DAddr dest_address, size_t copy_size, |
| 1584 | std::span<const u8> inlined_buffer) { | 1602 | std::span<const u8> inlined_buffer) { |
| 1585 | const IntervalType subtract_interval{dest_address, dest_address + copy_size}; | 1603 | const IntervalType subtract_interval{dest_address, dest_address + copy_size}; |
| 1586 | ClearDownload(subtract_interval); | 1604 | ClearDownload(subtract_interval); |
| @@ -1612,14 +1630,14 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer) { | |||
| 1612 | } | 1630 | } |
| 1613 | 1631 | ||
| 1614 | template <class P> | 1632 | template <class P> |
| 1615 | void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 size) { | 1633 | void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64 size) { |
| 1616 | boost::container::small_vector<BufferCopy, 1> copies; | 1634 | boost::container::small_vector<BufferCopy, 1> copies; |
| 1617 | u64 total_size_bytes = 0; | 1635 | u64 total_size_bytes = 0; |
| 1618 | u64 largest_copy = 0; | 1636 | u64 largest_copy = 0; |
| 1619 | memory_tracker.ForEachDownloadRangeAndClear( | 1637 | memory_tracker.ForEachDownloadRangeAndClear( |
| 1620 | cpu_addr, size, [&](u64 cpu_addr_out, u64 range_size) { | 1638 | device_addr, size, [&](u64 device_addr_out, u64 range_size) { |
| 1621 | const VAddr buffer_addr = buffer.CpuAddr(); | 1639 | const DAddr buffer_addr = buffer.CpuAddr(); |
| 1622 | const auto add_download = [&](VAddr start, VAddr end) { | 1640 | const auto add_download = [&](DAddr start, DAddr end) { |
| 1623 | const u64 new_offset = start - buffer_addr; | 1641 | const u64 new_offset = start - buffer_addr; |
| 1624 | const u64 new_size = end - start; | 1642 | const u64 new_size = end - start; |
| 1625 | copies.push_back(BufferCopy{ | 1643 | copies.push_back(BufferCopy{ |
| @@ -1634,8 +1652,8 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si | |||
| 1634 | largest_copy = std::max(largest_copy, new_size); | 1652 | largest_copy = std::max(largest_copy, new_size); |
| 1635 | }; | 1653 | }; |
| 1636 | 1654 | ||
| 1637 | const VAddr start_address = cpu_addr_out; | 1655 | const DAddr start_address = device_addr_out; |
| 1638 | const VAddr end_address = start_address + range_size; | 1656 | const DAddr end_address = start_address + range_size; |
| 1639 | ForEachInRangeSet(common_ranges, start_address, range_size, add_download); | 1657 | ForEachInRangeSet(common_ranges, start_address, range_size, add_download); |
| 1640 | const IntervalType subtract_interval{start_address, end_address}; | 1658 | const IntervalType subtract_interval{start_address, end_address}; |
| 1641 | ClearDownload(subtract_interval); | 1659 | ClearDownload(subtract_interval); |
| @@ -1658,18 +1676,18 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si | |||
| 1658 | runtime.CopyBuffer(download_staging.buffer, buffer, copies_span, true); | 1676 | runtime.CopyBuffer(download_staging.buffer, buffer, copies_span, true); |
| 1659 | runtime.Finish(); | 1677 | runtime.Finish(); |
| 1660 | for (const BufferCopy& copy : copies) { | 1678 | for (const BufferCopy& copy : copies) { |
| 1661 | const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset; | 1679 | const DAddr copy_device_addr = buffer.CpuAddr() + copy.src_offset; |
| 1662 | // Undo the modified offset | 1680 | // Undo the modified offset |
| 1663 | const u64 dst_offset = copy.dst_offset - download_staging.offset; | 1681 | const u64 dst_offset = copy.dst_offset - download_staging.offset; |
| 1664 | const u8* copy_mapped_memory = mapped_memory + dst_offset; | 1682 | const u8* copy_mapped_memory = mapped_memory + dst_offset; |
| 1665 | cpu_memory.WriteBlockUnsafe(copy_cpu_addr, copy_mapped_memory, copy.size); | 1683 | device_memory.WriteBlockUnsafe(copy_device_addr, copy_mapped_memory, copy.size); |
| 1666 | } | 1684 | } |
| 1667 | } else { | 1685 | } else { |
| 1668 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); | 1686 | const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); |
| 1669 | for (const BufferCopy& copy : copies) { | 1687 | for (const BufferCopy& copy : copies) { |
| 1670 | buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); | 1688 | buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); |
| 1671 | const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset; | 1689 | const DAddr copy_device_addr = buffer.CpuAddr() + copy.src_offset; |
| 1672 | cpu_memory.WriteBlockUnsafe(copy_cpu_addr, immediate_buffer.data(), copy.size); | 1690 | device_memory.WriteBlockUnsafe(copy_device_addr, immediate_buffer.data(), copy.size); |
| 1673 | } | 1691 | } |
| 1674 | } | 1692 | } |
| 1675 | } | 1693 | } |
| @@ -1758,20 +1776,20 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index, | |||
| 1758 | const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment); | 1776 | const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment); |
| 1759 | const u32 aligned_size = static_cast<u32>(gpu_addr - aligned_gpu_addr) + size; | 1777 | const u32 aligned_size = static_cast<u32>(gpu_addr - aligned_gpu_addr) + size; |
| 1760 | 1778 | ||
| 1761 | const std::optional<VAddr> aligned_cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr); | 1779 | const std::optional<DAddr> aligned_device_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr); |
| 1762 | if (!aligned_cpu_addr || size == 0) { | 1780 | if (!aligned_device_addr || size == 0) { |
| 1763 | LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index); | 1781 | LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index); |
| 1764 | return NULL_BINDING; | 1782 | return NULL_BINDING; |
| 1765 | } | 1783 | } |
| 1766 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1784 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1767 | ASSERT_MSG(cpu_addr, "Unaligned storage buffer address not found for cbuf index {}", | 1785 | ASSERT_MSG(device_addr, "Unaligned storage buffer address not found for cbuf index {}", |
| 1768 | cbuf_index); | 1786 | cbuf_index); |
| 1769 | // The end address used for size calculation does not need to be aligned | 1787 | // The end address used for size calculation does not need to be aligned |
| 1770 | const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, Core::Memory::YUZU_PAGESIZE); | 1788 | const DAddr cpu_end = Common::AlignUp(*device_addr + size, Core::DEVICE_PAGESIZE); |
| 1771 | 1789 | ||
| 1772 | const Binding binding{ | 1790 | const Binding binding{ |
| 1773 | .cpu_addr = *aligned_cpu_addr, | 1791 | .device_addr = *aligned_device_addr, |
| 1774 | .size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_cpu_addr), | 1792 | .size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_device_addr), |
| 1775 | .buffer_id = BufferId{}, | 1793 | .buffer_id = BufferId{}, |
| 1776 | }; | 1794 | }; |
| 1777 | return binding; | 1795 | return binding; |
| @@ -1780,15 +1798,15 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index, | |||
| 1780 | template <class P> | 1798 | template <class P> |
| 1781 | TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, | 1799 | TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, |
| 1782 | PixelFormat format) { | 1800 | PixelFormat format) { |
| 1783 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1801 | const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1784 | TextureBufferBinding binding; | 1802 | TextureBufferBinding binding; |
| 1785 | if (!cpu_addr || size == 0) { | 1803 | if (!device_addr || size == 0) { |
| 1786 | binding.cpu_addr = 0; | 1804 | binding.device_addr = 0; |
| 1787 | binding.size = 0; | 1805 | binding.size = 0; |
| 1788 | binding.buffer_id = NULL_BUFFER_ID; | 1806 | binding.buffer_id = NULL_BUFFER_ID; |
| 1789 | binding.format = PixelFormat::Invalid; | 1807 | binding.format = PixelFormat::Invalid; |
| 1790 | } else { | 1808 | } else { |
| 1791 | binding.cpu_addr = *cpu_addr; | 1809 | binding.device_addr = *device_addr; |
| 1792 | binding.size = size; | 1810 | binding.size = size; |
| 1793 | binding.buffer_id = BufferId{}; | 1811 | binding.buffer_id = BufferId{}; |
| 1794 | binding.format = format; | 1812 | binding.format = format; |
| @@ -1797,14 +1815,14 @@ TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr, | |||
| 1797 | } | 1815 | } |
| 1798 | 1816 | ||
| 1799 | template <class P> | 1817 | template <class P> |
| 1800 | std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) { | 1818 | std::span<const u8> BufferCache<P>::ImmediateBufferWithData(DAddr device_addr, size_t size) { |
| 1801 | u8* const base_pointer = cpu_memory.GetPointer(cpu_addr); | 1819 | u8* const base_pointer = device_memory.GetPointer<u8>(device_addr); |
| 1802 | if (IsRangeGranular(cpu_addr, size) || | 1820 | if (IsRangeGranular(device_addr, size) || |
| 1803 | base_pointer + size == cpu_memory.GetPointer(cpu_addr + size)) { | 1821 | base_pointer + size == device_memory.GetPointer<u8>(device_addr + size)) { |
| 1804 | return std::span(base_pointer, size); | 1822 | return std::span(base_pointer, size); |
| 1805 | } else { | 1823 | } else { |
| 1806 | const std::span<u8> span = ImmediateBuffer(size); | 1824 | const std::span<u8> span = ImmediateBuffer(size); |
| 1807 | cpu_memory.ReadBlockUnsafe(cpu_addr, span.data(), size); | 1825 | device_memory.ReadBlockUnsafe(device_addr, span.data(), size); |
| 1808 | return span; | 1826 | return span; |
| 1809 | } | 1827 | } |
| 1810 | } | 1828 | } |
| @@ -1828,13 +1846,14 @@ bool BufferCache<P>::HasFastUniformBufferBound(size_t stage, u32 binding_index) | |||
| 1828 | template <class P> | 1846 | template <class P> |
| 1829 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectCount() { | 1847 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectCount() { |
| 1830 | auto& buffer = slot_buffers[channel_state->count_buffer_binding.buffer_id]; | 1848 | auto& buffer = slot_buffers[channel_state->count_buffer_binding.buffer_id]; |
| 1831 | return std::make_pair(&buffer, buffer.Offset(channel_state->count_buffer_binding.cpu_addr)); | 1849 | return std::make_pair(&buffer, buffer.Offset(channel_state->count_buffer_binding.device_addr)); |
| 1832 | } | 1850 | } |
| 1833 | 1851 | ||
| 1834 | template <class P> | 1852 | template <class P> |
| 1835 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectBuffer() { | 1853 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectBuffer() { |
| 1836 | auto& buffer = slot_buffers[channel_state->indirect_buffer_binding.buffer_id]; | 1854 | auto& buffer = slot_buffers[channel_state->indirect_buffer_binding.buffer_id]; |
| 1837 | return std::make_pair(&buffer, buffer.Offset(channel_state->indirect_buffer_binding.cpu_addr)); | 1855 | return std::make_pair(&buffer, |
| 1856 | buffer.Offset(channel_state->indirect_buffer_binding.device_addr)); | ||
| 1838 | } | 1857 | } |
| 1839 | 1858 | ||
| 1840 | } // namespace VideoCommon | 1859 | } // namespace VideoCommon |
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index d6d696d8c..80dbb81e7 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include "common/microprofile.h" | 32 | #include "common/microprofile.h" |
| 33 | #include "common/scope_exit.h" | 33 | #include "common/scope_exit.h" |
| 34 | #include "common/settings.h" | 34 | #include "common/settings.h" |
| 35 | #include "core/memory.h" | ||
| 36 | #include "video_core/buffer_cache/buffer_base.h" | 35 | #include "video_core/buffer_cache/buffer_base.h" |
| 37 | #include "video_core/control/channel_state_cache.h" | 36 | #include "video_core/control/channel_state_cache.h" |
| 38 | #include "video_core/delayed_destruction_ring.h" | 37 | #include "video_core/delayed_destruction_ring.h" |
| @@ -41,7 +40,6 @@ | |||
| 41 | #include "video_core/engines/kepler_compute.h" | 40 | #include "video_core/engines/kepler_compute.h" |
| 42 | #include "video_core/engines/maxwell_3d.h" | 41 | #include "video_core/engines/maxwell_3d.h" |
| 43 | #include "video_core/memory_manager.h" | 42 | #include "video_core/memory_manager.h" |
| 44 | #include "video_core/rasterizer_interface.h" | ||
| 45 | #include "video_core/surface.h" | 43 | #include "video_core/surface.h" |
| 46 | #include "video_core/texture_cache/slot_vector.h" | 44 | #include "video_core/texture_cache/slot_vector.h" |
| 47 | #include "video_core/texture_cache/types.h" | 45 | #include "video_core/texture_cache/types.h" |
| @@ -94,7 +92,7 @@ static constexpr BufferId NULL_BUFFER_ID{0}; | |||
| 94 | static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB); | 92 | static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB); |
| 95 | 93 | ||
| 96 | struct Binding { | 94 | struct Binding { |
| 97 | VAddr cpu_addr{}; | 95 | DAddr device_addr{}; |
| 98 | u32 size{}; | 96 | u32 size{}; |
| 99 | BufferId buffer_id; | 97 | BufferId buffer_id; |
| 100 | }; | 98 | }; |
| @@ -104,7 +102,7 @@ struct TextureBufferBinding : Binding { | |||
| 104 | }; | 102 | }; |
| 105 | 103 | ||
| 106 | static constexpr Binding NULL_BINDING{ | 104 | static constexpr Binding NULL_BINDING{ |
| 107 | .cpu_addr = 0, | 105 | .device_addr = 0, |
| 108 | .size = 0, | 106 | .size = 0, |
| 109 | .buffer_id = NULL_BUFFER_ID, | 107 | .buffer_id = NULL_BUFFER_ID, |
| 110 | }; | 108 | }; |
| @@ -204,10 +202,10 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf | |||
| 204 | using Async_Buffer = typename P::Async_Buffer; | 202 | using Async_Buffer = typename P::Async_Buffer; |
| 205 | using MemoryTracker = typename P::MemoryTracker; | 203 | using MemoryTracker = typename P::MemoryTracker; |
| 206 | 204 | ||
| 207 | using IntervalCompare = std::less<VAddr>; | 205 | using IntervalCompare = std::less<DAddr>; |
| 208 | using IntervalInstance = boost::icl::interval_type_default<VAddr, std::less>; | 206 | using IntervalInstance = boost::icl::interval_type_default<DAddr, std::less>; |
| 209 | using IntervalAllocator = boost::fast_pool_allocator<VAddr>; | 207 | using IntervalAllocator = boost::fast_pool_allocator<DAddr>; |
| 210 | using IntervalSet = boost::icl::interval_set<VAddr>; | 208 | using IntervalSet = boost::icl::interval_set<DAddr>; |
| 211 | using IntervalType = typename IntervalSet::interval_type; | 209 | using IntervalType = typename IntervalSet::interval_type; |
| 212 | 210 | ||
| 213 | template <typename Type> | 211 | template <typename Type> |
| @@ -230,32 +228,31 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf | |||
| 230 | 228 | ||
| 231 | using OverlapCombine = counter_add_functor<int>; | 229 | using OverlapCombine = counter_add_functor<int>; |
| 232 | using OverlapSection = boost::icl::inter_section<int>; | 230 | using OverlapSection = boost::icl::inter_section<int>; |
| 233 | using OverlapCounter = boost::icl::split_interval_map<VAddr, int>; | 231 | using OverlapCounter = boost::icl::split_interval_map<DAddr, int>; |
| 234 | 232 | ||
| 235 | struct OverlapResult { | 233 | struct OverlapResult { |
| 236 | boost::container::small_vector<BufferId, 16> ids; | 234 | boost::container::small_vector<BufferId, 16> ids; |
| 237 | VAddr begin; | 235 | DAddr begin; |
| 238 | VAddr end; | 236 | DAddr end; |
| 239 | bool has_stream_leap = false; | 237 | bool has_stream_leap = false; |
| 240 | }; | 238 | }; |
| 241 | 239 | ||
| 242 | public: | 240 | public: |
| 243 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer_, | 241 | explicit BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, Runtime& runtime_); |
| 244 | Core::Memory::Memory& cpu_memory_, Runtime& runtime_); | ||
| 245 | 242 | ||
| 246 | void TickFrame(); | 243 | void TickFrame(); |
| 247 | 244 | ||
| 248 | void WriteMemory(VAddr cpu_addr, u64 size); | 245 | void WriteMemory(DAddr device_addr, u64 size); |
| 249 | 246 | ||
| 250 | void CachedWriteMemory(VAddr cpu_addr, u64 size); | 247 | void CachedWriteMemory(DAddr device_addr, u64 size); |
| 251 | 248 | ||
| 252 | bool OnCPUWrite(VAddr cpu_addr, u64 size); | 249 | bool OnCPUWrite(DAddr device_addr, u64 size); |
| 253 | 250 | ||
| 254 | void DownloadMemory(VAddr cpu_addr, u64 size); | 251 | void DownloadMemory(DAddr device_addr, u64 size); |
| 255 | 252 | ||
| 256 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); | 253 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(DAddr device_addr, u64 size); |
| 257 | 254 | ||
| 258 | bool InlineMemory(VAddr dest_address, size_t copy_size, std::span<const u8> inlined_buffer); | 255 | bool InlineMemory(DAddr dest_address, size_t copy_size, std::span<const u8> inlined_buffer); |
| 259 | 256 | ||
| 260 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size); | 257 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size); |
| 261 | 258 | ||
| @@ -300,7 +297,7 @@ public: | |||
| 300 | ObtainBufferSynchronize sync_info, | 297 | ObtainBufferSynchronize sync_info, |
| 301 | ObtainBufferOperation post_op); | 298 | ObtainBufferOperation post_op); |
| 302 | 299 | ||
| 303 | [[nodiscard]] std::pair<Buffer*, u32> ObtainCPUBuffer(VAddr gpu_addr, u32 size, | 300 | [[nodiscard]] std::pair<Buffer*, u32> ObtainCPUBuffer(DAddr gpu_addr, u32 size, |
| 304 | ObtainBufferSynchronize sync_info, | 301 | ObtainBufferSynchronize sync_info, |
| 305 | ObtainBufferOperation post_op); | 302 | ObtainBufferOperation post_op); |
| 306 | void FlushCachedWrites(); | 303 | void FlushCachedWrites(); |
| @@ -326,13 +323,13 @@ public: | |||
| 326 | bool DMAClear(GPUVAddr src_address, u64 amount, u32 value); | 323 | bool DMAClear(GPUVAddr src_address, u64 amount, u32 value); |
| 327 | 324 | ||
| 328 | /// Return true when a CPU region is modified from the GPU | 325 | /// Return true when a CPU region is modified from the GPU |
| 329 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); | 326 | [[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size); |
| 330 | 327 | ||
| 331 | /// Return true when a region is registered on the cache | 328 | /// Return true when a region is registered on the cache |
| 332 | [[nodiscard]] bool IsRegionRegistered(VAddr addr, size_t size); | 329 | [[nodiscard]] bool IsRegionRegistered(DAddr addr, size_t size); |
| 333 | 330 | ||
| 334 | /// Return true when a CPU region is modified from the CPU | 331 | /// Return true when a CPU region is modified from the CPU |
| 335 | [[nodiscard]] bool IsRegionCpuModified(VAddr addr, size_t size); | 332 | [[nodiscard]] bool IsRegionCpuModified(DAddr addr, size_t size); |
| 336 | 333 | ||
| 337 | void SetDrawIndirect( | 334 | void SetDrawIndirect( |
| 338 | const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) { | 335 | const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) { |
| @@ -366,9 +363,9 @@ private: | |||
| 366 | } | 363 | } |
| 367 | 364 | ||
| 368 | template <typename Func> | 365 | template <typename Func> |
| 369 | void ForEachBufferInRange(VAddr cpu_addr, u64 size, Func&& func) { | 366 | void ForEachBufferInRange(DAddr device_addr, u64 size, Func&& func) { |
| 370 | const u64 page_end = Common::DivCeil(cpu_addr + size, CACHING_PAGESIZE); | 367 | const u64 page_end = Common::DivCeil(device_addr + size, CACHING_PAGESIZE); |
| 371 | for (u64 page = cpu_addr >> CACHING_PAGEBITS; page < page_end;) { | 368 | for (u64 page = device_addr >> CACHING_PAGEBITS; page < page_end;) { |
| 372 | const BufferId buffer_id = page_table[page]; | 369 | const BufferId buffer_id = page_table[page]; |
| 373 | if (!buffer_id) { | 370 | if (!buffer_id) { |
| 374 | ++page; | 371 | ++page; |
| @@ -377,15 +374,15 @@ private: | |||
| 377 | Buffer& buffer = slot_buffers[buffer_id]; | 374 | Buffer& buffer = slot_buffers[buffer_id]; |
| 378 | func(buffer_id, buffer); | 375 | func(buffer_id, buffer); |
| 379 | 376 | ||
| 380 | const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes(); | 377 | const DAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes(); |
| 381 | page = Common::DivCeil(end_addr, CACHING_PAGESIZE); | 378 | page = Common::DivCeil(end_addr, CACHING_PAGESIZE); |
| 382 | } | 379 | } |
| 383 | } | 380 | } |
| 384 | 381 | ||
| 385 | template <typename Func> | 382 | template <typename Func> |
| 386 | void ForEachInRangeSet(IntervalSet& current_range, VAddr cpu_addr, u64 size, Func&& func) { | 383 | void ForEachInRangeSet(IntervalSet& current_range, DAddr device_addr, u64 size, Func&& func) { |
| 387 | const VAddr start_address = cpu_addr; | 384 | const DAddr start_address = device_addr; |
| 388 | const VAddr end_address = start_address + size; | 385 | const DAddr end_address = start_address + size; |
| 389 | const IntervalType search_interval{start_address, end_address}; | 386 | const IntervalType search_interval{start_address, end_address}; |
| 390 | auto it = current_range.lower_bound(search_interval); | 387 | auto it = current_range.lower_bound(search_interval); |
| 391 | if (it == current_range.end()) { | 388 | if (it == current_range.end()) { |
| @@ -393,8 +390,8 @@ private: | |||
| 393 | } | 390 | } |
| 394 | auto end_it = current_range.upper_bound(search_interval); | 391 | auto end_it = current_range.upper_bound(search_interval); |
| 395 | for (; it != end_it; it++) { | 392 | for (; it != end_it; it++) { |
| 396 | VAddr inter_addr_end = it->upper(); | 393 | DAddr inter_addr_end = it->upper(); |
| 397 | VAddr inter_addr = it->lower(); | 394 | DAddr inter_addr = it->lower(); |
| 398 | if (inter_addr_end > end_address) { | 395 | if (inter_addr_end > end_address) { |
| 399 | inter_addr_end = end_address; | 396 | inter_addr_end = end_address; |
| 400 | } | 397 | } |
| @@ -406,10 +403,10 @@ private: | |||
| 406 | } | 403 | } |
| 407 | 404 | ||
| 408 | template <typename Func> | 405 | template <typename Func> |
| 409 | void ForEachInOverlapCounter(OverlapCounter& current_range, VAddr cpu_addr, u64 size, | 406 | void ForEachInOverlapCounter(OverlapCounter& current_range, DAddr device_addr, u64 size, |
| 410 | Func&& func) { | 407 | Func&& func) { |
| 411 | const VAddr start_address = cpu_addr; | 408 | const DAddr start_address = device_addr; |
| 412 | const VAddr end_address = start_address + size; | 409 | const DAddr end_address = start_address + size; |
| 413 | const IntervalType search_interval{start_address, end_address}; | 410 | const IntervalType search_interval{start_address, end_address}; |
| 414 | auto it = current_range.lower_bound(search_interval); | 411 | auto it = current_range.lower_bound(search_interval); |
| 415 | if (it == current_range.end()) { | 412 | if (it == current_range.end()) { |
| @@ -418,8 +415,8 @@ private: | |||
| 418 | auto end_it = current_range.upper_bound(search_interval); | 415 | auto end_it = current_range.upper_bound(search_interval); |
| 419 | for (; it != end_it; it++) { | 416 | for (; it != end_it; it++) { |
| 420 | auto& inter = it->first; | 417 | auto& inter = it->first; |
| 421 | VAddr inter_addr_end = inter.upper(); | 418 | DAddr inter_addr_end = inter.upper(); |
| 422 | VAddr inter_addr = inter.lower(); | 419 | DAddr inter_addr = inter.lower(); |
| 423 | if (inter_addr_end > end_address) { | 420 | if (inter_addr_end > end_address) { |
| 424 | inter_addr_end = end_address; | 421 | inter_addr_end = end_address; |
| 425 | } | 422 | } |
| @@ -451,9 +448,9 @@ private: | |||
| 451 | } while (any_removals); | 448 | } while (any_removals); |
| 452 | } | 449 | } |
| 453 | 450 | ||
| 454 | static bool IsRangeGranular(VAddr cpu_addr, size_t size) { | 451 | static bool IsRangeGranular(DAddr device_addr, size_t size) { |
| 455 | return (cpu_addr & ~Core::Memory::YUZU_PAGEMASK) == | 452 | return (device_addr & ~Core::DEVICE_PAGEMASK) == |
| 456 | ((cpu_addr + size) & ~Core::Memory::YUZU_PAGEMASK); | 453 | ((device_addr + size) & ~Core::DEVICE_PAGEMASK); |
| 457 | } | 454 | } |
| 458 | 455 | ||
| 459 | void RunGarbageCollector(); | 456 | void RunGarbageCollector(); |
| @@ -508,15 +505,15 @@ private: | |||
| 508 | 505 | ||
| 509 | void UpdateComputeTextureBuffers(); | 506 | void UpdateComputeTextureBuffers(); |
| 510 | 507 | ||
| 511 | void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size); | 508 | void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size); |
| 512 | 509 | ||
| 513 | [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); | 510 | [[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size); |
| 514 | 511 | ||
| 515 | [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size); | 512 | [[nodiscard]] OverlapResult ResolveOverlaps(DAddr device_addr, u32 wanted_size); |
| 516 | 513 | ||
| 517 | void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score); | 514 | void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score); |
| 518 | 515 | ||
| 519 | [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); | 516 | [[nodiscard]] BufferId CreateBuffer(DAddr device_addr, u32 wanted_size); |
| 520 | 517 | ||
| 521 | void Register(BufferId buffer_id); | 518 | void Register(BufferId buffer_id); |
| 522 | 519 | ||
| @@ -527,7 +524,7 @@ private: | |||
| 527 | 524 | ||
| 528 | void TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept; | 525 | void TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept; |
| 529 | 526 | ||
| 530 | bool SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size); | 527 | bool SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size); |
| 531 | 528 | ||
| 532 | void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, | 529 | void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, |
| 533 | std::span<BufferCopy> copies); | 530 | std::span<BufferCopy> copies); |
| @@ -539,7 +536,7 @@ private: | |||
| 539 | 536 | ||
| 540 | void DownloadBufferMemory(Buffer& buffer_id); | 537 | void DownloadBufferMemory(Buffer& buffer_id); |
| 541 | 538 | ||
| 542 | void DownloadBufferMemory(Buffer& buffer_id, VAddr cpu_addr, u64 size); | 539 | void DownloadBufferMemory(Buffer& buffer_id, DAddr device_addr, u64 size); |
| 543 | 540 | ||
| 544 | void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false); | 541 | void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false); |
| 545 | 542 | ||
| @@ -549,7 +546,7 @@ private: | |||
| 549 | [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, | 546 | [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, |
| 550 | PixelFormat format); | 547 | PixelFormat format); |
| 551 | 548 | ||
| 552 | [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size); | 549 | [[nodiscard]] std::span<const u8> ImmediateBufferWithData(DAddr device_addr, size_t size); |
| 553 | 550 | ||
| 554 | [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); | 551 | [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); |
| 555 | 552 | ||
| @@ -557,11 +554,10 @@ private: | |||
| 557 | 554 | ||
| 558 | void ClearDownload(IntervalType subtract_interval); | 555 | void ClearDownload(IntervalType subtract_interval); |
| 559 | 556 | ||
| 560 | void InlineMemoryImplementation(VAddr dest_address, size_t copy_size, | 557 | void InlineMemoryImplementation(DAddr dest_address, size_t copy_size, |
| 561 | std::span<const u8> inlined_buffer); | 558 | std::span<const u8> inlined_buffer); |
| 562 | 559 | ||
| 563 | VideoCore::RasterizerInterface& rasterizer; | 560 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 564 | Core::Memory::Memory& cpu_memory; | ||
| 565 | 561 | ||
| 566 | SlotVector<Buffer> slot_buffers; | 562 | SlotVector<Buffer> slot_buffers; |
| 567 | DelayedDestructionRing<Buffer, 8> delayed_destruction_ring; | 563 | DelayedDestructionRing<Buffer, 8> delayed_destruction_ring; |
| @@ -598,7 +594,7 @@ private: | |||
| 598 | u64 critical_memory = 0; | 594 | u64 critical_memory = 0; |
| 599 | BufferId inline_buffer_id; | 595 | BufferId inline_buffer_id; |
| 600 | 596 | ||
| 601 | std::array<BufferId, ((1ULL << 39) >> CACHING_PAGEBITS)> page_table; | 597 | std::array<BufferId, ((1ULL << 34) >> CACHING_PAGEBITS)> page_table; |
| 602 | Common::ScratchBuffer<u8> tmp_buffer; | 598 | Common::ScratchBuffer<u8> tmp_buffer; |
| 603 | }; | 599 | }; |
| 604 | 600 | ||
diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h index 6c1c8287b..c95eed1f6 100644 --- a/src/video_core/buffer_cache/memory_tracker_base.h +++ b/src/video_core/buffer_cache/memory_tracker_base.h | |||
| @@ -17,19 +17,19 @@ | |||
| 17 | 17 | ||
| 18 | namespace VideoCommon { | 18 | namespace VideoCommon { |
| 19 | 19 | ||
| 20 | template <class RasterizerInterface> | 20 | template <typename DeviceTracker> |
| 21 | class MemoryTrackerBase { | 21 | class MemoryTrackerBase { |
| 22 | static constexpr size_t MAX_CPU_PAGE_BITS = 39; | 22 | static constexpr size_t MAX_CPU_PAGE_BITS = 34; |
| 23 | static constexpr size_t HIGHER_PAGE_BITS = 22; | 23 | static constexpr size_t HIGHER_PAGE_BITS = 22; |
| 24 | static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS; | 24 | static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS; |
| 25 | static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL; | 25 | static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL; |
| 26 | static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS); | 26 | static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS); |
| 27 | static constexpr size_t MANAGER_POOL_SIZE = 32; | 27 | static constexpr size_t MANAGER_POOL_SIZE = 32; |
| 28 | static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD; | 28 | static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD; |
| 29 | using Manager = WordManager<RasterizerInterface, WORDS_STACK_NEEDED>; | 29 | using Manager = WordManager<DeviceTracker, WORDS_STACK_NEEDED>; |
| 30 | 30 | ||
| 31 | public: | 31 | public: |
| 32 | MemoryTrackerBase(RasterizerInterface& rasterizer_) : rasterizer{&rasterizer_} {} | 32 | MemoryTrackerBase(DeviceTracker& device_tracker_) : device_tracker{&device_tracker_} {} |
| 33 | ~MemoryTrackerBase() = default; | 33 | ~MemoryTrackerBase() = default; |
| 34 | 34 | ||
| 35 | /// Returns the inclusive CPU modified range in a begin end pair | 35 | /// Returns the inclusive CPU modified range in a begin end pair |
| @@ -74,7 +74,7 @@ public: | |||
| 74 | }); | 74 | }); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | /// Mark region as CPU modified, notifying the rasterizer about this change | 77 | /// Mark region as CPU modified, notifying the device_tracker about this change |
| 78 | void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { | 78 | void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { |
| 79 | IteratePages<true>(dirty_cpu_addr, query_size, | 79 | IteratePages<true>(dirty_cpu_addr, query_size, |
| 80 | [](Manager* manager, u64 offset, size_t size) { | 80 | [](Manager* manager, u64 offset, size_t size) { |
| @@ -83,7 +83,7 @@ public: | |||
| 83 | }); | 83 | }); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | /// Unmark region as CPU modified, notifying the rasterizer about this change | 86 | /// Unmark region as CPU modified, notifying the device_tracker about this change |
| 87 | void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { | 87 | void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { |
| 88 | IteratePages<true>(dirty_cpu_addr, query_size, | 88 | IteratePages<true>(dirty_cpu_addr, query_size, |
| 89 | [](Manager* manager, u64 offset, size_t size) { | 89 | [](Manager* manager, u64 offset, size_t size) { |
| @@ -139,7 +139,7 @@ public: | |||
| 139 | }); | 139 | }); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | /// Flushes cached CPU writes, and notify the rasterizer about the deltas | 142 | /// Flushes cached CPU writes, and notify the device_tracker about the deltas |
| 143 | void FlushCachedWrites(VAddr query_cpu_addr, u64 query_size) noexcept { | 143 | void FlushCachedWrites(VAddr query_cpu_addr, u64 query_size) noexcept { |
| 144 | IteratePages<false>(query_cpu_addr, query_size, | 144 | IteratePages<false>(query_cpu_addr, query_size, |
| 145 | [](Manager* manager, [[maybe_unused]] u64 offset, | 145 | [](Manager* manager, [[maybe_unused]] u64 offset, |
| @@ -280,7 +280,7 @@ private: | |||
| 280 | manager_pool.emplace_back(); | 280 | manager_pool.emplace_back(); |
| 281 | auto& last_pool = manager_pool.back(); | 281 | auto& last_pool = manager_pool.back(); |
| 282 | for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) { | 282 | for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) { |
| 283 | new (&last_pool[i]) Manager(0, *rasterizer, HIGHER_PAGE_SIZE); | 283 | new (&last_pool[i]) Manager(0, *device_tracker, HIGHER_PAGE_SIZE); |
| 284 | free_managers.push_back(&last_pool[i]); | 284 | free_managers.push_back(&last_pool[i]); |
| 285 | } | 285 | } |
| 286 | return on_return(); | 286 | return on_return(); |
| @@ -293,7 +293,7 @@ private: | |||
| 293 | 293 | ||
| 294 | std::unordered_set<u32> cached_pages; | 294 | std::unordered_set<u32> cached_pages; |
| 295 | 295 | ||
| 296 | RasterizerInterface* rasterizer = nullptr; | 296 | DeviceTracker* device_tracker = nullptr; |
| 297 | }; | 297 | }; |
| 298 | 298 | ||
| 299 | } // namespace VideoCommon | 299 | } // namespace VideoCommon |
diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h index a336bde41..3db9d8b42 100644 --- a/src/video_core/buffer_cache/word_manager.h +++ b/src/video_core/buffer_cache/word_manager.h | |||
| @@ -13,12 +13,12 @@ | |||
| 13 | #include "common/common_funcs.h" | 13 | #include "common/common_funcs.h" |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/div_ceil.h" | 15 | #include "common/div_ceil.h" |
| 16 | #include "core/memory.h" | 16 | #include "video_core/host1x/gpu_device_memory_manager.h" |
| 17 | 17 | ||
| 18 | namespace VideoCommon { | 18 | namespace VideoCommon { |
| 19 | 19 | ||
| 20 | constexpr u64 PAGES_PER_WORD = 64; | 20 | constexpr u64 PAGES_PER_WORD = 64; |
| 21 | constexpr u64 BYTES_PER_PAGE = Core::Memory::YUZU_PAGESIZE; | 21 | constexpr u64 BYTES_PER_PAGE = Core::DEVICE_PAGESIZE; |
| 22 | constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE; | 22 | constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE; |
| 23 | 23 | ||
| 24 | enum class Type { | 24 | enum class Type { |
| @@ -163,11 +163,11 @@ struct Words { | |||
| 163 | WordsArray<stack_words> preflushable; | 163 | WordsArray<stack_words> preflushable; |
| 164 | }; | 164 | }; |
| 165 | 165 | ||
| 166 | template <class RasterizerInterface, size_t stack_words = 1> | 166 | template <class DeviceTracker, size_t stack_words = 1> |
| 167 | class WordManager { | 167 | class WordManager { |
| 168 | public: | 168 | public: |
| 169 | explicit WordManager(VAddr cpu_addr_, RasterizerInterface& rasterizer_, u64 size_bytes) | 169 | explicit WordManager(VAddr cpu_addr_, DeviceTracker& tracker_, u64 size_bytes) |
| 170 | : cpu_addr{cpu_addr_}, rasterizer{&rasterizer_}, words{size_bytes} {} | 170 | : cpu_addr{cpu_addr_}, tracker{&tracker_}, words{size_bytes} {} |
| 171 | 171 | ||
| 172 | explicit WordManager() = default; | 172 | explicit WordManager() = default; |
| 173 | 173 | ||
| @@ -279,7 +279,7 @@ public: | |||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | /** | 281 | /** |
| 282 | * Loop over each page in the given range, turn off those bits and notify the rasterizer if | 282 | * Loop over each page in the given range, turn off those bits and notify the tracker if |
| 283 | * needed. Call the given function on each turned off range. | 283 | * needed. Call the given function on each turned off range. |
| 284 | * | 284 | * |
| 285 | * @param query_cpu_range Base CPU address to loop over | 285 | * @param query_cpu_range Base CPU address to loop over |
| @@ -459,26 +459,26 @@ private: | |||
| 459 | } | 459 | } |
| 460 | 460 | ||
| 461 | /** | 461 | /** |
| 462 | * Notify rasterizer about changes in the CPU tracking state of a word in the buffer | 462 | * Notify tracker about changes in the CPU tracking state of a word in the buffer |
| 463 | * | 463 | * |
| 464 | * @param word_index Index to the word to notify to the rasterizer | 464 | * @param word_index Index to the word to notify to the tracker |
| 465 | * @param current_bits Current state of the word | 465 | * @param current_bits Current state of the word |
| 466 | * @param new_bits New state of the word | 466 | * @param new_bits New state of the word |
| 467 | * | 467 | * |
| 468 | * @tparam add_to_rasterizer True when the rasterizer should start tracking the new pages | 468 | * @tparam add_to_tracker True when the tracker should start tracking the new pages |
| 469 | */ | 469 | */ |
| 470 | template <bool add_to_rasterizer> | 470 | template <bool add_to_tracker> |
| 471 | void NotifyRasterizer(u64 word_index, u64 current_bits, u64 new_bits) const { | 471 | void NotifyRasterizer(u64 word_index, u64 current_bits, u64 new_bits) const { |
| 472 | u64 changed_bits = (add_to_rasterizer ? current_bits : ~current_bits) & new_bits; | 472 | u64 changed_bits = (add_to_tracker ? current_bits : ~current_bits) & new_bits; |
| 473 | VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; | 473 | VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; |
| 474 | IteratePages(changed_bits, [&](size_t offset, size_t size) { | 474 | IteratePages(changed_bits, [&](size_t offset, size_t size) { |
| 475 | rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, | 475 | tracker->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, size * BYTES_PER_PAGE, |
| 476 | size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1); | 476 | add_to_tracker ? 1 : -1); |
| 477 | }); | 477 | }); |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | VAddr cpu_addr = 0; | 480 | VAddr cpu_addr = 0; |
| 481 | RasterizerInterface* rasterizer = nullptr; | 481 | DeviceTracker* tracker = nullptr; |
| 482 | Words<stack_words> words; | 482 | Words<stack_words> words; |
| 483 | }; | 483 | }; |
| 484 | 484 | ||
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 58ce0d8c2..fb2060ca4 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp | |||
| @@ -5,10 +5,10 @@ | |||
| 5 | #include "common/microprofile.h" | 5 | #include "common/microprofile.h" |
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/memory.h" | ||
| 9 | #include "video_core/dma_pusher.h" | 8 | #include "video_core/dma_pusher.h" |
| 10 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
| 11 | #include "video_core/gpu.h" | 10 | #include "video_core/gpu.h" |
| 11 | #include "video_core/guest_memory.h" | ||
| 12 | #include "video_core/memory_manager.h" | 12 | #include "video_core/memory_manager.h" |
| 13 | 13 | ||
| 14 | namespace Tegra { | 14 | namespace Tegra { |
| @@ -85,15 +85,15 @@ bool DmaPusher::Step() { | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | const auto safe_process = [&] { | 87 | const auto safe_process = [&] { |
| 88 | Core::Memory::GpuGuestMemory<Tegra::CommandHeader, | 88 | Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, |
| 89 | Core::Memory::GuestMemoryFlags::SafeRead> | 89 | Tegra::Memory::GuestMemoryFlags::SafeRead> |
| 90 | headers(memory_manager, dma_state.dma_get, command_list_header.size, | 90 | headers(memory_manager, dma_state.dma_get, command_list_header.size, |
| 91 | &command_headers); | 91 | &command_headers); |
| 92 | ProcessCommands(headers); | 92 | ProcessCommands(headers); |
| 93 | }; | 93 | }; |
| 94 | const auto unsafe_process = [&] { | 94 | const auto unsafe_process = [&] { |
| 95 | Core::Memory::GpuGuestMemory<Tegra::CommandHeader, | 95 | Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, |
| 96 | Core::Memory::GuestMemoryFlags::UnsafeRead> | 96 | Tegra::Memory::GuestMemoryFlags::UnsafeRead> |
| 97 | headers(memory_manager, dma_state.dma_get, command_list_header.size, | 97 | headers(memory_manager, dma_state.dma_get, command_list_header.size, |
| 98 | &command_headers); | 98 | &command_headers); |
| 99 | ProcessCommands(headers); | 99 | ProcessCommands(headers); |
diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp index bc64d4486..e5cc04ec4 100644 --- a/src/video_core/engines/engine_upload.cpp +++ b/src/video_core/engines/engine_upload.cpp | |||
| @@ -5,8 +5,8 @@ | |||
| 5 | 5 | ||
| 6 | #include "common/algorithm.h" | 6 | #include "common/algorithm.h" |
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "core/memory.h" | ||
| 9 | #include "video_core/engines/engine_upload.h" | 8 | #include "video_core/engines/engine_upload.h" |
| 9 | #include "video_core/guest_memory.h" | ||
| 10 | #include "video_core/memory_manager.h" | 10 | #include "video_core/memory_manager.h" |
| 11 | #include "video_core/rasterizer_interface.h" | 11 | #include "video_core/rasterizer_interface.h" |
| 12 | #include "video_core/textures/decoders.h" | 12 | #include "video_core/textures/decoders.h" |
| @@ -68,7 +68,8 @@ void State::ProcessData(std::span<const u8> read_buffer) { | |||
| 68 | true, bytes_per_pixel, width, regs.dest.height, regs.dest.depth, | 68 | true, bytes_per_pixel, width, regs.dest.height, regs.dest.depth, |
| 69 | regs.dest.BlockHeight(), regs.dest.BlockDepth()); | 69 | regs.dest.BlockHeight(), regs.dest.BlockDepth()); |
| 70 | 70 | ||
| 71 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> | 71 | Tegra::Memory::GpuGuestMemoryScoped<u8, |
| 72 | Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite> | ||
| 72 | tmp(memory_manager, address, dst_size, &tmp_buffer); | 73 | tmp(memory_manager, address, dst_size, &tmp_buffer); |
| 73 | 74 | ||
| 74 | Tegra::Texture::SwizzleSubrect(tmp, read_buffer, bytes_per_pixel, width, regs.dest.height, | 75 | Tegra::Texture::SwizzleSubrect(tmp, read_buffer, bytes_per_pixel, width, regs.dest.height, |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 95ba4f76c..a94e1f043 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/core_timing.h" | 11 | #include "core/core_timing.h" |
| 12 | #include "core/memory.h" | ||
| 13 | #include "video_core/dirty_flags.h" | 12 | #include "video_core/dirty_flags.h" |
| 14 | #include "video_core/engines/draw_manager.h" | 13 | #include "video_core/engines/draw_manager.h" |
| 15 | #include "video_core/engines/maxwell_3d.h" | 14 | #include "video_core/engines/maxwell_3d.h" |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 56fbff306..2ebd21fc5 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -8,9 +8,9 @@ | |||
| 8 | #include "common/polyfill_ranges.h" | 8 | #include "common/polyfill_ranges.h" |
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/memory.h" | ||
| 12 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 13 | #include "video_core/engines/maxwell_dma.h" | 12 | #include "video_core/engines/maxwell_dma.h" |
| 13 | #include "video_core/guest_memory.h" | ||
| 14 | #include "video_core/memory_manager.h" | 14 | #include "video_core/memory_manager.h" |
| 15 | #include "video_core/renderer_base.h" | 15 | #include "video_core/renderer_base.h" |
| 16 | #include "video_core/textures/decoders.h" | 16 | #include "video_core/textures/decoders.h" |
| @@ -133,8 +133,8 @@ void MaxwellDMA::Launch() { | |||
| 133 | UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); | 133 | UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); |
| 134 | read_buffer.resize_destructive(16); | 134 | read_buffer.resize_destructive(16); |
| 135 | for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { | 135 | for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { |
| 136 | Core::Memory::GpuGuestMemoryScoped< | 136 | Tegra::Memory::GpuGuestMemoryScoped< |
| 137 | u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> | 137 | u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite> |
| 138 | tmp_write_buffer(memory_manager, | 138 | tmp_write_buffer(memory_manager, |
| 139 | convert_linear_2_blocklinear_addr(regs.offset_in + offset), | 139 | convert_linear_2_blocklinear_addr(regs.offset_in + offset), |
| 140 | 16, &read_buffer); | 140 | 16, &read_buffer); |
| @@ -146,16 +146,16 @@ void MaxwellDMA::Launch() { | |||
| 146 | UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); | 146 | UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); |
| 147 | read_buffer.resize_destructive(16); | 147 | read_buffer.resize_destructive(16); |
| 148 | for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { | 148 | for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { |
| 149 | Core::Memory::GpuGuestMemoryScoped< | 149 | Tegra::Memory::GpuGuestMemoryScoped< |
| 150 | u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> | 150 | u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite> |
| 151 | tmp_write_buffer(memory_manager, regs.offset_in + offset, 16, &read_buffer); | 151 | tmp_write_buffer(memory_manager, regs.offset_in + offset, 16, &read_buffer); |
| 152 | tmp_write_buffer.SetAddressAndSize( | 152 | tmp_write_buffer.SetAddressAndSize( |
| 153 | convert_linear_2_blocklinear_addr(regs.offset_out + offset), 16); | 153 | convert_linear_2_blocklinear_addr(regs.offset_out + offset), 16); |
| 154 | } | 154 | } |
| 155 | } else { | 155 | } else { |
| 156 | if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { | 156 | if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { |
| 157 | Core::Memory::GpuGuestMemoryScoped< | 157 | Tegra::Memory::GpuGuestMemoryScoped< |
| 158 | u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> | 158 | u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite> |
| 159 | tmp_write_buffer(memory_manager, regs.offset_in, regs.line_length_in, | 159 | tmp_write_buffer(memory_manager, regs.offset_in, regs.line_length_in, |
| 160 | &read_buffer); | 160 | &read_buffer); |
| 161 | tmp_write_buffer.SetAddressAndSize(regs.offset_out, regs.line_length_in); | 161 | tmp_write_buffer.SetAddressAndSize(regs.offset_out, regs.line_length_in); |
| @@ -226,9 +226,9 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 226 | 226 | ||
| 227 | const size_t dst_size = dst_operand.pitch * regs.line_count; | 227 | const size_t dst_size = dst_operand.pitch * regs.line_count; |
| 228 | 228 | ||
| 229 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( | 229 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( |
| 230 | memory_manager, src_operand.address, src_size, &read_buffer); | 230 | memory_manager, src_operand.address, src_size, &read_buffer); |
| 231 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> | 231 | Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> |
| 232 | tmp_write_buffer(memory_manager, dst_operand.address, dst_size, &write_buffer); | 232 | tmp_write_buffer(memory_manager, dst_operand.address, dst_size, &write_buffer); |
| 233 | 233 | ||
| 234 | UnswizzleSubrect(tmp_write_buffer, tmp_read_buffer, bytes_per_pixel, width, height, depth, | 234 | UnswizzleSubrect(tmp_write_buffer, tmp_read_buffer, bytes_per_pixel, width, height, depth, |
| @@ -290,9 +290,9 @@ void MaxwellDMA::CopyPitchToBlockLinear() { | |||
| 290 | 290 | ||
| 291 | GPUVAddr src_addr = regs.offset_in; | 291 | GPUVAddr src_addr = regs.offset_in; |
| 292 | GPUVAddr dst_addr = regs.offset_out; | 292 | GPUVAddr dst_addr = regs.offset_out; |
| 293 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( | 293 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( |
| 294 | memory_manager, src_addr, src_size, &read_buffer); | 294 | memory_manager, src_addr, src_size, &read_buffer); |
| 295 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> | 295 | Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> |
| 296 | tmp_write_buffer(memory_manager, dst_addr, dst_size, &write_buffer); | 296 | tmp_write_buffer(memory_manager, dst_addr, dst_size, &write_buffer); |
| 297 | 297 | ||
| 298 | // If the input is linear and the output is tiled, swizzle the input and copy it over. | 298 | // If the input is linear and the output is tiled, swizzle the input and copy it over. |
| @@ -344,9 +344,9 @@ void MaxwellDMA::CopyBlockLinearToBlockLinear() { | |||
| 344 | 344 | ||
| 345 | intermediate_buffer.resize_destructive(mid_buffer_size); | 345 | intermediate_buffer.resize_destructive(mid_buffer_size); |
| 346 | 346 | ||
| 347 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( | 347 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( |
| 348 | memory_manager, regs.offset_in, src_size, &read_buffer); | 348 | memory_manager, regs.offset_in, src_size, &read_buffer); |
| 349 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> | 349 | Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite> |
| 350 | tmp_write_buffer(memory_manager, regs.offset_out, dst_size, &write_buffer); | 350 | tmp_write_buffer(memory_manager, regs.offset_out, dst_size, &write_buffer); |
| 351 | 351 | ||
| 352 | UnswizzleSubrect(intermediate_buffer, tmp_read_buffer, bytes_per_pixel, src_width, src.height, | 352 | UnswizzleSubrect(intermediate_buffer, tmp_read_buffer, bytes_per_pixel, src_width, src.height, |
diff --git a/src/video_core/engines/sw_blitter/blitter.cpp b/src/video_core/engines/sw_blitter/blitter.cpp index 67ce9134b..4bc079024 100644 --- a/src/video_core/engines/sw_blitter/blitter.cpp +++ b/src/video_core/engines/sw_blitter/blitter.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "common/scratch_buffer.h" | 8 | #include "common/scratch_buffer.h" |
| 9 | #include "video_core/engines/sw_blitter/blitter.h" | 9 | #include "video_core/engines/sw_blitter/blitter.h" |
| 10 | #include "video_core/engines/sw_blitter/converter.h" | 10 | #include "video_core/engines/sw_blitter/converter.h" |
| 11 | #include "video_core/guest_memory.h" | ||
| 11 | #include "video_core/memory_manager.h" | 12 | #include "video_core/memory_manager.h" |
| 12 | #include "video_core/surface.h" | 13 | #include "video_core/surface.h" |
| 13 | #include "video_core/textures/decoders.h" | 14 | #include "video_core/textures/decoders.h" |
| @@ -160,7 +161,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, | |||
| 160 | const auto dst_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(dst.format)); | 161 | const auto dst_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(dst.format)); |
| 161 | const size_t src_size = get_surface_size(src, src_bytes_per_pixel); | 162 | const size_t src_size = get_surface_size(src, src_bytes_per_pixel); |
| 162 | 163 | ||
| 163 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_buffer( | 164 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_buffer( |
| 164 | memory_manager, src.Address(), src_size, &impl->tmp_buffer); | 165 | memory_manager, src.Address(), src_size, &impl->tmp_buffer); |
| 165 | 166 | ||
| 166 | const size_t src_copy_size = src_extent_x * src_extent_y * src_bytes_per_pixel; | 167 | const size_t src_copy_size = src_extent_x * src_extent_y * src_bytes_per_pixel; |
| @@ -220,7 +221,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst, | |||
| 220 | } | 221 | } |
| 221 | 222 | ||
| 222 | const size_t dst_size = get_surface_size(dst, dst_bytes_per_pixel); | 223 | const size_t dst_size = get_surface_size(dst, dst_bytes_per_pixel); |
| 223 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadWrite> | 224 | Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::SafeReadWrite> |
| 224 | tmp_buffer2(memory_manager, dst.Address(), dst_size, &impl->tmp_buffer); | 225 | tmp_buffer2(memory_manager, dst.Address(), dst_size, &impl->tmp_buffer); |
| 225 | 226 | ||
| 226 | if (dst.linear == Fermi2D::MemoryLayout::BlockLinear) { | 227 | if (dst.linear == Fermi2D::MemoryLayout::BlockLinear) { |
diff --git a/src/video_core/framebuffer_config.h b/src/video_core/framebuffer_config.h index 5f3bffcab..856f4bd52 100644 --- a/src/video_core/framebuffer_config.h +++ b/src/video_core/framebuffer_config.h | |||
| @@ -14,7 +14,7 @@ namespace Tegra { | |||
| 14 | * Struct describing framebuffer configuration | 14 | * Struct describing framebuffer configuration |
| 15 | */ | 15 | */ |
| 16 | struct FramebufferConfig { | 16 | struct FramebufferConfig { |
| 17 | VAddr address{}; | 17 | DAddr address{}; |
| 18 | u32 offset{}; | 18 | u32 offset{}; |
| 19 | u32 width{}; | 19 | u32 width{}; |
| 20 | u32 height{}; | 20 | u32 height{}; |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 11549d448..609704b33 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -85,7 +85,8 @@ struct GPU::Impl { | |||
| 85 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { | 85 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { |
| 86 | renderer = std::move(renderer_); | 86 | renderer = std::move(renderer_); |
| 87 | rasterizer = renderer->ReadRasterizer(); | 87 | rasterizer = renderer->ReadRasterizer(); |
| 88 | host1x.MemoryManager().BindRasterizer(rasterizer); | 88 | host1x.MemoryManager().BindInterface(rasterizer); |
| 89 | host1x.GMMU().BindRasterizer(rasterizer); | ||
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | /// Flush all current written commands into the host GPU for execution. | 92 | /// Flush all current written commands into the host GPU for execution. |
| @@ -95,8 +96,8 @@ struct GPU::Impl { | |||
| 95 | 96 | ||
| 96 | /// Synchronizes CPU writes with Host GPU memory. | 97 | /// Synchronizes CPU writes with Host GPU memory. |
| 97 | void InvalidateGPUCache() { | 98 | void InvalidateGPUCache() { |
| 98 | std::function<void(VAddr, size_t)> callback_writes( | 99 | std::function<void(PAddr, size_t)> callback_writes( |
| 99 | [this](VAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); | 100 | [this](PAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); |
| 100 | system.GatherGPUDirtyMemory(callback_writes); | 101 | system.GatherGPUDirtyMemory(callback_writes); |
| 101 | } | 102 | } |
| 102 | 103 | ||
| @@ -279,11 +280,11 @@ struct GPU::Impl { | |||
| 279 | } | 280 | } |
| 280 | 281 | ||
| 281 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 282 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 282 | void FlushRegion(VAddr addr, u64 size) { | 283 | void FlushRegion(DAddr addr, u64 size) { |
| 283 | gpu_thread.FlushRegion(addr, size); | 284 | gpu_thread.FlushRegion(addr, size); |
| 284 | } | 285 | } |
| 285 | 286 | ||
| 286 | VideoCore::RasterizerDownloadArea OnCPURead(VAddr addr, u64 size) { | 287 | VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size) { |
| 287 | auto raster_area = rasterizer->GetFlushArea(addr, size); | 288 | auto raster_area = rasterizer->GetFlushArea(addr, size); |
| 288 | if (raster_area.preemtive) { | 289 | if (raster_area.preemtive) { |
| 289 | return raster_area; | 290 | return raster_area; |
| @@ -299,16 +300,16 @@ struct GPU::Impl { | |||
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | /// Notify rasterizer that any caches of the specified region should be invalidated | 302 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 302 | void InvalidateRegion(VAddr addr, u64 size) { | 303 | void InvalidateRegion(DAddr addr, u64 size) { |
| 303 | gpu_thread.InvalidateRegion(addr, size); | 304 | gpu_thread.InvalidateRegion(addr, size); |
| 304 | } | 305 | } |
| 305 | 306 | ||
| 306 | bool OnCPUWrite(VAddr addr, u64 size) { | 307 | bool OnCPUWrite(DAddr addr, u64 size) { |
| 307 | return rasterizer->OnCPUWrite(addr, size); | 308 | return rasterizer->OnCPUWrite(addr, size); |
| 308 | } | 309 | } |
| 309 | 310 | ||
| 310 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 311 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 311 | void FlushAndInvalidateRegion(VAddr addr, u64 size) { | 312 | void FlushAndInvalidateRegion(DAddr addr, u64 size) { |
| 312 | gpu_thread.FlushAndInvalidateRegion(addr, size); | 313 | gpu_thread.FlushAndInvalidateRegion(addr, size); |
| 313 | } | 314 | } |
| 314 | 315 | ||
| @@ -437,7 +438,7 @@ void GPU::OnCommandListEnd() { | |||
| 437 | impl->OnCommandListEnd(); | 438 | impl->OnCommandListEnd(); |
| 438 | } | 439 | } |
| 439 | 440 | ||
| 440 | u64 GPU::RequestFlush(VAddr addr, std::size_t size) { | 441 | u64 GPU::RequestFlush(DAddr addr, std::size_t size) { |
| 441 | return impl->RequestSyncOperation( | 442 | return impl->RequestSyncOperation( |
| 442 | [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); }); | 443 | [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); }); |
| 443 | } | 444 | } |
| @@ -557,23 +558,23 @@ void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 557 | impl->SwapBuffers(framebuffer); | 558 | impl->SwapBuffers(framebuffer); |
| 558 | } | 559 | } |
| 559 | 560 | ||
| 560 | VideoCore::RasterizerDownloadArea GPU::OnCPURead(VAddr addr, u64 size) { | 561 | VideoCore::RasterizerDownloadArea GPU::OnCPURead(PAddr addr, u64 size) { |
| 561 | return impl->OnCPURead(addr, size); | 562 | return impl->OnCPURead(addr, size); |
| 562 | } | 563 | } |
| 563 | 564 | ||
| 564 | void GPU::FlushRegion(VAddr addr, u64 size) { | 565 | void GPU::FlushRegion(DAddr addr, u64 size) { |
| 565 | impl->FlushRegion(addr, size); | 566 | impl->FlushRegion(addr, size); |
| 566 | } | 567 | } |
| 567 | 568 | ||
| 568 | void GPU::InvalidateRegion(VAddr addr, u64 size) { | 569 | void GPU::InvalidateRegion(DAddr addr, u64 size) { |
| 569 | impl->InvalidateRegion(addr, size); | 570 | impl->InvalidateRegion(addr, size); |
| 570 | } | 571 | } |
| 571 | 572 | ||
| 572 | bool GPU::OnCPUWrite(VAddr addr, u64 size) { | 573 | bool GPU::OnCPUWrite(DAddr addr, u64 size) { |
| 573 | return impl->OnCPUWrite(addr, size); | 574 | return impl->OnCPUWrite(addr, size); |
| 574 | } | 575 | } |
| 575 | 576 | ||
| 576 | void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 577 | void GPU::FlushAndInvalidateRegion(DAddr addr, u64 size) { |
| 577 | impl->FlushAndInvalidateRegion(addr, size); | 578 | impl->FlushAndInvalidateRegion(addr, size); |
| 578 | } | 579 | } |
| 579 | 580 | ||
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index ba2838b89..b3c1d15bd 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -158,7 +158,7 @@ public: | |||
| 158 | void InitAddressSpace(Tegra::MemoryManager& memory_manager); | 158 | void InitAddressSpace(Tegra::MemoryManager& memory_manager); |
| 159 | 159 | ||
| 160 | /// Request a host GPU memory flush from the CPU. | 160 | /// Request a host GPU memory flush from the CPU. |
| 161 | [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size); | 161 | [[nodiscard]] u64 RequestFlush(DAddr addr, std::size_t size); |
| 162 | 162 | ||
| 163 | /// Obtains current flush request fence id. | 163 | /// Obtains current flush request fence id. |
| 164 | [[nodiscard]] u64 CurrentSyncRequestFence() const; | 164 | [[nodiscard]] u64 CurrentSyncRequestFence() const; |
| @@ -242,20 +242,20 @@ public: | |||
| 242 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); | 242 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); |
| 243 | 243 | ||
| 244 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 244 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 245 | [[nodiscard]] VideoCore::RasterizerDownloadArea OnCPURead(VAddr addr, u64 size); | 245 | [[nodiscard]] VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size); |
| 246 | 246 | ||
| 247 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 247 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 248 | void FlushRegion(VAddr addr, u64 size); | 248 | void FlushRegion(DAddr addr, u64 size); |
| 249 | 249 | ||
| 250 | /// Notify rasterizer that any caches of the specified region should be invalidated | 250 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 251 | void InvalidateRegion(VAddr addr, u64 size); | 251 | void InvalidateRegion(DAddr addr, u64 size); |
| 252 | 252 | ||
| 253 | /// Notify rasterizer that CPU is trying to write this area. It returns true if the area is | 253 | /// Notify rasterizer that CPU is trying to write this area. It returns true if the area is |
| 254 | /// sensible, false otherwise | 254 | /// sensible, false otherwise |
| 255 | bool OnCPUWrite(VAddr addr, u64 size); | 255 | bool OnCPUWrite(DAddr addr, u64 size); |
| 256 | 256 | ||
| 257 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 257 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 258 | void FlushAndInvalidateRegion(VAddr addr, u64 size); | 258 | void FlushAndInvalidateRegion(DAddr addr, u64 size); |
| 259 | 259 | ||
| 260 | private: | 260 | private: |
| 261 | struct Impl; | 261 | struct Impl; |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 2f0f9f593..788d4f61e 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -82,7 +82,7 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 82 | PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt)); | 82 | PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt)); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void ThreadManager::FlushRegion(VAddr addr, u64 size) { | 85 | void ThreadManager::FlushRegion(DAddr addr, u64 size) { |
| 86 | if (!is_async) { | 86 | if (!is_async) { |
| 87 | // Always flush with synchronous GPU mode | 87 | // Always flush with synchronous GPU mode |
| 88 | PushCommand(FlushRegionCommand(addr, size)); | 88 | PushCommand(FlushRegionCommand(addr, size)); |
| @@ -101,11 +101,11 @@ void ThreadManager::TickGPU() { | |||
| 101 | PushCommand(GPUTickCommand()); | 101 | PushCommand(GPUTickCommand()); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { | 104 | void ThreadManager::InvalidateRegion(DAddr addr, u64 size) { |
| 105 | rasterizer->OnCacheInvalidation(addr, size); | 105 | rasterizer->OnCacheInvalidation(addr, size); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 108 | void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size) { |
| 109 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important | 109 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important |
| 110 | rasterizer->OnCacheInvalidation(addr, size); | 110 | rasterizer->OnCacheInvalidation(addr, size); |
| 111 | } | 111 | } |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 43940bd6d..2de25e9ef 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -54,26 +54,26 @@ struct SwapBuffersCommand final { | |||
| 54 | 54 | ||
| 55 | /// Command to signal to the GPU thread to flush a region | 55 | /// Command to signal to the GPU thread to flush a region |
| 56 | struct FlushRegionCommand final { | 56 | struct FlushRegionCommand final { |
| 57 | explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {} | 57 | explicit constexpr FlushRegionCommand(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {} |
| 58 | 58 | ||
| 59 | VAddr addr; | 59 | DAddr addr; |
| 60 | u64 size; | 60 | u64 size; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | /// Command to signal to the GPU thread to invalidate a region | 63 | /// Command to signal to the GPU thread to invalidate a region |
| 64 | struct InvalidateRegionCommand final { | 64 | struct InvalidateRegionCommand final { |
| 65 | explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {} | 65 | explicit constexpr InvalidateRegionCommand(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {} |
| 66 | 66 | ||
| 67 | VAddr addr; | 67 | DAddr addr; |
| 68 | u64 size; | 68 | u64 size; |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | /// Command to signal to the GPU thread to flush and invalidate a region | 71 | /// Command to signal to the GPU thread to flush and invalidate a region |
| 72 | struct FlushAndInvalidateRegionCommand final { | 72 | struct FlushAndInvalidateRegionCommand final { |
| 73 | explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_) | 73 | explicit constexpr FlushAndInvalidateRegionCommand(DAddr addr_, u64 size_) |
| 74 | : addr{addr_}, size{size_} {} | 74 | : addr{addr_}, size{size_} {} |
| 75 | 75 | ||
| 76 | VAddr addr; | 76 | DAddr addr; |
| 77 | u64 size; | 77 | u64 size; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| @@ -122,13 +122,13 @@ public: | |||
| 122 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); | 122 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); |
| 123 | 123 | ||
| 124 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 124 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 125 | void FlushRegion(VAddr addr, u64 size); | 125 | void FlushRegion(DAddr addr, u64 size); |
| 126 | 126 | ||
| 127 | /// Notify rasterizer that any caches of the specified region should be invalidated | 127 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 128 | void InvalidateRegion(VAddr addr, u64 size); | 128 | void InvalidateRegion(DAddr addr, u64 size); |
| 129 | 129 | ||
| 130 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 130 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 131 | void FlushAndInvalidateRegion(VAddr addr, u64 size); | 131 | void FlushAndInvalidateRegion(DAddr addr, u64 size); |
| 132 | 132 | ||
| 133 | void TickGPU(); | 133 | void TickGPU(); |
| 134 | 134 | ||
diff --git a/src/video_core/guest_memory.h b/src/video_core/guest_memory.h new file mode 100644 index 000000000..8b6213172 --- /dev/null +++ b/src/video_core/guest_memory.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <iterator> | ||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | #include <span> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "common/scratch_buffer.h" | ||
| 13 | #include "core/guest_memory.h" | ||
| 14 | #include "video_core/memory_manager.h" | ||
| 15 | |||
| 16 | namespace Tegra::Memory { | ||
| 17 | |||
| 18 | using GuestMemoryFlags = Core::Memory::GuestMemoryFlags; | ||
| 19 | |||
| 20 | template <typename T, GuestMemoryFlags FLAGS> | ||
| 21 | using DeviceGuestMemory = Core::Memory::GuestMemory<Tegra::MaxwellDeviceMemoryManager, T, FLAGS>; | ||
| 22 | template <typename T, GuestMemoryFlags FLAGS> | ||
| 23 | using DeviceGuestMemoryScoped = | ||
| 24 | Core::Memory::GuestMemoryScoped<Tegra::MaxwellDeviceMemoryManager, T, FLAGS>; | ||
| 25 | template <typename T, GuestMemoryFlags FLAGS> | ||
| 26 | using GpuGuestMemory = Core::Memory::GuestMemory<Tegra::MemoryManager, T, FLAGS>; | ||
| 27 | template <typename T, GuestMemoryFlags FLAGS> | ||
| 28 | using GpuGuestMemoryScoped = Core::Memory::GuestMemoryScoped<Tegra::MemoryManager, T, FLAGS>; | ||
| 29 | |||
| 30 | } // namespace Tegra::Memory | ||
diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index 309a7f1d5..994591c8d 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp | |||
| @@ -32,13 +32,12 @@ H264::~H264() = default; | |||
| 32 | std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, | 32 | std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, |
| 33 | size_t* out_configuration_size, bool is_first_frame) { | 33 | size_t* out_configuration_size, bool is_first_frame) { |
| 34 | H264DecoderContext context; | 34 | H264DecoderContext context; |
| 35 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, | 35 | host1x.GMMU().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext)); |
| 36 | sizeof(H264DecoderContext)); | ||
| 37 | 36 | ||
| 38 | const s64 frame_number = context.h264_parameter_set.frame_number.Value(); | 37 | const s64 frame_number = context.h264_parameter_set.frame_number.Value(); |
| 39 | if (!is_first_frame && frame_number != 0) { | 38 | if (!is_first_frame && frame_number != 0) { |
| 40 | frame.resize_destructive(context.stream_len); | 39 | frame.resize_destructive(context.stream_len); |
| 41 | host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); | 40 | host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); |
| 42 | *out_configuration_size = 0; | 41 | *out_configuration_size = 0; |
| 43 | return frame; | 42 | return frame; |
| 44 | } | 43 | } |
| @@ -159,8 +158,8 @@ std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters | |||
| 159 | std::memcpy(frame.data(), encoded_header.data(), encoded_header.size()); | 158 | std::memcpy(frame.data(), encoded_header.data(), encoded_header.size()); |
| 160 | 159 | ||
| 161 | *out_configuration_size = encoded_header.size(); | 160 | *out_configuration_size = encoded_header.size(); |
| 162 | host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, | 161 | host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data() + encoded_header.size(), |
| 163 | frame.data() + encoded_header.size(), context.stream_len); | 162 | context.stream_len); |
| 164 | 163 | ||
| 165 | return frame; | 164 | return frame; |
| 166 | } | 165 | } |
diff --git a/src/video_core/host1x/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp index ee6392ff9..be97e3b00 100644 --- a/src/video_core/host1x/codecs/vp8.cpp +++ b/src/video_core/host1x/codecs/vp8.cpp | |||
| @@ -14,7 +14,7 @@ VP8::~VP8() = default; | |||
| 14 | 14 | ||
| 15 | std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { | 15 | std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { |
| 16 | VP8PictureInfo info; | 16 | VP8PictureInfo info; |
| 17 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); | 17 | host1x.GMMU().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); |
| 18 | 18 | ||
| 19 | const bool is_key_frame = info.key_frame == 1u; | 19 | const bool is_key_frame = info.key_frame == 1u; |
| 20 | const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size); | 20 | const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size); |
| @@ -45,7 +45,7 @@ std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& | |||
| 45 | frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f)); | 45 | frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f)); |
| 46 | } | 46 | } |
| 47 | const u64 bitstream_offset = state.frame_bitstream_offset; | 47 | const u64 bitstream_offset = state.frame_bitstream_offset; |
| 48 | host1x.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size); | 48 | host1x.GMMU().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size); |
| 49 | 49 | ||
| 50 | return frame; | 50 | return frame; |
| 51 | } | 51 | } |
diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp index 306c3d0e8..65d6fb2d5 100644 --- a/src/video_core/host1x/codecs/vp9.cpp +++ b/src/video_core/host1x/codecs/vp9.cpp | |||
| @@ -358,7 +358,7 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_ | |||
| 358 | 358 | ||
| 359 | Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) { | 359 | Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) { |
| 360 | PictureInfo picture_info; | 360 | PictureInfo picture_info; |
| 361 | host1x.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); | 361 | host1x.GMMU().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); |
| 362 | Vp9PictureInfo vp9_info = picture_info.Convert(); | 362 | Vp9PictureInfo vp9_info = picture_info.Convert(); |
| 363 | 363 | ||
| 364 | InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); | 364 | InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); |
| @@ -373,7 +373,7 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& | |||
| 373 | 373 | ||
| 374 | void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) { | 374 | void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) { |
| 375 | EntropyProbs entropy; | 375 | EntropyProbs entropy; |
| 376 | host1x.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs)); | 376 | host1x.GMMU().ReadBlock(offset, &entropy, sizeof(EntropyProbs)); |
| 377 | entropy.Convert(dst); | 377 | entropy.Convert(dst); |
| 378 | } | 378 | } |
| 379 | 379 | ||
| @@ -383,9 +383,8 @@ Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters | |||
| 383 | // gpu.SyncGuestHost(); epic, why? | 383 | // gpu.SyncGuestHost(); epic, why? |
| 384 | current_frame.info = GetVp9PictureInfo(state); | 384 | current_frame.info = GetVp9PictureInfo(state); |
| 385 | current_frame.bit_stream.resize(current_frame.info.bitstream_size); | 385 | current_frame.bit_stream.resize(current_frame.info.bitstream_size); |
| 386 | host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, | 386 | host1x.GMMU().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(), |
| 387 | current_frame.bit_stream.data(), | 387 | current_frame.info.bitstream_size); |
| 388 | current_frame.info.bitstream_size); | ||
| 389 | } | 388 | } |
| 390 | if (!next_frame.bit_stream.empty()) { | 389 | if (!next_frame.bit_stream.empty()) { |
| 391 | Vp9FrameContainer temp{ | 390 | Vp9FrameContainer temp{ |
diff --git a/src/video_core/host1x/gpu_device_memory_manager.cpp b/src/video_core/host1x/gpu_device_memory_manager.cpp new file mode 100644 index 000000000..668c2f08b --- /dev/null +++ b/src/video_core/host1x/gpu_device_memory_manager.cpp | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/device_memory_manager.inc" | ||
| 5 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 6 | #include "video_core/rasterizer_interface.h" | ||
| 7 | |||
| 8 | namespace Tegra { | ||
| 9 | |||
| 10 | struct MaxwellDeviceMethods { | ||
| 11 | static inline void MarkRegionCaching(Core::Memory::Memory* interface, VAddr address, | ||
| 12 | size_t size, bool caching) { | ||
| 13 | interface->RasterizerMarkRegionCached(address, size, caching); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | |||
| 17 | } // namespace Tegra | ||
| 18 | |||
| 19 | template struct Core::DeviceMemoryManagerAllocator<Tegra::MaxwellDeviceTraits>; | ||
| 20 | template class Core::DeviceMemoryManager<Tegra::MaxwellDeviceTraits>; | ||
| 21 | |||
| 22 | template const u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr) const; | ||
| 23 | template u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr); | ||
| 24 | |||
| 25 | template u8 Tegra::MaxwellDeviceMemoryManager::Read<u8>(DAddr addr) const; | ||
| 26 | template u16 Tegra::MaxwellDeviceMemoryManager::Read<u16>(DAddr addr) const; | ||
| 27 | template u32 Tegra::MaxwellDeviceMemoryManager::Read<u32>(DAddr addr) const; | ||
| 28 | template u64 Tegra::MaxwellDeviceMemoryManager::Read<u64>(DAddr addr) const; | ||
| 29 | template void Tegra::MaxwellDeviceMemoryManager::Write<u8>(DAddr addr, u8 data); | ||
| 30 | template void Tegra::MaxwellDeviceMemoryManager::Write<u16>(DAddr addr, u16 data); | ||
| 31 | template void Tegra::MaxwellDeviceMemoryManager::Write<u32>(DAddr addr, u32 data); | ||
| 32 | template void Tegra::MaxwellDeviceMemoryManager::Write<u64>(DAddr addr, u64 data); \ No newline at end of file | ||
diff --git a/src/video_core/host1x/gpu_device_memory_manager.h b/src/video_core/host1x/gpu_device_memory_manager.h new file mode 100644 index 000000000..a9f249991 --- /dev/null +++ b/src/video_core/host1x/gpu_device_memory_manager.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/device_memory_manager.h" | ||
| 7 | |||
| 8 | namespace VideoCore { | ||
| 9 | class RasterizerInterface; | ||
| 10 | } | ||
| 11 | |||
| 12 | namespace Tegra { | ||
| 13 | |||
| 14 | struct MaxwellDeviceMethods; | ||
| 15 | |||
| 16 | struct MaxwellDeviceTraits { | ||
| 17 | static constexpr size_t device_virtual_bits = 34; | ||
| 18 | using DeviceInterface = typename VideoCore::RasterizerInterface; | ||
| 19 | using DeviceMethods = MaxwellDeviceMethods; | ||
| 20 | }; | ||
| 21 | |||
| 22 | using MaxwellDeviceMemoryManager = Core::DeviceMemoryManager<MaxwellDeviceTraits>; | ||
| 23 | |||
| 24 | } // namespace Tegra \ No newline at end of file | ||
diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp index 7c317a85d..c4c7a5883 100644 --- a/src/video_core/host1x/host1x.cpp +++ b/src/video_core/host1x/host1x.cpp | |||
| @@ -9,9 +9,12 @@ namespace Tegra { | |||
| 9 | namespace Host1x { | 9 | namespace Host1x { |
| 10 | 10 | ||
| 11 | Host1x::Host1x(Core::System& system_) | 11 | Host1x::Host1x(Core::System& system_) |
| 12 | : system{system_}, syncpoint_manager{}, memory_manager{system, 32, 12}, | 12 | : system{system_}, syncpoint_manager{}, |
| 13 | memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 12}, | ||
| 13 | allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {} | 14 | allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {} |
| 14 | 15 | ||
| 16 | Host1x::~Host1x() = default; | ||
| 17 | |||
| 15 | } // namespace Host1x | 18 | } // namespace Host1x |
| 16 | 19 | ||
| 17 | } // namespace Tegra | 20 | } // namespace Tegra |
diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h index 57082ae54..d72d97b7b 100644 --- a/src/video_core/host1x/host1x.h +++ b/src/video_core/host1x/host1x.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | 7 | ||
| 8 | #include "common/address_space.h" | 8 | #include "common/address_space.h" |
| 9 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 9 | #include "video_core/host1x/syncpoint_manager.h" | 10 | #include "video_core/host1x/syncpoint_manager.h" |
| 10 | #include "video_core/memory_manager.h" | 11 | #include "video_core/memory_manager.h" |
| 11 | 12 | ||
| @@ -20,6 +21,7 @@ namespace Host1x { | |||
| 20 | class Host1x { | 21 | class Host1x { |
| 21 | public: | 22 | public: |
| 22 | explicit Host1x(Core::System& system); | 23 | explicit Host1x(Core::System& system); |
| 24 | ~Host1x(); | ||
| 23 | 25 | ||
| 24 | SyncpointManager& GetSyncpointManager() { | 26 | SyncpointManager& GetSyncpointManager() { |
| 25 | return syncpoint_manager; | 27 | return syncpoint_manager; |
| @@ -29,14 +31,22 @@ public: | |||
| 29 | return syncpoint_manager; | 31 | return syncpoint_manager; |
| 30 | } | 32 | } |
| 31 | 33 | ||
| 32 | Tegra::MemoryManager& MemoryManager() { | 34 | Tegra::MaxwellDeviceMemoryManager& MemoryManager() { |
| 33 | return memory_manager; | 35 | return memory_manager; |
| 34 | } | 36 | } |
| 35 | 37 | ||
| 36 | const Tegra::MemoryManager& MemoryManager() const { | 38 | const Tegra::MaxwellDeviceMemoryManager& MemoryManager() const { |
| 37 | return memory_manager; | 39 | return memory_manager; |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 42 | Tegra::MemoryManager& GMMU() { | ||
| 43 | return gmmu_manager; | ||
| 44 | } | ||
| 45 | |||
| 46 | const Tegra::MemoryManager& GMMU() const { | ||
| 47 | return gmmu_manager; | ||
| 48 | } | ||
| 49 | |||
| 40 | Common::FlatAllocator<u32, 0, 32>& Allocator() { | 50 | Common::FlatAllocator<u32, 0, 32>& Allocator() { |
| 41 | return *allocator; | 51 | return *allocator; |
| 42 | } | 52 | } |
| @@ -48,7 +58,8 @@ public: | |||
| 48 | private: | 58 | private: |
| 49 | Core::System& system; | 59 | Core::System& system; |
| 50 | SyncpointManager syncpoint_manager; | 60 | SyncpointManager syncpoint_manager; |
| 51 | Tegra::MemoryManager memory_manager; | 61 | Tegra::MaxwellDeviceMemoryManager memory_manager; |
| 62 | Tegra::MemoryManager gmmu_manager; | ||
| 52 | std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator; | 63 | std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator; |
| 53 | }; | 64 | }; |
| 54 | 65 | ||
diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp index 2a5eba415..d154746af 100644 --- a/src/video_core/host1x/vic.cpp +++ b/src/video_core/host1x/vic.cpp | |||
| @@ -81,7 +81,7 @@ void Vic::Execute() { | |||
| 81 | LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); | 81 | LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); |
| 82 | return; | 82 | return; |
| 83 | } | 83 | } |
| 84 | const VicConfig config{host1x.MemoryManager().Read<u64>(config_struct_address + 0x20)}; | 84 | const VicConfig config{host1x.GMMU().Read<u64>(config_struct_address + 0x20)}; |
| 85 | auto frame = nvdec_processor->GetFrame(); | 85 | auto frame = nvdec_processor->GetFrame(); |
| 86 | if (!frame) { | 86 | if (!frame) { |
| 87 | return; | 87 | return; |
| @@ -162,12 +162,12 @@ void Vic::WriteRGBFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c | |||
| 162 | Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height, | 162 | Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height, |
| 163 | block_height, 0, width * 4); | 163 | block_height, 0, width * 4); |
| 164 | 164 | ||
| 165 | host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); | 165 | host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); |
| 166 | } else { | 166 | } else { |
| 167 | // send pitch linear frame | 167 | // send pitch linear frame |
| 168 | const size_t linear_size = width * height * 4; | 168 | const size_t linear_size = width * height * 4; |
| 169 | host1x.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, | 169 | host1x.GMMU().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, |
| 170 | linear_size); | 170 | linear_size); |
| 171 | } | 171 | } |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -193,8 +193,7 @@ void Vic::WriteYUVFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c | |||
| 193 | const std::size_t dst = y * aligned_width; | 193 | const std::size_t dst = y * aligned_width; |
| 194 | std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width); | 194 | std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width); |
| 195 | } | 195 | } |
| 196 | host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), | 196 | host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), luma_buffer.size()); |
| 197 | luma_buffer.size()); | ||
| 198 | 197 | ||
| 199 | // Chroma | 198 | // Chroma |
| 200 | const std::size_t half_height = frame_height / 2; | 199 | const std::size_t half_height = frame_height / 2; |
| @@ -233,8 +232,8 @@ void Vic::WriteYUVFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c | |||
| 233 | ASSERT(false); | 232 | ASSERT(false); |
| 234 | break; | 233 | break; |
| 235 | } | 234 | } |
| 236 | host1x.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), | 235 | host1x.GMMU().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), |
| 237 | chroma_buffer.size()); | 236 | chroma_buffer.size()); |
| 238 | } | 237 | } |
| 239 | 238 | ||
| 240 | } // namespace Host1x | 239 | } // namespace Host1x |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index d16040613..a52f8e486 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -7,25 +7,26 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/device_memory.h" | ||
| 11 | #include "core/hle/kernel/k_page_table.h" | 10 | #include "core/hle/kernel/k_page_table.h" |
| 12 | #include "core/hle/kernel/k_process.h" | 11 | #include "core/hle/kernel/k_process.h" |
| 12 | #include "video_core/guest_memory.h" | ||
| 13 | #include "video_core/host1x/host1x.h" | ||
| 13 | #include "video_core/invalidation_accumulator.h" | 14 | #include "video_core/invalidation_accumulator.h" |
| 14 | #include "video_core/memory_manager.h" | 15 | #include "video_core/memory_manager.h" |
| 15 | #include "video_core/rasterizer_interface.h" | 16 | #include "video_core/rasterizer_interface.h" |
| 16 | #include "video_core/renderer_base.h" | 17 | #include "video_core/renderer_base.h" |
| 17 | 18 | ||
| 18 | namespace Tegra { | 19 | namespace Tegra { |
| 19 | using Core::Memory::GuestMemoryFlags; | 20 | using Tegra::Memory::GuestMemoryFlags; |
| 20 | 21 | ||
| 21 | std::atomic<size_t> MemoryManager::unique_identifier_generator{}; | 22 | std::atomic<size_t> MemoryManager::unique_identifier_generator{}; |
| 22 | 23 | ||
| 23 | MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_, | 24 | MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_, |
| 24 | u64 page_bits_) | 25 | u64 address_space_bits_, u64 big_page_bits_, u64 page_bits_) |
| 25 | : system{system_}, memory{system.ApplicationMemory()}, device_memory{system.DeviceMemory()}, | 26 | : system{system_}, memory{memory_}, address_space_bits{address_space_bits_}, |
| 26 | address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_}, | 27 | page_bits{page_bits_}, big_page_bits{big_page_bits_}, entries{}, big_entries{}, |
| 27 | entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38, | 28 | page_table{address_space_bits, address_space_bits + page_bits - 38, |
| 28 | page_bits != big_page_bits ? page_bits : 0}, | 29 | page_bits != big_page_bits ? page_bits : 0}, |
| 29 | kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add( | 30 | kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add( |
| 30 | 1, std::memory_order_acq_rel)}, | 31 | 1, std::memory_order_acq_rel)}, |
| 31 | accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} { | 32 | accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} { |
| @@ -42,11 +43,16 @@ MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 | |||
| 42 | big_page_table_mask = big_page_table_size - 1; | 43 | big_page_table_mask = big_page_table_size - 1; |
| 43 | 44 | ||
| 44 | big_entries.resize(big_page_table_size / 32, 0); | 45 | big_entries.resize(big_page_table_size / 32, 0); |
| 45 | big_page_table_cpu.resize(big_page_table_size); | 46 | big_page_table_dev.resize(big_page_table_size); |
| 46 | big_page_continuous.resize(big_page_table_size / continuous_bits, 0); | 47 | big_page_continuous.resize(big_page_table_size / continuous_bits, 0); |
| 47 | entries.resize(page_table_size / 32, 0); | 48 | entries.resize(page_table_size / 32, 0); |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 51 | MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_, | ||
| 52 | u64 page_bits_) | ||
| 53 | : MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, big_page_bits_, | ||
| 54 | page_bits_) {} | ||
| 55 | |||
| 50 | MemoryManager::~MemoryManager() = default; | 56 | MemoryManager::~MemoryManager() = default; |
| 51 | 57 | ||
| 52 | template <bool is_big_page> | 58 | template <bool is_big_page> |
| @@ -100,7 +106,7 @@ inline void MemoryManager::SetBigPageContinuous(size_t big_page_index, bool valu | |||
| 100 | } | 106 | } |
| 101 | 107 | ||
| 102 | template <MemoryManager::EntryType entry_type> | 108 | template <MemoryManager::EntryType entry_type> |
| 103 | GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, | 109 | GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size, |
| 104 | PTEKind kind) { | 110 | PTEKind kind) { |
| 105 | [[maybe_unused]] u64 remaining_size{size}; | 111 | [[maybe_unused]] u64 remaining_size{size}; |
| 106 | if constexpr (entry_type == EntryType::Mapped) { | 112 | if constexpr (entry_type == EntryType::Mapped) { |
| @@ -114,9 +120,9 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cp | |||
| 114 | rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, page_size); | 120 | rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, page_size); |
| 115 | } | 121 | } |
| 116 | if constexpr (entry_type == EntryType::Mapped) { | 122 | if constexpr (entry_type == EntryType::Mapped) { |
| 117 | const VAddr current_cpu_addr = cpu_addr + offset; | 123 | const DAddr current_dev_addr = dev_addr + offset; |
| 118 | const auto index = PageEntryIndex<false>(current_gpu_addr); | 124 | const auto index = PageEntryIndex<false>(current_gpu_addr); |
| 119 | const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits); | 125 | const u32 sub_value = static_cast<u32>(current_dev_addr >> cpu_page_bits); |
| 120 | page_table[index] = sub_value; | 126 | page_table[index] = sub_value; |
| 121 | } | 127 | } |
| 122 | remaining_size -= page_size; | 128 | remaining_size -= page_size; |
| @@ -126,7 +132,7 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cp | |||
| 126 | } | 132 | } |
| 127 | 133 | ||
| 128 | template <MemoryManager::EntryType entry_type> | 134 | template <MemoryManager::EntryType entry_type> |
| 129 | GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, | 135 | GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, |
| 130 | size_t size, PTEKind kind) { | 136 | size_t size, PTEKind kind) { |
| 131 | [[maybe_unused]] u64 remaining_size{size}; | 137 | [[maybe_unused]] u64 remaining_size{size}; |
| 132 | for (u64 offset{}; offset < size; offset += big_page_size) { | 138 | for (u64 offset{}; offset < size; offset += big_page_size) { |
| @@ -137,20 +143,20 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr | |||
| 137 | rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, big_page_size); | 143 | rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, big_page_size); |
| 138 | } | 144 | } |
| 139 | if constexpr (entry_type == EntryType::Mapped) { | 145 | if constexpr (entry_type == EntryType::Mapped) { |
| 140 | const VAddr current_cpu_addr = cpu_addr + offset; | 146 | const DAddr current_dev_addr = dev_addr + offset; |
| 141 | const auto index = PageEntryIndex<true>(current_gpu_addr); | 147 | const auto index = PageEntryIndex<true>(current_gpu_addr); |
| 142 | const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits); | 148 | const u32 sub_value = static_cast<u32>(current_dev_addr >> cpu_page_bits); |
| 143 | big_page_table_cpu[index] = sub_value; | 149 | big_page_table_dev[index] = sub_value; |
| 144 | const bool is_continuous = ([&] { | 150 | const bool is_continuous = ([&] { |
| 145 | uintptr_t base_ptr{ | 151 | uintptr_t base_ptr{ |
| 146 | reinterpret_cast<uintptr_t>(memory.GetPointerSilent(current_cpu_addr))}; | 152 | reinterpret_cast<uintptr_t>(memory.GetPointer<u8>(current_dev_addr))}; |
| 147 | if (base_ptr == 0) { | 153 | if (base_ptr == 0) { |
| 148 | return false; | 154 | return false; |
| 149 | } | 155 | } |
| 150 | for (VAddr start_cpu = current_cpu_addr + page_size; | 156 | for (DAddr start_cpu = current_dev_addr + page_size; |
| 151 | start_cpu < current_cpu_addr + big_page_size; start_cpu += page_size) { | 157 | start_cpu < current_dev_addr + big_page_size; start_cpu += page_size) { |
| 152 | base_ptr += page_size; | 158 | base_ptr += page_size; |
| 153 | auto next_ptr = reinterpret_cast<uintptr_t>(memory.GetPointerSilent(start_cpu)); | 159 | auto next_ptr = reinterpret_cast<uintptr_t>(memory.GetPointer<u8>(start_cpu)); |
| 154 | if (next_ptr == 0 || base_ptr != next_ptr) { | 160 | if (next_ptr == 0 || base_ptr != next_ptr) { |
| 155 | return false; | 161 | return false; |
| 156 | } | 162 | } |
| @@ -172,12 +178,12 @@ void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) | |||
| 172 | rasterizer = rasterizer_; | 178 | rasterizer = rasterizer_; |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | GPUVAddr MemoryManager::Map(GPUVAddr gpu_addr, VAddr cpu_addr, std::size_t size, PTEKind kind, | 181 | GPUVAddr MemoryManager::Map(GPUVAddr gpu_addr, DAddr dev_addr, std::size_t size, PTEKind kind, |
| 176 | bool is_big_pages) { | 182 | bool is_big_pages) { |
| 177 | if (is_big_pages) [[likely]] { | 183 | if (is_big_pages) [[likely]] { |
| 178 | return BigPageTableOp<EntryType::Mapped>(gpu_addr, cpu_addr, size, kind); | 184 | return BigPageTableOp<EntryType::Mapped>(gpu_addr, dev_addr, size, kind); |
| 179 | } | 185 | } |
| 180 | return PageTableOp<EntryType::Mapped>(gpu_addr, cpu_addr, size, kind); | 186 | return PageTableOp<EntryType::Mapped>(gpu_addr, dev_addr, size, kind); |
| 181 | } | 187 | } |
| 182 | 188 | ||
| 183 | GPUVAddr MemoryManager::MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages) { | 189 | GPUVAddr MemoryManager::MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages) { |
| @@ -202,7 +208,7 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) { | |||
| 202 | PageTableOp<EntryType::Free>(gpu_addr, 0, size, PTEKind::INVALID); | 208 | PageTableOp<EntryType::Free>(gpu_addr, 0, size, PTEKind::INVALID); |
| 203 | } | 209 | } |
| 204 | 210 | ||
| 205 | std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const { | 211 | std::optional<DAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const { |
| 206 | if (!IsWithinGPUAddressRange(gpu_addr)) [[unlikely]] { | 212 | if (!IsWithinGPUAddressRange(gpu_addr)) [[unlikely]] { |
| 207 | return std::nullopt; | 213 | return std::nullopt; |
| 208 | } | 214 | } |
| @@ -211,17 +217,17 @@ std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const { | |||
| 211 | return std::nullopt; | 217 | return std::nullopt; |
| 212 | } | 218 | } |
| 213 | 219 | ||
| 214 | const VAddr cpu_addr_base = static_cast<VAddr>(page_table[PageEntryIndex<false>(gpu_addr)]) | 220 | const DAddr dev_addr_base = static_cast<DAddr>(page_table[PageEntryIndex<false>(gpu_addr)]) |
| 215 | << cpu_page_bits; | 221 | << cpu_page_bits; |
| 216 | return cpu_addr_base + (gpu_addr & page_mask); | 222 | return dev_addr_base + (gpu_addr & page_mask); |
| 217 | } | 223 | } |
| 218 | 224 | ||
| 219 | const VAddr cpu_addr_base = | 225 | const DAddr dev_addr_base = |
| 220 | static_cast<VAddr>(big_page_table_cpu[PageEntryIndex<true>(gpu_addr)]) << cpu_page_bits; | 226 | static_cast<DAddr>(big_page_table_dev[PageEntryIndex<true>(gpu_addr)]) << cpu_page_bits; |
| 221 | return cpu_addr_base + (gpu_addr & big_page_mask); | 227 | return dev_addr_base + (gpu_addr & big_page_mask); |
| 222 | } | 228 | } |
| 223 | 229 | ||
| 224 | std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr, std::size_t size) const { | 230 | std::optional<DAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr, std::size_t size) const { |
| 225 | size_t page_index{addr >> page_bits}; | 231 | size_t page_index{addr >> page_bits}; |
| 226 | const size_t page_last{(addr + size + page_size - 1) >> page_bits}; | 232 | const size_t page_last{(addr + size + page_size - 1) >> page_bits}; |
| 227 | while (page_index < page_last) { | 233 | while (page_index < page_last) { |
| @@ -274,7 +280,7 @@ u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) { | |||
| 274 | return {}; | 280 | return {}; |
| 275 | } | 281 | } |
| 276 | 282 | ||
| 277 | return memory.GetPointer(*address); | 283 | return memory.GetPointer<u8>(*address); |
| 278 | } | 284 | } |
| 279 | 285 | ||
| 280 | const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { | 286 | const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { |
| @@ -283,7 +289,7 @@ const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { | |||
| 283 | return {}; | 289 | return {}; |
| 284 | } | 290 | } |
| 285 | 291 | ||
| 286 | return memory.GetPointer(*address); | 292 | return memory.GetPointer<u8>(*address); |
| 287 | } | 293 | } |
| 288 | 294 | ||
| 289 | #ifdef _MSC_VER // no need for gcc / clang but msvc's compiler is more conservative with inlining. | 295 | #ifdef _MSC_VER // no need for gcc / clang but msvc's compiler is more conservative with inlining. |
| @@ -367,25 +373,25 @@ void MemoryManager::ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std: | |||
| 367 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; | 373 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; |
| 368 | }; | 374 | }; |
| 369 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 375 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 370 | const VAddr cpu_addr_base = | 376 | const DAddr dev_addr_base = |
| 371 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 377 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 372 | if constexpr (is_safe) { | 378 | if constexpr (is_safe) { |
| 373 | rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); | 379 | rasterizer->FlushRegion(dev_addr_base, copy_amount, which); |
| 374 | } | 380 | } |
| 375 | u8* physical = memory.GetPointer(cpu_addr_base); | 381 | u8* physical = memory.GetPointer<u8>(dev_addr_base); |
| 376 | std::memcpy(dest_buffer, physical, copy_amount); | 382 | std::memcpy(dest_buffer, physical, copy_amount); |
| 377 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; | 383 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; |
| 378 | }; | 384 | }; |
| 379 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 385 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 380 | const VAddr cpu_addr_base = | 386 | const DAddr dev_addr_base = |
| 381 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 387 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 382 | if constexpr (is_safe) { | 388 | if constexpr (is_safe) { |
| 383 | rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); | 389 | rasterizer->FlushRegion(dev_addr_base, copy_amount, which); |
| 384 | } | 390 | } |
| 385 | if (!IsBigPageContinuous(page_index)) [[unlikely]] { | 391 | if (!IsBigPageContinuous(page_index)) [[unlikely]] { |
| 386 | memory.ReadBlockUnsafe(cpu_addr_base, dest_buffer, copy_amount); | 392 | memory.ReadBlockUnsafe(dev_addr_base, dest_buffer, copy_amount); |
| 387 | } else { | 393 | } else { |
| 388 | u8* physical = memory.GetPointer(cpu_addr_base); | 394 | u8* physical = memory.GetPointer<u8>(dev_addr_base); |
| 389 | std::memcpy(dest_buffer, physical, copy_amount); | 395 | std::memcpy(dest_buffer, physical, copy_amount); |
| 390 | } | 396 | } |
| 391 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; | 397 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; |
| @@ -416,25 +422,25 @@ void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffe | |||
| 416 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | 422 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; |
| 417 | }; | 423 | }; |
| 418 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 424 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 419 | const VAddr cpu_addr_base = | 425 | const DAddr dev_addr_base = |
| 420 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 426 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 421 | if constexpr (is_safe) { | 427 | if constexpr (is_safe) { |
| 422 | rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); | 428 | rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which); |
| 423 | } | 429 | } |
| 424 | u8* physical = memory.GetPointer(cpu_addr_base); | 430 | u8* physical = memory.GetPointer<u8>(dev_addr_base); |
| 425 | std::memcpy(physical, src_buffer, copy_amount); | 431 | std::memcpy(physical, src_buffer, copy_amount); |
| 426 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | 432 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; |
| 427 | }; | 433 | }; |
| 428 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 434 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 429 | const VAddr cpu_addr_base = | 435 | const DAddr dev_addr_base = |
| 430 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 436 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 431 | if constexpr (is_safe) { | 437 | if constexpr (is_safe) { |
| 432 | rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); | 438 | rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which); |
| 433 | } | 439 | } |
| 434 | if (!IsBigPageContinuous(page_index)) [[unlikely]] { | 440 | if (!IsBigPageContinuous(page_index)) [[unlikely]] { |
| 435 | memory.WriteBlockUnsafe(cpu_addr_base, src_buffer, copy_amount); | 441 | memory.WriteBlockUnsafe(dev_addr_base, src_buffer, copy_amount); |
| 436 | } else { | 442 | } else { |
| 437 | u8* physical = memory.GetPointer(cpu_addr_base); | 443 | u8* physical = memory.GetPointer<u8>(dev_addr_base); |
| 438 | std::memcpy(physical, src_buffer, copy_amount); | 444 | std::memcpy(physical, src_buffer, copy_amount); |
| 439 | } | 445 | } |
| 440 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | 446 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; |
| @@ -470,14 +476,14 @@ void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size, | |||
| 470 | [[maybe_unused]] std::size_t copy_amount) {}; | 476 | [[maybe_unused]] std::size_t copy_amount) {}; |
| 471 | 477 | ||
| 472 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 478 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 473 | const VAddr cpu_addr_base = | 479 | const DAddr dev_addr_base = |
| 474 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 480 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 475 | rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); | 481 | rasterizer->FlushRegion(dev_addr_base, copy_amount, which); |
| 476 | }; | 482 | }; |
| 477 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 483 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 478 | const VAddr cpu_addr_base = | 484 | const DAddr dev_addr_base = |
| 479 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 485 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 480 | rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); | 486 | rasterizer->FlushRegion(dev_addr_base, copy_amount, which); |
| 481 | }; | 487 | }; |
| 482 | auto flush_short_pages = [&](std::size_t page_index, std::size_t offset, | 488 | auto flush_short_pages = [&](std::size_t page_index, std::size_t offset, |
| 483 | std::size_t copy_amount) { | 489 | std::size_t copy_amount) { |
| @@ -495,15 +501,15 @@ bool MemoryManager::IsMemoryDirty(GPUVAddr gpu_addr, size_t size, | |||
| 495 | [[maybe_unused]] std::size_t copy_amount) { return false; }; | 501 | [[maybe_unused]] std::size_t copy_amount) { return false; }; |
| 496 | 502 | ||
| 497 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 503 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 498 | const VAddr cpu_addr_base = | 504 | const DAddr dev_addr_base = |
| 499 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 505 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 500 | result |= rasterizer->MustFlushRegion(cpu_addr_base, copy_amount, which); | 506 | result |= rasterizer->MustFlushRegion(dev_addr_base, copy_amount, which); |
| 501 | return result; | 507 | return result; |
| 502 | }; | 508 | }; |
| 503 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 509 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 504 | const VAddr cpu_addr_base = | 510 | const DAddr dev_addr_base = |
| 505 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 511 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 506 | result |= rasterizer->MustFlushRegion(cpu_addr_base, copy_amount, which); | 512 | result |= rasterizer->MustFlushRegion(dev_addr_base, copy_amount, which); |
| 507 | return result; | 513 | return result; |
| 508 | }; | 514 | }; |
| 509 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, | 515 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, |
| @@ -517,7 +523,7 @@ bool MemoryManager::IsMemoryDirty(GPUVAddr gpu_addr, size_t size, | |||
| 517 | } | 523 | } |
| 518 | 524 | ||
| 519 | size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const { | 525 | size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const { |
| 520 | std::optional<VAddr> old_page_addr{}; | 526 | std::optional<DAddr> old_page_addr{}; |
| 521 | size_t range_so_far = 0; | 527 | size_t range_so_far = 0; |
| 522 | bool result{false}; | 528 | bool result{false}; |
| 523 | auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, | 529 | auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, |
| @@ -526,24 +532,24 @@ size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const { | |||
| 526 | return true; | 532 | return true; |
| 527 | }; | 533 | }; |
| 528 | auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 534 | auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 529 | const VAddr cpu_addr_base = | 535 | const DAddr dev_addr_base = |
| 530 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 536 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 531 | if (old_page_addr && *old_page_addr != cpu_addr_base) { | 537 | if (old_page_addr && *old_page_addr != dev_addr_base) { |
| 532 | result = true; | 538 | result = true; |
| 533 | return true; | 539 | return true; |
| 534 | } | 540 | } |
| 535 | range_so_far += copy_amount; | 541 | range_so_far += copy_amount; |
| 536 | old_page_addr = {cpu_addr_base + copy_amount}; | 542 | old_page_addr = {dev_addr_base + copy_amount}; |
| 537 | return false; | 543 | return false; |
| 538 | }; | 544 | }; |
| 539 | auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 545 | auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 540 | const VAddr cpu_addr_base = | 546 | const DAddr dev_addr_base = |
| 541 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 547 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 542 | if (old_page_addr && *old_page_addr != cpu_addr_base) { | 548 | if (old_page_addr && *old_page_addr != dev_addr_base) { |
| 543 | return true; | 549 | return true; |
| 544 | } | 550 | } |
| 545 | range_so_far += copy_amount; | 551 | range_so_far += copy_amount; |
| 546 | old_page_addr = {cpu_addr_base + copy_amount}; | 552 | old_page_addr = {dev_addr_base + copy_amount}; |
| 547 | return false; | 553 | return false; |
| 548 | }; | 554 | }; |
| 549 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, | 555 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, |
| @@ -568,14 +574,14 @@ void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size, | |||
| 568 | [[maybe_unused]] std::size_t copy_amount) {}; | 574 | [[maybe_unused]] std::size_t copy_amount) {}; |
| 569 | 575 | ||
| 570 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 576 | auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 571 | const VAddr cpu_addr_base = | 577 | const DAddr dev_addr_base = |
| 572 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 578 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 573 | rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); | 579 | rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which); |
| 574 | }; | 580 | }; |
| 575 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 581 | auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 576 | const VAddr cpu_addr_base = | 582 | const DAddr dev_addr_base = |
| 577 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 583 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 578 | rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); | 584 | rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which); |
| 579 | }; | 585 | }; |
| 580 | auto invalidate_short_pages = [&](std::size_t page_index, std::size_t offset, | 586 | auto invalidate_short_pages = [&](std::size_t page_index, std::size_t offset, |
| 581 | std::size_t copy_amount) { | 587 | std::size_t copy_amount) { |
| @@ -587,7 +593,7 @@ void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size, | |||
| 587 | 593 | ||
| 588 | void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size, | 594 | void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size, |
| 589 | VideoCommon::CacheType which) { | 595 | VideoCommon::CacheType which) { |
| 590 | Core::Memory::GpuGuestMemoryScoped<u8, GuestMemoryFlags::SafeReadWrite> data( | 596 | Tegra::Memory::GpuGuestMemoryScoped<u8, GuestMemoryFlags::SafeReadWrite> data( |
| 591 | *this, gpu_src_addr, size); | 597 | *this, gpu_src_addr, size); |
| 592 | data.SetAddressAndSize(gpu_dest_addr, size); | 598 | data.SetAddressAndSize(gpu_dest_addr, size); |
| 593 | FlushRegion(gpu_dest_addr, size, which); | 599 | FlushRegion(gpu_dest_addr, size, which); |
| @@ -600,18 +606,18 @@ bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const { | |||
| 600 | const std::size_t page{(page_index & big_page_mask) + size}; | 606 | const std::size_t page{(page_index & big_page_mask) + size}; |
| 601 | return page <= big_page_size; | 607 | return page <= big_page_size; |
| 602 | } | 608 | } |
| 603 | const std::size_t page{(gpu_addr & Core::Memory::YUZU_PAGEMASK) + size}; | 609 | const std::size_t page{(gpu_addr & Core::DEVICE_PAGEMASK) + size}; |
| 604 | return page <= Core::Memory::YUZU_PAGESIZE; | 610 | return page <= Core::DEVICE_PAGESIZE; |
| 605 | } | 611 | } |
| 606 | if (GetEntry<false>(gpu_addr) != EntryType::Mapped) { | 612 | if (GetEntry<false>(gpu_addr) != EntryType::Mapped) { |
| 607 | return false; | 613 | return false; |
| 608 | } | 614 | } |
| 609 | const std::size_t page{(gpu_addr & Core::Memory::YUZU_PAGEMASK) + size}; | 615 | const std::size_t page{(gpu_addr & Core::DEVICE_PAGEMASK) + size}; |
| 610 | return page <= Core::Memory::YUZU_PAGESIZE; | 616 | return page <= Core::DEVICE_PAGESIZE; |
| 611 | } | 617 | } |
| 612 | 618 | ||
| 613 | bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const { | 619 | bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const { |
| 614 | std::optional<VAddr> old_page_addr{}; | 620 | std::optional<DAddr> old_page_addr{}; |
| 615 | bool result{true}; | 621 | bool result{true}; |
| 616 | auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, | 622 | auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, |
| 617 | std::size_t copy_amount) { | 623 | std::size_t copy_amount) { |
| @@ -619,23 +625,23 @@ bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const | |||
| 619 | return true; | 625 | return true; |
| 620 | }; | 626 | }; |
| 621 | auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 627 | auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 622 | const VAddr cpu_addr_base = | 628 | const DAddr dev_addr_base = |
| 623 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 629 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 624 | if (old_page_addr && *old_page_addr != cpu_addr_base) { | 630 | if (old_page_addr && *old_page_addr != dev_addr_base) { |
| 625 | result = false; | 631 | result = false; |
| 626 | return true; | 632 | return true; |
| 627 | } | 633 | } |
| 628 | old_page_addr = {cpu_addr_base + copy_amount}; | 634 | old_page_addr = {dev_addr_base + copy_amount}; |
| 629 | return false; | 635 | return false; |
| 630 | }; | 636 | }; |
| 631 | auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { | 637 | auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { |
| 632 | const VAddr cpu_addr_base = | 638 | const DAddr dev_addr_base = |
| 633 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 639 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 634 | if (old_page_addr && *old_page_addr != cpu_addr_base) { | 640 | if (old_page_addr && *old_page_addr != dev_addr_base) { |
| 635 | result = false; | 641 | result = false; |
| 636 | return true; | 642 | return true; |
| 637 | } | 643 | } |
| 638 | old_page_addr = {cpu_addr_base + copy_amount}; | 644 | old_page_addr = {dev_addr_base + copy_amount}; |
| 639 | return false; | 645 | return false; |
| 640 | }; | 646 | }; |
| 641 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, | 647 | auto check_short_pages = [&](std::size_t page_index, std::size_t offset, |
| @@ -678,11 +684,11 @@ template <bool is_gpu_address> | |||
| 678 | void MemoryManager::GetSubmappedRangeImpl( | 684 | void MemoryManager::GetSubmappedRangeImpl( |
| 679 | GPUVAddr gpu_addr, std::size_t size, | 685 | GPUVAddr gpu_addr, std::size_t size, |
| 680 | boost::container::small_vector< | 686 | boost::container::small_vector< |
| 681 | std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>, 32>& result) | 687 | std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>, 32>& result) |
| 682 | const { | 688 | const { |
| 683 | std::optional<std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>> | 689 | std::optional<std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>> |
| 684 | last_segment{}; | 690 | last_segment{}; |
| 685 | std::optional<VAddr> old_page_addr{}; | 691 | std::optional<DAddr> old_page_addr{}; |
| 686 | const auto split = [&last_segment, &result]([[maybe_unused]] std::size_t page_index, | 692 | const auto split = [&last_segment, &result]([[maybe_unused]] std::size_t page_index, |
| 687 | [[maybe_unused]] std::size_t offset, | 693 | [[maybe_unused]] std::size_t offset, |
| 688 | [[maybe_unused]] std::size_t copy_amount) { | 694 | [[maybe_unused]] std::size_t copy_amount) { |
| @@ -694,20 +700,20 @@ void MemoryManager::GetSubmappedRangeImpl( | |||
| 694 | const auto extend_size_big = [this, &split, &old_page_addr, | 700 | const auto extend_size_big = [this, &split, &old_page_addr, |
| 695 | &last_segment](std::size_t page_index, std::size_t offset, | 701 | &last_segment](std::size_t page_index, std::size_t offset, |
| 696 | std::size_t copy_amount) { | 702 | std::size_t copy_amount) { |
| 697 | const VAddr cpu_addr_base = | 703 | const DAddr dev_addr_base = |
| 698 | (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; | 704 | (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset; |
| 699 | if (old_page_addr) { | 705 | if (old_page_addr) { |
| 700 | if (*old_page_addr != cpu_addr_base) { | 706 | if (*old_page_addr != dev_addr_base) { |
| 701 | split(0, 0, 0); | 707 | split(0, 0, 0); |
| 702 | } | 708 | } |
| 703 | } | 709 | } |
| 704 | old_page_addr = {cpu_addr_base + copy_amount}; | 710 | old_page_addr = {dev_addr_base + copy_amount}; |
| 705 | if (!last_segment) { | 711 | if (!last_segment) { |
| 706 | if constexpr (is_gpu_address) { | 712 | if constexpr (is_gpu_address) { |
| 707 | const GPUVAddr new_base_addr = (page_index << big_page_bits) + offset; | 713 | const GPUVAddr new_base_addr = (page_index << big_page_bits) + offset; |
| 708 | last_segment = {new_base_addr, copy_amount}; | 714 | last_segment = {new_base_addr, copy_amount}; |
| 709 | } else { | 715 | } else { |
| 710 | last_segment = {cpu_addr_base, copy_amount}; | 716 | last_segment = {dev_addr_base, copy_amount}; |
| 711 | } | 717 | } |
| 712 | } else { | 718 | } else { |
| 713 | last_segment->second += copy_amount; | 719 | last_segment->second += copy_amount; |
| @@ -716,20 +722,20 @@ void MemoryManager::GetSubmappedRangeImpl( | |||
| 716 | const auto extend_size_short = [this, &split, &old_page_addr, | 722 | const auto extend_size_short = [this, &split, &old_page_addr, |
| 717 | &last_segment](std::size_t page_index, std::size_t offset, | 723 | &last_segment](std::size_t page_index, std::size_t offset, |
| 718 | std::size_t copy_amount) { | 724 | std::size_t copy_amount) { |
| 719 | const VAddr cpu_addr_base = | 725 | const DAddr dev_addr_base = |
| 720 | (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; | 726 | (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset; |
| 721 | if (old_page_addr) { | 727 | if (old_page_addr) { |
| 722 | if (*old_page_addr != cpu_addr_base) { | 728 | if (*old_page_addr != dev_addr_base) { |
| 723 | split(0, 0, 0); | 729 | split(0, 0, 0); |
| 724 | } | 730 | } |
| 725 | } | 731 | } |
| 726 | old_page_addr = {cpu_addr_base + copy_amount}; | 732 | old_page_addr = {dev_addr_base + copy_amount}; |
| 727 | if (!last_segment) { | 733 | if (!last_segment) { |
| 728 | if constexpr (is_gpu_address) { | 734 | if constexpr (is_gpu_address) { |
| 729 | const GPUVAddr new_base_addr = (page_index << page_bits) + offset; | 735 | const GPUVAddr new_base_addr = (page_index << page_bits) + offset; |
| 730 | last_segment = {new_base_addr, copy_amount}; | 736 | last_segment = {new_base_addr, copy_amount}; |
| 731 | } else { | 737 | } else { |
| 732 | last_segment = {cpu_addr_base, copy_amount}; | 738 | last_segment = {dev_addr_base, copy_amount}; |
| 733 | } | 739 | } |
| 734 | } else { | 740 | } else { |
| 735 | last_segment->second += copy_amount; | 741 | last_segment->second += copy_amount; |
| @@ -756,9 +762,12 @@ void MemoryManager::FlushCaching() { | |||
| 756 | } | 762 | } |
| 757 | 763 | ||
| 758 | const u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) const { | 764 | const u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) const { |
| 759 | auto cpu_addr = GpuToCpuAddress(src_addr); | 765 | if (!IsContinuousRange(src_addr, size)) { |
| 760 | if (cpu_addr) { | 766 | return nullptr; |
| 761 | return memory.GetSpan(*cpu_addr, size); | 767 | } |
| 768 | auto dev_addr = GpuToCpuAddress(src_addr); | ||
| 769 | if (dev_addr) { | ||
| 770 | return memory.GetSpan(*dev_addr, size); | ||
| 762 | } | 771 | } |
| 763 | return nullptr; | 772 | return nullptr; |
| 764 | } | 773 | } |
| @@ -767,9 +776,9 @@ u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) { | |||
| 767 | if (!IsContinuousRange(src_addr, size)) { | 776 | if (!IsContinuousRange(src_addr, size)) { |
| 768 | return nullptr; | 777 | return nullptr; |
| 769 | } | 778 | } |
| 770 | auto cpu_addr = GpuToCpuAddress(src_addr); | 779 | auto dev_addr = GpuToCpuAddress(src_addr); |
| 771 | if (cpu_addr) { | 780 | if (dev_addr) { |
| 772 | return memory.GetSpan(*cpu_addr, size); | 781 | return memory.GetSpan(*dev_addr, size); |
| 773 | } | 782 | } |
| 774 | return nullptr; | 783 | return nullptr; |
| 775 | } | 784 | } |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 9b311b9e5..c5255f36c 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include "common/range_map.h" | 15 | #include "common/range_map.h" |
| 16 | #include "common/scratch_buffer.h" | 16 | #include "common/scratch_buffer.h" |
| 17 | #include "common/virtual_buffer.h" | 17 | #include "common/virtual_buffer.h" |
| 18 | #include "core/memory.h" | ||
| 19 | #include "video_core/cache_types.h" | 18 | #include "video_core/cache_types.h" |
| 19 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 20 | #include "video_core/pte_kind.h" | 20 | #include "video_core/pte_kind.h" |
| 21 | 21 | ||
| 22 | namespace VideoCore { | 22 | namespace VideoCore { |
| @@ -28,10 +28,6 @@ class InvalidationAccumulator; | |||
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | namespace Core { | 30 | namespace Core { |
| 31 | class DeviceMemory; | ||
| 32 | namespace Memory { | ||
| 33 | class Memory; | ||
| 34 | } // namespace Memory | ||
| 35 | class System; | 31 | class System; |
| 36 | } // namespace Core | 32 | } // namespace Core |
| 37 | 33 | ||
| @@ -41,6 +37,9 @@ class MemoryManager final { | |||
| 41 | public: | 37 | public: |
| 42 | explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40, | 38 | explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40, |
| 43 | u64 big_page_bits_ = 16, u64 page_bits_ = 12); | 39 | u64 big_page_bits_ = 16, u64 page_bits_ = 12); |
| 40 | explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_, | ||
| 41 | u64 address_space_bits_ = 40, u64 big_page_bits_ = 16, | ||
| 42 | u64 page_bits_ = 12); | ||
| 44 | ~MemoryManager(); | 43 | ~MemoryManager(); |
| 45 | 44 | ||
| 46 | size_t GetID() const { | 45 | size_t GetID() const { |
| @@ -50,9 +49,9 @@ public: | |||
| 50 | /// Binds a renderer to the memory manager. | 49 | /// Binds a renderer to the memory manager. |
| 51 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | 50 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 52 | 51 | ||
| 53 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | 52 | [[nodiscard]] std::optional<DAddr> GpuToCpuAddress(GPUVAddr addr) const; |
| 54 | 53 | ||
| 55 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr, std::size_t size) const; | 54 | [[nodiscard]] std::optional<DAddr> GpuToCpuAddress(GPUVAddr addr, std::size_t size) const; |
| 56 | 55 | ||
| 57 | template <typename T> | 56 | template <typename T> |
| 58 | [[nodiscard]] T Read(GPUVAddr addr) const; | 57 | [[nodiscard]] T Read(GPUVAddr addr) const; |
| @@ -69,7 +68,7 @@ public: | |||
| 69 | if (!address) { | 68 | if (!address) { |
| 70 | return {}; | 69 | return {}; |
| 71 | } | 70 | } |
| 72 | return memory.GetPointer(*address); | 71 | return memory.GetPointer<T>(*address); |
| 73 | } | 72 | } |
| 74 | 73 | ||
| 75 | template <typename T> | 74 | template <typename T> |
| @@ -110,7 +109,7 @@ public: | |||
| 110 | [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; | 109 | [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 111 | 110 | ||
| 112 | /** | 111 | /** |
| 113 | * Checks if a gpu region is mapped by a single range of cpu addresses. | 112 | * Checks if a gpu region is mapped by a single range of device addresses. |
| 114 | */ | 113 | */ |
| 115 | [[nodiscard]] bool IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const; | 114 | [[nodiscard]] bool IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 116 | 115 | ||
| @@ -120,14 +119,14 @@ public: | |||
| 120 | [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const; | 119 | [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const; |
| 121 | 120 | ||
| 122 | /** | 121 | /** |
| 123 | * Returns a vector with all the subranges of cpu addresses mapped beneath. | 122 | * Returns a vector with all the subranges of device addresses mapped beneath. |
| 124 | * if the region is continuous, a single pair will be returned. If it's unmapped, an empty | 123 | * if the region is continuous, a single pair will be returned. If it's unmapped, an empty |
| 125 | * vector will be returned; | 124 | * vector will be returned; |
| 126 | */ | 125 | */ |
| 127 | boost::container::small_vector<std::pair<GPUVAddr, std::size_t>, 32> GetSubmappedRange( | 126 | boost::container::small_vector<std::pair<GPUVAddr, std::size_t>, 32> GetSubmappedRange( |
| 128 | GPUVAddr gpu_addr, std::size_t size) const; | 127 | GPUVAddr gpu_addr, std::size_t size) const; |
| 129 | 128 | ||
| 130 | GPUVAddr Map(GPUVAddr gpu_addr, VAddr cpu_addr, std::size_t size, | 129 | GPUVAddr Map(GPUVAddr gpu_addr, DAddr dev_addr, std::size_t size, |
| 131 | PTEKind kind = PTEKind::INVALID, bool is_big_pages = true); | 130 | PTEKind kind = PTEKind::INVALID, bool is_big_pages = true); |
| 132 | GPUVAddr MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages = true); | 131 | GPUVAddr MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages = true); |
| 133 | void Unmap(GPUVAddr gpu_addr, std::size_t size); | 132 | void Unmap(GPUVAddr gpu_addr, std::size_t size); |
| @@ -186,12 +185,11 @@ private: | |||
| 186 | void GetSubmappedRangeImpl( | 185 | void GetSubmappedRangeImpl( |
| 187 | GPUVAddr gpu_addr, std::size_t size, | 186 | GPUVAddr gpu_addr, std::size_t size, |
| 188 | boost::container::small_vector< | 187 | boost::container::small_vector< |
| 189 | std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>, 32>& | 188 | std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>, 32>& |
| 190 | result) const; | 189 | result) const; |
| 191 | 190 | ||
| 192 | Core::System& system; | 191 | Core::System& system; |
| 193 | Core::Memory::Memory& memory; | 192 | MaxwellDeviceMemoryManager& memory; |
| 194 | Core::DeviceMemory& device_memory; | ||
| 195 | 193 | ||
| 196 | const u64 address_space_bits; | 194 | const u64 address_space_bits; |
| 197 | const u64 page_bits; | 195 | const u64 page_bits; |
| @@ -218,11 +216,11 @@ private: | |||
| 218 | std::vector<u64> big_entries; | 216 | std::vector<u64> big_entries; |
| 219 | 217 | ||
| 220 | template <EntryType entry_type> | 218 | template <EntryType entry_type> |
| 221 | GPUVAddr PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, | 219 | GPUVAddr PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size, |
| 222 | PTEKind kind); | 220 | PTEKind kind); |
| 223 | 221 | ||
| 224 | template <EntryType entry_type> | 222 | template <EntryType entry_type> |
| 225 | GPUVAddr BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, | 223 | GPUVAddr BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size, |
| 226 | PTEKind kind); | 224 | PTEKind kind); |
| 227 | 225 | ||
| 228 | template <bool is_big_page> | 226 | template <bool is_big_page> |
| @@ -233,11 +231,11 @@ private: | |||
| 233 | 231 | ||
| 234 | Common::MultiLevelPageTable<u32> page_table; | 232 | Common::MultiLevelPageTable<u32> page_table; |
| 235 | Common::RangeMap<GPUVAddr, PTEKind> kind_map; | 233 | Common::RangeMap<GPUVAddr, PTEKind> kind_map; |
| 236 | Common::VirtualBuffer<u32> big_page_table_cpu; | 234 | Common::VirtualBuffer<u32> big_page_table_dev; |
| 237 | 235 | ||
| 238 | std::vector<u64> big_page_continuous; | 236 | std::vector<u64> big_page_continuous; |
| 239 | boost::container::small_vector<std::pair<VAddr, std::size_t>, 32> page_stash{}; | 237 | boost::container::small_vector<std::pair<DAddr, std::size_t>, 32> page_stash{}; |
| 240 | boost::container::small_vector<std::pair<VAddr, std::size_t>, 32> page_stash2{}; | 238 | boost::container::small_vector<std::pair<DAddr, std::size_t>, 32> page_stash2{}; |
| 241 | 239 | ||
| 242 | mutable std::mutex guard; | 240 | mutable std::mutex guard; |
| 243 | 241 | ||
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index a64404ce4..4861b123a 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h | |||
| @@ -18,9 +18,9 @@ | |||
| 18 | 18 | ||
| 19 | #include "common/assert.h" | 19 | #include "common/assert.h" |
| 20 | #include "common/settings.h" | 20 | #include "common/settings.h" |
| 21 | #include "core/memory.h" | ||
| 22 | #include "video_core/control/channel_state_cache.h" | 21 | #include "video_core/control/channel_state_cache.h" |
| 23 | #include "video_core/engines/maxwell_3d.h" | 22 | #include "video_core/engines/maxwell_3d.h" |
| 23 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 24 | #include "video_core/memory_manager.h" | 24 | #include "video_core/memory_manager.h" |
| 25 | #include "video_core/rasterizer_interface.h" | 25 | #include "video_core/rasterizer_interface.h" |
| 26 | #include "video_core/texture_cache/slot_vector.h" | 26 | #include "video_core/texture_cache/slot_vector.h" |
| @@ -102,18 +102,19 @@ template <class QueryCache, class CachedQuery, class CounterStream, class HostCo | |||
| 102 | class QueryCacheLegacy : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | 102 | class QueryCacheLegacy : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { |
| 103 | public: | 103 | public: |
| 104 | explicit QueryCacheLegacy(VideoCore::RasterizerInterface& rasterizer_, | 104 | explicit QueryCacheLegacy(VideoCore::RasterizerInterface& rasterizer_, |
| 105 | Core::Memory::Memory& cpu_memory_) | 105 | Tegra::MaxwellDeviceMemoryManager& device_memory_) |
| 106 | : rasterizer{rasterizer_}, | 106 | : rasterizer{rasterizer_}, |
| 107 | // Use reinterpret_cast instead of static_cast as workaround for | 107 | // Use reinterpret_cast instead of static_cast as workaround for |
| 108 | // UBSan bug (https://github.com/llvm/llvm-project/issues/59060) | 108 | // UBSan bug (https://github.com/llvm/llvm-project/issues/59060) |
| 109 | cpu_memory{cpu_memory_}, streams{{ | 109 | device_memory{device_memory_}, |
| 110 | {CounterStream{reinterpret_cast<QueryCache&>(*this), | 110 | streams{{ |
| 111 | VideoCore::QueryType::SamplesPassed}}, | 111 | {CounterStream{reinterpret_cast<QueryCache&>(*this), |
| 112 | {CounterStream{reinterpret_cast<QueryCache&>(*this), | 112 | VideoCore::QueryType::SamplesPassed}}, |
| 113 | VideoCore::QueryType::PrimitivesGenerated}}, | 113 | {CounterStream{reinterpret_cast<QueryCache&>(*this), |
| 114 | {CounterStream{reinterpret_cast<QueryCache&>(*this), | 114 | VideoCore::QueryType::PrimitivesGenerated}}, |
| 115 | VideoCore::QueryType::TfbPrimitivesWritten}}, | 115 | {CounterStream{reinterpret_cast<QueryCache&>(*this), |
| 116 | }} { | 116 | VideoCore::QueryType::TfbPrimitivesWritten}}, |
| 117 | }} { | ||
| 117 | (void)slot_async_jobs.insert(); // Null value | 118 | (void)slot_async_jobs.insert(); // Null value |
| 118 | } | 119 | } |
| 119 | 120 | ||
| @@ -322,13 +323,14 @@ private: | |||
| 322 | local_lock.unlock(); | 323 | local_lock.unlock(); |
| 323 | if (timestamp) { | 324 | if (timestamp) { |
| 324 | u64 timestamp_value = *timestamp; | 325 | u64 timestamp_value = *timestamp; |
| 325 | cpu_memory.WriteBlockUnsafe(address + sizeof(u64), ×tamp_value, sizeof(u64)); | 326 | device_memory.WriteBlockUnsafe(address + sizeof(u64), ×tamp_value, |
| 326 | cpu_memory.WriteBlockUnsafe(address, &value, sizeof(u64)); | 327 | sizeof(u64)); |
| 328 | device_memory.WriteBlockUnsafe(address, &value, sizeof(u64)); | ||
| 327 | rasterizer.InvalidateRegion(address, sizeof(u64) * 2, | 329 | rasterizer.InvalidateRegion(address, sizeof(u64) * 2, |
| 328 | VideoCommon::CacheType::NoQueryCache); | 330 | VideoCommon::CacheType::NoQueryCache); |
| 329 | } else { | 331 | } else { |
| 330 | u32 small_value = static_cast<u32>(value); | 332 | u32 small_value = static_cast<u32>(value); |
| 331 | cpu_memory.WriteBlockUnsafe(address, &small_value, sizeof(u32)); | 333 | device_memory.WriteBlockUnsafe(address, &small_value, sizeof(u32)); |
| 332 | rasterizer.InvalidateRegion(address, sizeof(u32), | 334 | rasterizer.InvalidateRegion(address, sizeof(u32), |
| 333 | VideoCommon::CacheType::NoQueryCache); | 335 | VideoCommon::CacheType::NoQueryCache); |
| 334 | } | 336 | } |
| @@ -342,7 +344,7 @@ private: | |||
| 342 | SlotVector<AsyncJob> slot_async_jobs; | 344 | SlotVector<AsyncJob> slot_async_jobs; |
| 343 | 345 | ||
| 344 | VideoCore::RasterizerInterface& rasterizer; | 346 | VideoCore::RasterizerInterface& rasterizer; |
| 345 | Core::Memory::Memory& cpu_memory; | 347 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 346 | 348 | ||
| 347 | mutable std::recursive_mutex mutex; | 349 | mutable std::recursive_mutex mutex; |
| 348 | 350 | ||
diff --git a/src/video_core/query_cache/query_base.h b/src/video_core/query_cache/query_base.h index 68f1d38c1..d5d21beaa 100644 --- a/src/video_core/query_cache/query_base.h +++ b/src/video_core/query_cache/query_base.h | |||
| @@ -23,7 +23,7 @@ DECLARE_ENUM_FLAG_OPERATORS(QueryFlagBits) | |||
| 23 | 23 | ||
| 24 | class QueryBase { | 24 | class QueryBase { |
| 25 | public: | 25 | public: |
| 26 | VAddr guest_address{}; | 26 | DAddr guest_address{}; |
| 27 | QueryFlagBits flags{}; | 27 | QueryFlagBits flags{}; |
| 28 | u64 value{}; | 28 | u64 value{}; |
| 29 | 29 | ||
| @@ -32,7 +32,7 @@ protected: | |||
| 32 | QueryBase() = default; | 32 | QueryBase() = default; |
| 33 | 33 | ||
| 34 | // Parameterized constructor | 34 | // Parameterized constructor |
| 35 | QueryBase(VAddr address, QueryFlagBits flags_, u64 value_) | 35 | QueryBase(DAddr address, QueryFlagBits flags_, u64 value_) |
| 36 | : guest_address(address), flags(flags_), value{value_} {} | 36 | : guest_address(address), flags(flags_), value{value_} {} |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 94f0c4466..08b779055 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "common/scope_exit.h" | 16 | #include "common/scope_exit.h" |
| 17 | #include "common/settings.h" | 17 | #include "common/settings.h" |
| 18 | #include "core/memory.h" | ||
| 19 | #include "video_core/engines/maxwell_3d.h" | 18 | #include "video_core/engines/maxwell_3d.h" |
| 20 | #include "video_core/gpu.h" | 19 | #include "video_core/gpu.h" |
| 20 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 21 | #include "video_core/memory_manager.h" | 21 | #include "video_core/memory_manager.h" |
| 22 | #include "video_core/query_cache/bank_base.h" | 22 | #include "video_core/query_cache/bank_base.h" |
| 23 | #include "video_core/query_cache/query_base.h" | 23 | #include "video_core/query_cache/query_base.h" |
| @@ -113,9 +113,10 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl { | |||
| 113 | using RuntimeType = typename Traits::RuntimeType; | 113 | using RuntimeType = typename Traits::RuntimeType; |
| 114 | 114 | ||
| 115 | QueryCacheBaseImpl(QueryCacheBase<Traits>* owner_, VideoCore::RasterizerInterface& rasterizer_, | 115 | QueryCacheBaseImpl(QueryCacheBase<Traits>* owner_, VideoCore::RasterizerInterface& rasterizer_, |
| 116 | Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_, Tegra::GPU& gpu_) | 116 | Tegra::MaxwellDeviceMemoryManager& device_memory_, RuntimeType& runtime_, |
| 117 | Tegra::GPU& gpu_) | ||
| 117 | : owner{owner_}, rasterizer{rasterizer_}, | 118 | : owner{owner_}, rasterizer{rasterizer_}, |
| 118 | cpu_memory{cpu_memory_}, runtime{runtime_}, gpu{gpu_} { | 119 | device_memory{device_memory_}, runtime{runtime_}, gpu{gpu_} { |
| 119 | streamer_mask = 0; | 120 | streamer_mask = 0; |
| 120 | for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) { | 121 | for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) { |
| 121 | streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i)); | 122 | streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i)); |
| @@ -158,7 +159,7 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl { | |||
| 158 | 159 | ||
| 159 | QueryCacheBase<Traits>* owner; | 160 | QueryCacheBase<Traits>* owner; |
| 160 | VideoCore::RasterizerInterface& rasterizer; | 161 | VideoCore::RasterizerInterface& rasterizer; |
| 161 | Core::Memory::Memory& cpu_memory; | 162 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 162 | RuntimeType& runtime; | 163 | RuntimeType& runtime; |
| 163 | Tegra::GPU& gpu; | 164 | Tegra::GPU& gpu; |
| 164 | std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers; | 165 | std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers; |
| @@ -171,10 +172,11 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl { | |||
| 171 | template <typename Traits> | 172 | template <typename Traits> |
| 172 | QueryCacheBase<Traits>::QueryCacheBase(Tegra::GPU& gpu_, | 173 | QueryCacheBase<Traits>::QueryCacheBase(Tegra::GPU& gpu_, |
| 173 | VideoCore::RasterizerInterface& rasterizer_, | 174 | VideoCore::RasterizerInterface& rasterizer_, |
| 174 | Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_) | 175 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 176 | RuntimeType& runtime_) | ||
| 175 | : cached_queries{} { | 177 | : cached_queries{} { |
| 176 | impl = std::make_unique<QueryCacheBase<Traits>::QueryCacheBaseImpl>( | 178 | impl = std::make_unique<QueryCacheBase<Traits>::QueryCacheBaseImpl>( |
| 177 | this, rasterizer_, cpu_memory_, runtime_, gpu_); | 179 | this, rasterizer_, device_memory_, runtime_, gpu_); |
| 178 | } | 180 | } |
| 179 | 181 | ||
| 180 | template <typename Traits> | 182 | template <typename Traits> |
| @@ -240,7 +242,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type | |||
| 240 | if (!cpu_addr_opt) [[unlikely]] { | 242 | if (!cpu_addr_opt) [[unlikely]] { |
| 241 | return; | 243 | return; |
| 242 | } | 244 | } |
| 243 | VAddr cpu_addr = *cpu_addr_opt; | 245 | DAddr cpu_addr = *cpu_addr_opt; |
| 244 | const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport); | 246 | const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport); |
| 245 | auto* query = streamer->GetQuery(new_query_id); | 247 | auto* query = streamer->GetQuery(new_query_id); |
| 246 | if (is_fence) { | 248 | if (is_fence) { |
| @@ -250,13 +252,12 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type | |||
| 250 | query_location.stream_id.Assign(static_cast<u32>(streamer_id)); | 252 | query_location.stream_id.Assign(static_cast<u32>(streamer_id)); |
| 251 | query_location.query_id.Assign(static_cast<u32>(new_query_id)); | 253 | query_location.query_id.Assign(static_cast<u32>(new_query_id)); |
| 252 | const auto gen_caching_indexing = [](VAddr cur_addr) { | 254 | const auto gen_caching_indexing = [](VAddr cur_addr) { |
| 253 | return std::make_pair<u64, u32>(cur_addr >> Core::Memory::YUZU_PAGEBITS, | 255 | return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS, |
| 254 | static_cast<u32>(cur_addr & Core::Memory::YUZU_PAGEMASK)); | 256 | static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK)); |
| 255 | }; | 257 | }; |
| 256 | u8* pointer = impl->cpu_memory.GetPointer(cpu_addr); | 258 | u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr); |
| 257 | u8* pointer_timestamp = impl->cpu_memory.GetPointer(cpu_addr + 8); | 259 | u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8); |
| 258 | bool is_synced = !Settings::IsGPULevelHigh() && is_fence; | 260 | bool is_synced = !Settings::IsGPULevelHigh() && is_fence; |
| 259 | |||
| 260 | std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location, | 261 | std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location, |
| 261 | pointer, pointer_timestamp] { | 262 | pointer, pointer_timestamp] { |
| 262 | if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { | 263 | if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { |
| @@ -323,8 +324,8 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type | |||
| 323 | template <typename Traits> | 324 | template <typename Traits> |
| 324 | void QueryCacheBase<Traits>::UnregisterPending() { | 325 | void QueryCacheBase<Traits>::UnregisterPending() { |
| 325 | const auto gen_caching_indexing = [](VAddr cur_addr) { | 326 | const auto gen_caching_indexing = [](VAddr cur_addr) { |
| 326 | return std::make_pair<u64, u32>(cur_addr >> Core::Memory::YUZU_PAGEBITS, | 327 | return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS, |
| 327 | static_cast<u32>(cur_addr & Core::Memory::YUZU_PAGEMASK)); | 328 | static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK)); |
| 328 | }; | 329 | }; |
| 329 | std::scoped_lock lock(cache_mutex); | 330 | std::scoped_lock lock(cache_mutex); |
| 330 | for (QueryLocation loc : impl->pending_unregister) { | 331 | for (QueryLocation loc : impl->pending_unregister) { |
| @@ -388,7 +389,7 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() { | |||
| 388 | } | 389 | } |
| 389 | VAddr cpu_addr = *cpu_addr_opt; | 390 | VAddr cpu_addr = *cpu_addr_opt; |
| 390 | std::scoped_lock lock(cache_mutex); | 391 | std::scoped_lock lock(cache_mutex); |
| 391 | auto it1 = cached_queries.find(cpu_addr >> Core::Memory::YUZU_PAGEBITS); | 392 | auto it1 = cached_queries.find(cpu_addr >> Core::DEVICE_PAGEBITS); |
| 392 | if (it1 == cached_queries.end()) { | 393 | if (it1 == cached_queries.end()) { |
| 393 | return VideoCommon::LookupData{ | 394 | return VideoCommon::LookupData{ |
| 394 | .address = cpu_addr, | 395 | .address = cpu_addr, |
| @@ -396,10 +397,10 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() { | |||
| 396 | }; | 397 | }; |
| 397 | } | 398 | } |
| 398 | auto& sub_container = it1->second; | 399 | auto& sub_container = it1->second; |
| 399 | auto it_current = sub_container.find(cpu_addr & Core::Memory::YUZU_PAGEMASK); | 400 | auto it_current = sub_container.find(cpu_addr & Core::DEVICE_PAGEMASK); |
| 400 | 401 | ||
| 401 | if (it_current == sub_container.end()) { | 402 | if (it_current == sub_container.end()) { |
| 402 | auto it_current_2 = sub_container.find((cpu_addr & Core::Memory::YUZU_PAGEMASK) + 4); | 403 | auto it_current_2 = sub_container.find((cpu_addr & Core::DEVICE_PAGEMASK) + 4); |
| 403 | if (it_current_2 == sub_container.end()) { | 404 | if (it_current_2 == sub_container.end()) { |
| 404 | return VideoCommon::LookupData{ | 405 | return VideoCommon::LookupData{ |
| 405 | .address = cpu_addr, | 406 | .address = cpu_addr, |
| @@ -559,7 +560,7 @@ bool QueryCacheBase<Traits>::SemiFlushQueryDirty(QueryCacheBase<Traits>::QueryLo | |||
| 559 | } | 560 | } |
| 560 | if (True(query_base->flags & QueryFlagBits::IsFinalValueSynced) && | 561 | if (True(query_base->flags & QueryFlagBits::IsFinalValueSynced) && |
| 561 | False(query_base->flags & QueryFlagBits::IsGuestSynced)) { | 562 | False(query_base->flags & QueryFlagBits::IsGuestSynced)) { |
| 562 | auto* ptr = impl->cpu_memory.GetPointer(query_base->guest_address); | 563 | auto* ptr = impl->device_memory.template GetPointer<u8>(query_base->guest_address); |
| 563 | if (True(query_base->flags & QueryFlagBits::HasTimestamp)) { | 564 | if (True(query_base->flags & QueryFlagBits::HasTimestamp)) { |
| 564 | std::memcpy(ptr, &query_base->value, sizeof(query_base->value)); | 565 | std::memcpy(ptr, &query_base->value, sizeof(query_base->value)); |
| 565 | return false; | 566 | return false; |
diff --git a/src/video_core/query_cache/query_cache_base.h b/src/video_core/query_cache/query_cache_base.h index 5a88e7f0a..00c25c8d6 100644 --- a/src/video_core/query_cache/query_cache_base.h +++ b/src/video_core/query_cache/query_cache_base.h | |||
| @@ -13,15 +13,11 @@ | |||
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/bit_field.h" | 14 | #include "common/bit_field.h" |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "core/memory.h" | ||
| 17 | #include "video_core/control/channel_state_cache.h" | 16 | #include "video_core/control/channel_state_cache.h" |
| 17 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 18 | #include "video_core/query_cache/query_base.h" | 18 | #include "video_core/query_cache/query_base.h" |
| 19 | #include "video_core/query_cache/types.h" | 19 | #include "video_core/query_cache/types.h" |
| 20 | 20 | ||
| 21 | namespace Core::Memory { | ||
| 22 | class Memory; | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace VideoCore { | 21 | namespace VideoCore { |
| 26 | class RasterizerInterface; | 22 | class RasterizerInterface; |
| 27 | } | 23 | } |
| @@ -53,7 +49,8 @@ public: | |||
| 53 | }; | 49 | }; |
| 54 | 50 | ||
| 55 | explicit QueryCacheBase(Tegra::GPU& gpu, VideoCore::RasterizerInterface& rasterizer_, | 51 | explicit QueryCacheBase(Tegra::GPU& gpu, VideoCore::RasterizerInterface& rasterizer_, |
| 56 | Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_); | 52 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 53 | RuntimeType& runtime_); | ||
| 57 | 54 | ||
| 58 | ~QueryCacheBase(); | 55 | ~QueryCacheBase(); |
| 59 | 56 | ||
| @@ -125,10 +122,10 @@ protected: | |||
| 125 | const u64 addr_begin = addr; | 122 | const u64 addr_begin = addr; |
| 126 | const u64 addr_end = addr_begin + size; | 123 | const u64 addr_end = addr_begin + size; |
| 127 | 124 | ||
| 128 | const u64 page_end = addr_end >> Core::Memory::YUZU_PAGEBITS; | 125 | const u64 page_end = addr_end >> Core::DEVICE_PAGEBITS; |
| 129 | std::scoped_lock lock(cache_mutex); | 126 | std::scoped_lock lock(cache_mutex); |
| 130 | for (u64 page = addr_begin >> Core::Memory::YUZU_PAGEBITS; page <= page_end; ++page) { | 127 | for (u64 page = addr_begin >> Core::DEVICE_PAGEBITS; page <= page_end; ++page) { |
| 131 | const u64 page_start = page << Core::Memory::YUZU_PAGEBITS; | 128 | const u64 page_start = page << Core::DEVICE_PAGEBITS; |
| 132 | const auto in_range = [page_start, addr_begin, addr_end](const u32 query_location) { | 129 | const auto in_range = [page_start, addr_begin, addr_end](const u32 query_location) { |
| 133 | const u64 cache_begin = page_start + query_location; | 130 | const u64 cache_begin = page_start + query_location; |
| 134 | const u64 cache_end = cache_begin + sizeof(u32); | 131 | const u64 cache_end = cache_begin + sizeof(u32); |
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp deleted file mode 100644 index f200a650f..000000000 --- a/src/video_core/rasterizer_accelerated.cpp +++ /dev/null | |||
| @@ -1,72 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <atomic> | ||
| 5 | |||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/div_ceil.h" | ||
| 9 | #include "core/memory.h" | ||
| 10 | #include "video_core/rasterizer_accelerated.h" | ||
| 11 | |||
| 12 | namespace VideoCore { | ||
| 13 | |||
| 14 | using namespace Core::Memory; | ||
| 15 | |||
| 16 | RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) | ||
| 17 | : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {} | ||
| 18 | |||
| 19 | RasterizerAccelerated::~RasterizerAccelerated() = default; | ||
| 20 | |||
| 21 | void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { | ||
| 22 | u64 uncache_begin = 0; | ||
| 23 | u64 cache_begin = 0; | ||
| 24 | u64 uncache_bytes = 0; | ||
| 25 | u64 cache_bytes = 0; | ||
| 26 | |||
| 27 | std::atomic_thread_fence(std::memory_order_acquire); | ||
| 28 | const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE); | ||
| 29 | for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) { | ||
| 30 | std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page); | ||
| 31 | |||
| 32 | if (delta > 0) { | ||
| 33 | ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!"); | ||
| 34 | } else if (delta < 0) { | ||
| 35 | ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!"); | ||
| 36 | } else { | ||
| 37 | ASSERT_MSG(false, "Delta must be non-zero!"); | ||
| 38 | } | ||
| 39 | |||
| 40 | // Adds or subtracts 1, as count is a unsigned 8-bit value | ||
| 41 | count.fetch_add(static_cast<u16>(delta), std::memory_order_release); | ||
| 42 | |||
| 43 | // Assume delta is either -1 or 1 | ||
| 44 | if (count.load(std::memory_order::relaxed) == 0) { | ||
| 45 | if (uncache_bytes == 0) { | ||
| 46 | uncache_begin = page; | ||
| 47 | } | ||
| 48 | uncache_bytes += YUZU_PAGESIZE; | ||
| 49 | } else if (uncache_bytes > 0) { | ||
| 50 | cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, | ||
| 51 | false); | ||
| 52 | uncache_bytes = 0; | ||
| 53 | } | ||
| 54 | if (count.load(std::memory_order::relaxed) == 1 && delta > 0) { | ||
| 55 | if (cache_bytes == 0) { | ||
| 56 | cache_begin = page; | ||
| 57 | } | ||
| 58 | cache_bytes += YUZU_PAGESIZE; | ||
| 59 | } else if (cache_bytes > 0) { | ||
| 60 | cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); | ||
| 61 | cache_bytes = 0; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | if (uncache_bytes > 0) { | ||
| 65 | cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false); | ||
| 66 | } | ||
| 67 | if (cache_bytes > 0) { | ||
| 68 | cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | } // namespace VideoCore | ||
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h deleted file mode 100644 index e6c0ea87a..000000000 --- a/src/video_core/rasterizer_accelerated.h +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/rasterizer_interface.h" | ||
| 11 | |||
| 12 | namespace Core::Memory { | ||
| 13 | class Memory; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace VideoCore { | ||
| 17 | |||
| 18 | /// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface. | ||
| 19 | class RasterizerAccelerated : public RasterizerInterface { | ||
| 20 | public: | ||
| 21 | explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_); | ||
| 22 | ~RasterizerAccelerated() override; | ||
| 23 | |||
| 24 | void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override; | ||
| 25 | |||
| 26 | private: | ||
| 27 | class CacheEntry final { | ||
| 28 | public: | ||
| 29 | CacheEntry() = default; | ||
| 30 | |||
| 31 | std::atomic_uint16_t& Count(std::size_t page) { | ||
| 32 | return values[page & 3]; | ||
| 33 | } | ||
| 34 | |||
| 35 | const std::atomic_uint16_t& Count(std::size_t page) const { | ||
| 36 | return values[page & 3]; | ||
| 37 | } | ||
| 38 | |||
| 39 | private: | ||
| 40 | std::array<std::atomic_uint16_t, 4> values{}; | ||
| 41 | }; | ||
| 42 | static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); | ||
| 43 | |||
| 44 | using CachedPages = std::array<CacheEntry, 0x2000000>; | ||
| 45 | std::unique_ptr<CachedPages> cached_pages; | ||
| 46 | Core::Memory::Memory& cpu_memory; | ||
| 47 | }; | ||
| 48 | |||
| 49 | } // namespace VideoCore | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 49224ca85..8fa4e4d9a 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -86,35 +86,35 @@ public: | |||
| 86 | virtual void FlushAll() = 0; | 86 | virtual void FlushAll() = 0; |
| 87 | 87 | ||
| 88 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 88 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 89 | virtual void FlushRegion(VAddr addr, u64 size, | 89 | virtual void FlushRegion(DAddr addr, u64 size, |
| 90 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; | 90 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; |
| 91 | 91 | ||
| 92 | /// Check if the the specified memory area requires flushing to CPU Memory. | 92 | /// Check if the the specified memory area requires flushing to CPU Memory. |
| 93 | virtual bool MustFlushRegion(VAddr addr, u64 size, | 93 | virtual bool MustFlushRegion(DAddr addr, u64 size, |
| 94 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; | 94 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; |
| 95 | 95 | ||
| 96 | virtual RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) = 0; | 96 | virtual RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) = 0; |
| 97 | 97 | ||
| 98 | /// Notify rasterizer that any caches of the specified region should be invalidated | 98 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 99 | virtual void InvalidateRegion(VAddr addr, u64 size, | 99 | virtual void InvalidateRegion(DAddr addr, u64 size, |
| 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; | 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; |
| 101 | 101 | ||
| 102 | virtual void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) { | 102 | virtual void InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) { |
| 103 | for (const auto& [cpu_addr, size] : sequences) { | 103 | for (const auto& [cpu_addr, size] : sequences) { |
| 104 | InvalidateRegion(cpu_addr, size); | 104 | InvalidateRegion(cpu_addr, size); |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /// Notify rasterizer that any caches of the specified region are desync with guest | 108 | /// Notify rasterizer that any caches of the specified region are desync with guest |
| 109 | virtual void OnCacheInvalidation(VAddr addr, u64 size) = 0; | 109 | virtual void OnCacheInvalidation(PAddr addr, u64 size) = 0; |
| 110 | 110 | ||
| 111 | virtual bool OnCPUWrite(VAddr addr, u64 size) = 0; | 111 | virtual bool OnCPUWrite(PAddr addr, u64 size) = 0; |
| 112 | 112 | ||
| 113 | /// Sync memory between guest and host. | 113 | /// Sync memory between guest and host. |
| 114 | virtual void InvalidateGPUCache() = 0; | 114 | virtual void InvalidateGPUCache() = 0; |
| 115 | 115 | ||
| 116 | /// Unmap memory range | 116 | /// Unmap memory range |
| 117 | virtual void UnmapMemory(VAddr addr, u64 size) = 0; | 117 | virtual void UnmapMemory(DAddr addr, u64 size) = 0; |
| 118 | 118 | ||
| 119 | /// Remap GPU memory range. This means underneath backing memory changed | 119 | /// Remap GPU memory range. This means underneath backing memory changed |
| 120 | virtual void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) = 0; | 120 | virtual void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) = 0; |
| @@ -122,7 +122,7 @@ public: | |||
| 122 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 122 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 123 | /// and invalidated | 123 | /// and invalidated |
| 124 | virtual void FlushAndInvalidateRegion( | 124 | virtual void FlushAndInvalidateRegion( |
| 125 | VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; | 125 | DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; |
| 126 | 126 | ||
| 127 | /// Notify the host renderer to wait for previous primitive and compute operations. | 127 | /// Notify the host renderer to wait for previous primitive and compute operations. |
| 128 | virtual void WaitForIdle() = 0; | 128 | virtual void WaitForIdle() = 0; |
| @@ -157,13 +157,10 @@ public: | |||
| 157 | 157 | ||
| 158 | /// Attempt to use a faster method to display the framebuffer to screen | 158 | /// Attempt to use a faster method to display the framebuffer to screen |
| 159 | [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, | 159 | [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 160 | VAddr framebuffer_addr, u32 pixel_stride) { | 160 | DAddr framebuffer_addr, u32 pixel_stride) { |
| 161 | return false; | 161 | return false; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | /// Increase/decrease the number of object in pages touching the specified region | ||
| 165 | virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {} | ||
| 166 | |||
| 167 | /// Initialize disk cached resources for the game being emulated | 164 | /// Initialize disk cached resources for the game being emulated |
| 168 | virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 165 | virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 169 | const DiskResourceLoadCallback& callback) {} | 166 | const DiskResourceLoadCallback& callback) {} |
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp index 4f1d5b548..abfabb65b 100644 --- a/src/video_core/renderer_null/null_rasterizer.cpp +++ b/src/video_core/renderer_null/null_rasterizer.cpp | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/alignment.h" | 4 | #include "common/alignment.h" |
| 5 | #include "core/memory.h" | ||
| 6 | #include "video_core/control/channel_state.h" | 5 | #include "video_core/control/channel_state.h" |
| 7 | #include "video_core/host1x/host1x.h" | 6 | #include "video_core/host1x/host1x.h" |
| 8 | #include "video_core/memory_manager.h" | 7 | #include "video_core/memory_manager.h" |
| @@ -19,8 +18,7 @@ bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { | |||
| 19 | return true; | 18 | return true; |
| 20 | } | 19 | } |
| 21 | 20 | ||
| 22 | RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu) | 21 | RasterizerNull::RasterizerNull(Tegra::GPU& gpu) : m_gpu{gpu} {} |
| 23 | : RasterizerAccelerated(cpu_memory_), m_gpu{gpu} {} | ||
| 24 | RasterizerNull::~RasterizerNull() = default; | 22 | RasterizerNull::~RasterizerNull() = default; |
| 25 | 23 | ||
| 26 | void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} | 24 | void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} |
| @@ -45,25 +43,25 @@ void RasterizerNull::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr | |||
| 45 | u32 size) {} | 43 | u32 size) {} |
| 46 | void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {} | 44 | void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {} |
| 47 | void RasterizerNull::FlushAll() {} | 45 | void RasterizerNull::FlushAll() {} |
| 48 | void RasterizerNull::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} | 46 | void RasterizerNull::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType) {} |
| 49 | bool RasterizerNull::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType) { | 47 | bool RasterizerNull::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType) { |
| 50 | return false; | 48 | return false; |
| 51 | } | 49 | } |
| 52 | void RasterizerNull::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} | 50 | void RasterizerNull::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType) {} |
| 53 | bool RasterizerNull::OnCPUWrite(VAddr addr, u64 size) { | 51 | bool RasterizerNull::OnCPUWrite(PAddr addr, u64 size) { |
| 54 | return false; | 52 | return false; |
| 55 | } | 53 | } |
| 56 | void RasterizerNull::OnCacheInvalidation(VAddr addr, u64 size) {} | 54 | void RasterizerNull::OnCacheInvalidation(PAddr addr, u64 size) {} |
| 57 | VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(VAddr addr, u64 size) { | 55 | VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(PAddr addr, u64 size) { |
| 58 | VideoCore::RasterizerDownloadArea new_area{ | 56 | VideoCore::RasterizerDownloadArea new_area{ |
| 59 | .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), | 57 | .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE), |
| 60 | .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), | 58 | .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE), |
| 61 | .preemtive = true, | 59 | .preemtive = true, |
| 62 | }; | 60 | }; |
| 63 | return new_area; | 61 | return new_area; |
| 64 | } | 62 | } |
| 65 | void RasterizerNull::InvalidateGPUCache() {} | 63 | void RasterizerNull::InvalidateGPUCache() {} |
| 66 | void RasterizerNull::UnmapMemory(VAddr addr, u64 size) {} | 64 | void RasterizerNull::UnmapMemory(DAddr addr, u64 size) {} |
| 67 | void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {} | 65 | void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {} |
| 68 | void RasterizerNull::SignalFence(std::function<void()>&& func) { | 66 | void RasterizerNull::SignalFence(std::function<void()>&& func) { |
| 69 | func(); | 67 | func(); |
| @@ -78,7 +76,7 @@ void RasterizerNull::SignalSyncPoint(u32 value) { | |||
| 78 | } | 76 | } |
| 79 | void RasterizerNull::SignalReference() {} | 77 | void RasterizerNull::SignalReference() {} |
| 80 | void RasterizerNull::ReleaseFences(bool) {} | 78 | void RasterizerNull::ReleaseFences(bool) {} |
| 81 | void RasterizerNull::FlushAndInvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} | 79 | void RasterizerNull::FlushAndInvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType) {} |
| 82 | void RasterizerNull::WaitForIdle() {} | 80 | void RasterizerNull::WaitForIdle() {} |
| 83 | void RasterizerNull::FragmentBarrier() {} | 81 | void RasterizerNull::FragmentBarrier() {} |
| 84 | void RasterizerNull::TiledCacheBarrier() {} | 82 | void RasterizerNull::TiledCacheBarrier() {} |
| @@ -95,7 +93,7 @@ bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surfac | |||
| 95 | void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 93 | void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 96 | std::span<const u8> memory) {} | 94 | std::span<const u8> memory) {} |
| 97 | bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 95 | bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 98 | VAddr framebuffer_addr, u32 pixel_stride) { | 96 | DAddr framebuffer_addr, u32 pixel_stride) { |
| 99 | return true; | 97 | return true; |
| 100 | } | 98 | } |
| 101 | void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 99 | void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h index 23001eeb8..a5789604f 100644 --- a/src/video_core/renderer_null/null_rasterizer.h +++ b/src/video_core/renderer_null/null_rasterizer.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | #include "common/common_types.h" | 6 | #include "common/common_types.h" |
| 7 | #include "video_core/control/channel_state_cache.h" | 7 | #include "video_core/control/channel_state_cache.h" |
| 8 | #include "video_core/engines/maxwell_dma.h" | 8 | #include "video_core/engines/maxwell_dma.h" |
| 9 | #include "video_core/rasterizer_accelerated.h" | ||
| 10 | #include "video_core/rasterizer_interface.h" | 9 | #include "video_core/rasterizer_interface.h" |
| 11 | 10 | ||
| 12 | namespace Core { | 11 | namespace Core { |
| @@ -32,10 +31,10 @@ public: | |||
| 32 | } | 31 | } |
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | class RasterizerNull final : public VideoCore::RasterizerAccelerated, | 34 | class RasterizerNull final : public VideoCore::RasterizerInterface, |
| 36 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | 35 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { |
| 37 | public: | 36 | public: |
| 38 | explicit RasterizerNull(Core::Memory::Memory& cpu_memory, Tegra::GPU& gpu); | 37 | explicit RasterizerNull(Tegra::GPU& gpu); |
| 39 | ~RasterizerNull() override; | 38 | ~RasterizerNull() override; |
| 40 | 39 | ||
| 41 | void Draw(bool is_indexed, u32 instance_count) override; | 40 | void Draw(bool is_indexed, u32 instance_count) override; |
| @@ -48,17 +47,17 @@ public: | |||
| 48 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; | 47 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; |
| 49 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; | 48 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; |
| 50 | void FlushAll() override; | 49 | void FlushAll() override; |
| 51 | void FlushRegion(VAddr addr, u64 size, | 50 | void FlushRegion(DAddr addr, u64 size, |
| 52 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 51 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 53 | bool MustFlushRegion(VAddr addr, u64 size, | 52 | bool MustFlushRegion(DAddr addr, u64 size, |
| 54 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 53 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 55 | void InvalidateRegion(VAddr addr, u64 size, | 54 | void InvalidateRegion(DAddr addr, u64 size, |
| 56 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 55 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 57 | void OnCacheInvalidation(VAddr addr, u64 size) override; | 56 | void OnCacheInvalidation(DAddr addr, u64 size) override; |
| 58 | bool OnCPUWrite(VAddr addr, u64 size) override; | 57 | bool OnCPUWrite(DAddr addr, u64 size) override; |
| 59 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; | 58 | VideoCore::RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) override; |
| 60 | void InvalidateGPUCache() override; | 59 | void InvalidateGPUCache() override; |
| 61 | void UnmapMemory(VAddr addr, u64 size) override; | 60 | void UnmapMemory(DAddr addr, u64 size) override; |
| 62 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | 61 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
| 63 | void SignalFence(std::function<void()>&& func) override; | 62 | void SignalFence(std::function<void()>&& func) override; |
| 64 | void SyncOperation(std::function<void()>&& func) override; | 63 | void SyncOperation(std::function<void()>&& func) override; |
| @@ -66,7 +65,7 @@ public: | |||
| 66 | void SignalReference() override; | 65 | void SignalReference() override; |
| 67 | void ReleaseFences(bool force) override; | 66 | void ReleaseFences(bool force) override; |
| 68 | void FlushAndInvalidateRegion( | 67 | void FlushAndInvalidateRegion( |
| 69 | VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 68 | DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 70 | void WaitForIdle() override; | 69 | void WaitForIdle() override; |
| 71 | void FragmentBarrier() override; | 70 | void FragmentBarrier() override; |
| 72 | void TiledCacheBarrier() override; | 71 | void TiledCacheBarrier() override; |
| @@ -78,7 +77,7 @@ public: | |||
| 78 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | 77 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; |
| 79 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 78 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 80 | std::span<const u8> memory) override; | 79 | std::span<const u8> memory) override; |
| 81 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 80 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, |
| 82 | u32 pixel_stride) override; | 81 | u32 pixel_stride) override; |
| 83 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 82 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 84 | const VideoCore::DiskResourceLoadCallback& callback) override; | 83 | const VideoCore::DiskResourceLoadCallback& callback) override; |
diff --git a/src/video_core/renderer_null/renderer_null.cpp b/src/video_core/renderer_null/renderer_null.cpp index be92cc2f4..078feb925 100644 --- a/src/video_core/renderer_null/renderer_null.cpp +++ b/src/video_core/renderer_null/renderer_null.cpp | |||
| @@ -7,10 +7,9 @@ | |||
| 7 | 7 | ||
| 8 | namespace Null { | 8 | namespace Null { |
| 9 | 9 | ||
| 10 | RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | 10 | RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, |
| 11 | Tegra::GPU& gpu, | ||
| 12 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 11 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 13 | : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(cpu_memory, gpu) {} | 12 | : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(gpu) {} |
| 14 | 13 | ||
| 15 | RendererNull::~RendererNull() = default; | 14 | RendererNull::~RendererNull() = default; |
| 16 | 15 | ||
diff --git a/src/video_core/renderer_null/renderer_null.h b/src/video_core/renderer_null/renderer_null.h index 967ff5645..9531b43f6 100644 --- a/src/video_core/renderer_null/renderer_null.h +++ b/src/video_core/renderer_null/renderer_null.h | |||
| @@ -13,8 +13,7 @@ namespace Null { | |||
| 13 | 13 | ||
| 14 | class RendererNull final : public VideoCore::RendererBase { | 14 | class RendererNull final : public VideoCore::RendererBase { |
| 15 | public: | 15 | public: |
| 16 | explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | 16 | explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, |
| 17 | Tegra::GPU& gpu, | ||
| 18 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | 17 | std::unique_ptr<Core::Frontend::GraphicsContext> context); |
| 19 | ~RendererNull() override; | 18 | ~RendererNull() override; |
| 20 | 19 | ||
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 517ac14dd..ade72e1f9 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -47,11 +47,10 @@ constexpr std::array PROGRAM_LUT{ | |||
| 47 | } // Anonymous namespace | 47 | } // Anonymous namespace |
| 48 | 48 | ||
| 49 | Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params) | 49 | Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params) |
| 50 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params) {} | 50 | : VideoCommon::BufferBase(null_params) {} |
| 51 | 51 | ||
| 52 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 52 | Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_) |
| 53 | VAddr cpu_addr_, u64 size_bytes_) | 53 | : VideoCommon::BufferBase(cpu_addr_, size_bytes_) { |
| 54 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) { | ||
| 55 | buffer.Create(); | 54 | buffer.Create(); |
| 56 | if (runtime.device.HasDebuggingToolAttached()) { | 55 | if (runtime.device.HasDebuggingToolAttached()) { |
| 57 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); | 56 | const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 2c18de166..af34c272b 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/buffer_cache/buffer_cache_base.h" | 11 | #include "video_core/buffer_cache/buffer_cache_base.h" |
| 12 | #include "video_core/buffer_cache/memory_tracker_base.h" | 12 | #include "video_core/buffer_cache/memory_tracker_base.h" |
| 13 | #include "video_core/rasterizer_interface.h" | ||
| 14 | #include "video_core/renderer_opengl/gl_device.h" | 13 | #include "video_core/renderer_opengl/gl_device.h" |
| 15 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 14 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 16 | #include "video_core/renderer_opengl/gl_staging_buffer_pool.h" | 15 | #include "video_core/renderer_opengl/gl_staging_buffer_pool.h" |
| @@ -19,10 +18,9 @@ namespace OpenGL { | |||
| 19 | 18 | ||
| 20 | class BufferCacheRuntime; | 19 | class BufferCacheRuntime; |
| 21 | 20 | ||
| 22 | class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> { | 21 | class Buffer : public VideoCommon::BufferBase { |
| 23 | public: | 22 | public: |
| 24 | explicit Buffer(BufferCacheRuntime&, VideoCore::RasterizerInterface& rasterizer, VAddr cpu_addr, | 23 | explicit Buffer(BufferCacheRuntime&, DAddr cpu_addr, u64 size_bytes); |
| 25 | u64 size_bytes); | ||
| 26 | explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams); | 24 | explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams); |
| 27 | 25 | ||
| 28 | void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept; | 26 | void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept; |
| @@ -244,7 +242,7 @@ struct BufferCacheParams { | |||
| 244 | using Runtime = OpenGL::BufferCacheRuntime; | 242 | using Runtime = OpenGL::BufferCacheRuntime; |
| 245 | using Buffer = OpenGL::Buffer; | 243 | using Buffer = OpenGL::Buffer; |
| 246 | using Async_Buffer = OpenGL::StagingBufferMap; | 244 | using Async_Buffer = OpenGL::StagingBufferMap; |
| 247 | using MemoryTracker = VideoCommon::MemoryTrackerBase<VideoCore::RasterizerInterface>; | 245 | using MemoryTracker = VideoCommon::MemoryTrackerBase<Tegra::MaxwellDeviceMemoryManager>; |
| 248 | 246 | ||
| 249 | static constexpr bool IS_OPENGL = true; | 247 | static constexpr bool IS_OPENGL = true; |
| 250 | static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = true; | 248 | static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = true; |
diff --git a/src/video_core/renderer_opengl/gl_query_cache.cpp b/src/video_core/renderer_opengl/gl_query_cache.cpp index fef7360ed..2147d587f 100644 --- a/src/video_core/renderer_opengl/gl_query_cache.cpp +++ b/src/video_core/renderer_opengl/gl_query_cache.cpp | |||
| @@ -35,8 +35,9 @@ constexpr GLenum GetTarget(VideoCore::QueryType type) { | |||
| 35 | 35 | ||
| 36 | } // Anonymous namespace | 36 | } // Anonymous namespace |
| 37 | 37 | ||
| 38 | QueryCache::QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_) | 38 | QueryCache::QueryCache(RasterizerOpenGL& rasterizer_, |
| 39 | : QueryCacheLegacy(rasterizer_, cpu_memory_), gl_rasterizer{rasterizer_} { | 39 | Tegra::MaxwellDeviceMemoryManager& device_memory_) |
| 40 | : QueryCacheLegacy(rasterizer_, device_memory_), gl_rasterizer{rasterizer_} { | ||
| 40 | EnableCounters(); | 41 | EnableCounters(); |
| 41 | } | 42 | } |
| 42 | 43 | ||
diff --git a/src/video_core/renderer_opengl/gl_query_cache.h b/src/video_core/renderer_opengl/gl_query_cache.h index 0721e0b3d..38118f355 100644 --- a/src/video_core/renderer_opengl/gl_query_cache.h +++ b/src/video_core/renderer_opengl/gl_query_cache.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 11 | #include "video_core/query_cache.h" | 12 | #include "video_core/query_cache.h" |
| 12 | #include "video_core/rasterizer_interface.h" | 13 | #include "video_core/rasterizer_interface.h" |
| 13 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 14 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -28,7 +29,8 @@ using CounterStream = VideoCommon::CounterStreamBase<QueryCache, HostCounter>; | |||
| 28 | class QueryCache final | 29 | class QueryCache final |
| 29 | : public VideoCommon::QueryCacheLegacy<QueryCache, CachedQuery, CounterStream, HostCounter> { | 30 | : public VideoCommon::QueryCacheLegacy<QueryCache, CachedQuery, CounterStream, HostCounter> { |
| 30 | public: | 31 | public: |
| 31 | explicit QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_); | 32 | explicit QueryCache(RasterizerOpenGL& rasterizer_, |
| 33 | Tegra::MaxwellDeviceMemoryManager& device_memory_); | ||
| 32 | ~QueryCache(); | 34 | ~QueryCache(); |
| 33 | 35 | ||
| 34 | OGLQuery AllocateQuery(VideoCore::QueryType type); | 36 | OGLQuery AllocateQuery(VideoCore::QueryType type); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7a5fad735..d5354ef2d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -70,18 +70,18 @@ std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy | |||
| 70 | } // Anonymous namespace | 70 | } // Anonymous namespace |
| 71 | 71 | ||
| 72 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 72 | RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 73 | Core::Memory::Memory& cpu_memory_, const Device& device_, | 73 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 74 | ScreenInfo& screen_info_, ProgramManager& program_manager_, | 74 | const Device& device_, ScreenInfo& screen_info_, |
| 75 | StateTracker& state_tracker_) | 75 | ProgramManager& program_manager_, StateTracker& state_tracker_) |
| 76 | : RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_), screen_info(screen_info_), | 76 | : gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_), |
| 77 | program_manager(program_manager_), state_tracker(state_tracker_), | 77 | program_manager(program_manager_), state_tracker(state_tracker_), |
| 78 | texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), | 78 | texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), |
| 79 | texture_cache(texture_cache_runtime, *this), | 79 | texture_cache(texture_cache_runtime, device_memory_), |
| 80 | buffer_cache_runtime(device, staging_buffer_pool), | 80 | buffer_cache_runtime(device, staging_buffer_pool), |
| 81 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), | 81 | buffer_cache(device_memory_, buffer_cache_runtime), |
| 82 | shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, | 82 | shader_cache(device_memory_, emu_window_, device, texture_cache, buffer_cache, |
| 83 | state_tracker, gpu.ShaderNotify()), | 83 | program_manager, state_tracker, gpu.ShaderNotify()), |
| 84 | query_cache(*this, cpu_memory_), accelerate_dma(buffer_cache, texture_cache), | 84 | query_cache(*this, device_memory_), accelerate_dma(buffer_cache, texture_cache), |
| 85 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), | 85 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), |
| 86 | blit_image(program_manager_) {} | 86 | blit_image(program_manager_) {} |
| 87 | 87 | ||
| @@ -475,7 +475,7 @@ void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) { | |||
| 475 | 475 | ||
| 476 | void RasterizerOpenGL::FlushAll() {} | 476 | void RasterizerOpenGL::FlushAll() {} |
| 477 | 477 | ||
| 478 | void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 478 | void RasterizerOpenGL::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 479 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 479 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 480 | if (addr == 0 || size == 0) { | 480 | if (addr == 0 || size == 0) { |
| 481 | return; | 481 | return; |
| @@ -493,7 +493,7 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType | |||
| 493 | } | 493 | } |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 496 | bool RasterizerOpenGL::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 497 | if ((True(which & VideoCommon::CacheType::BufferCache))) { | 497 | if ((True(which & VideoCommon::CacheType::BufferCache))) { |
| 498 | std::scoped_lock lock{buffer_cache.mutex}; | 498 | std::scoped_lock lock{buffer_cache.mutex}; |
| 499 | if (buffer_cache.IsRegionGpuModified(addr, size)) { | 499 | if (buffer_cache.IsRegionGpuModified(addr, size)) { |
| @@ -510,7 +510,7 @@ bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheT | |||
| 510 | return false; | 510 | return false; |
| 511 | } | 511 | } |
| 512 | 512 | ||
| 513 | VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(VAddr addr, u64 size) { | 513 | VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(DAddr addr, u64 size) { |
| 514 | { | 514 | { |
| 515 | std::scoped_lock lock{texture_cache.mutex}; | 515 | std::scoped_lock lock{texture_cache.mutex}; |
| 516 | auto area = texture_cache.GetFlushArea(addr, size); | 516 | auto area = texture_cache.GetFlushArea(addr, size); |
| @@ -526,14 +526,14 @@ VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(VAddr addr, u64 | |||
| 526 | } | 526 | } |
| 527 | } | 527 | } |
| 528 | VideoCore::RasterizerDownloadArea new_area{ | 528 | VideoCore::RasterizerDownloadArea new_area{ |
| 529 | .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), | 529 | .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE), |
| 530 | .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), | 530 | .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE), |
| 531 | .preemtive = true, | 531 | .preemtive = true, |
| 532 | }; | 532 | }; |
| 533 | return new_area; | 533 | return new_area; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 536 | void RasterizerOpenGL::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 537 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 537 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 538 | if (addr == 0 || size == 0) { | 538 | if (addr == 0 || size == 0) { |
| 539 | return; | 539 | return; |
| @@ -554,7 +554,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache | |||
| 554 | } | 554 | } |
| 555 | } | 555 | } |
| 556 | 556 | ||
| 557 | bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { | 557 | bool RasterizerOpenGL::OnCPUWrite(DAddr addr, u64 size) { |
| 558 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 558 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 559 | if (addr == 0 || size == 0) { | 559 | if (addr == 0 || size == 0) { |
| 560 | return false; | 560 | return false; |
| @@ -576,8 +576,9 @@ bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { | |||
| 576 | return false; | 576 | return false; |
| 577 | } | 577 | } |
| 578 | 578 | ||
| 579 | void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) { | 579 | void RasterizerOpenGL::OnCacheInvalidation(DAddr addr, u64 size) { |
| 580 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); | 580 | MICROPROFILE_SCOPE(OpenGL_CacheManagement); |
| 581 | |||
| 581 | if (addr == 0 || size == 0) { | 582 | if (addr == 0 || size == 0) { |
| 582 | return; | 583 | return; |
| 583 | } | 584 | } |
| @@ -596,7 +597,7 @@ void RasterizerOpenGL::InvalidateGPUCache() { | |||
| 596 | gpu.InvalidateGPUCache(); | 597 | gpu.InvalidateGPUCache(); |
| 597 | } | 598 | } |
| 598 | 599 | ||
| 599 | void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) { | 600 | void RasterizerOpenGL::UnmapMemory(DAddr addr, u64 size) { |
| 600 | { | 601 | { |
| 601 | std::scoped_lock lock{texture_cache.mutex}; | 602 | std::scoped_lock lock{texture_cache.mutex}; |
| 602 | texture_cache.UnmapMemory(addr, size); | 603 | texture_cache.UnmapMemory(addr, size); |
| @@ -635,7 +636,7 @@ void RasterizerOpenGL::ReleaseFences(bool force) { | |||
| 635 | fence_manager.WaitPendingFences(force); | 636 | fence_manager.WaitPendingFences(force); |
| 636 | } | 637 | } |
| 637 | 638 | ||
| 638 | void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size, | 639 | void RasterizerOpenGL::FlushAndInvalidateRegion(DAddr addr, u64 size, |
| 639 | VideoCommon::CacheType which) { | 640 | VideoCommon::CacheType which) { |
| 640 | if (Settings::IsGPULevelExtreme()) { | 641 | if (Settings::IsGPULevelExtreme()) { |
| 641 | FlushRegion(addr, size, which); | 642 | FlushRegion(addr, size, which); |
| @@ -739,7 +740,7 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si | |||
| 739 | } | 740 | } |
| 740 | 741 | ||
| 741 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 742 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 742 | VAddr framebuffer_addr, u32 pixel_stride) { | 743 | DAddr framebuffer_addr, u32 pixel_stride) { |
| 743 | if (framebuffer_addr == 0) { | 744 | if (framebuffer_addr == 0) { |
| 744 | return false; | 745 | return false; |
| 745 | } | 746 | } |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index ce3460938..34aa73526 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "video_core/control/channel_state_cache.h" | 15 | #include "video_core/control/channel_state_cache.h" |
| 16 | #include "video_core/engines/maxwell_dma.h" | 16 | #include "video_core/engines/maxwell_dma.h" |
| 17 | #include "video_core/rasterizer_accelerated.h" | ||
| 18 | #include "video_core/rasterizer_interface.h" | 17 | #include "video_core/rasterizer_interface.h" |
| 19 | #include "video_core/renderer_opengl/blit_image.h" | 18 | #include "video_core/renderer_opengl/blit_image.h" |
| 20 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 19 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| @@ -72,13 +71,13 @@ private: | |||
| 72 | TextureCache& texture_cache; | 71 | TextureCache& texture_cache; |
| 73 | }; | 72 | }; |
| 74 | 73 | ||
| 75 | class RasterizerOpenGL : public VideoCore::RasterizerAccelerated, | 74 | class RasterizerOpenGL : public VideoCore::RasterizerInterface, |
| 76 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | 75 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { |
| 77 | public: | 76 | public: |
| 78 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 77 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 79 | Core::Memory::Memory& cpu_memory_, const Device& device_, | 78 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 80 | ScreenInfo& screen_info_, ProgramManager& program_manager_, | 79 | const Device& device_, ScreenInfo& screen_info_, |
| 81 | StateTracker& state_tracker_); | 80 | ProgramManager& program_manager_, StateTracker& state_tracker_); |
| 82 | ~RasterizerOpenGL() override; | 81 | ~RasterizerOpenGL() override; |
| 83 | 82 | ||
| 84 | void Draw(bool is_indexed, u32 instance_count) override; | 83 | void Draw(bool is_indexed, u32 instance_count) override; |
| @@ -92,17 +91,17 @@ public: | |||
| 92 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; | 91 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; |
| 93 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; | 92 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; |
| 94 | void FlushAll() override; | 93 | void FlushAll() override; |
| 95 | void FlushRegion(VAddr addr, u64 size, | 94 | void FlushRegion(DAddr addr, u64 size, |
| 96 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 95 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 97 | bool MustFlushRegion(VAddr addr, u64 size, | 96 | bool MustFlushRegion(DAddr addr, u64 size, |
| 98 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 97 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 99 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; | 98 | VideoCore::RasterizerDownloadArea GetFlushArea(PAddr addr, u64 size) override; |
| 100 | void InvalidateRegion(VAddr addr, u64 size, | 99 | void InvalidateRegion(DAddr addr, u64 size, |
| 101 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 102 | void OnCacheInvalidation(VAddr addr, u64 size) override; | 101 | void OnCacheInvalidation(PAddr addr, u64 size) override; |
| 103 | bool OnCPUWrite(VAddr addr, u64 size) override; | 102 | bool OnCPUWrite(PAddr addr, u64 size) override; |
| 104 | void InvalidateGPUCache() override; | 103 | void InvalidateGPUCache() override; |
| 105 | void UnmapMemory(VAddr addr, u64 size) override; | 104 | void UnmapMemory(DAddr addr, u64 size) override; |
| 106 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | 105 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
| 107 | void SignalFence(std::function<void()>&& func) override; | 106 | void SignalFence(std::function<void()>&& func) override; |
| 108 | void SyncOperation(std::function<void()>&& func) override; | 107 | void SyncOperation(std::function<void()>&& func) override; |
| @@ -110,7 +109,7 @@ public: | |||
| 110 | void SignalReference() override; | 109 | void SignalReference() override; |
| 111 | void ReleaseFences(bool force = true) override; | 110 | void ReleaseFences(bool force = true) override; |
| 112 | void FlushAndInvalidateRegion( | 111 | void FlushAndInvalidateRegion( |
| 113 | VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 112 | DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 114 | void WaitForIdle() override; | 113 | void WaitForIdle() override; |
| 115 | void FragmentBarrier() override; | 114 | void FragmentBarrier() override; |
| 116 | void TiledCacheBarrier() override; | 115 | void TiledCacheBarrier() override; |
| @@ -123,7 +122,7 @@ public: | |||
| 123 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | 122 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; |
| 124 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 123 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 125 | std::span<const u8> memory) override; | 124 | std::span<const u8> memory) override; |
| 126 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 125 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, |
| 127 | u32 pixel_stride) override; | 126 | u32 pixel_stride) override; |
| 128 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 127 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 129 | const VideoCore::DiskResourceLoadCallback& callback) override; | 128 | const VideoCore::DiskResourceLoadCallback& callback) override; |
| @@ -235,6 +234,7 @@ private: | |||
| 235 | VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport); | 234 | VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport); |
| 236 | 235 | ||
| 237 | Tegra::GPU& gpu; | 236 | Tegra::GPU& gpu; |
| 237 | Tegra::MaxwellDeviceMemoryManager& device_memory; | ||
| 238 | 238 | ||
| 239 | const Device& device; | 239 | const Device& device; |
| 240 | ScreenInfo& screen_info; | 240 | ScreenInfo& screen_info; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 30df41b7d..50462cdde 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -168,11 +168,12 @@ void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs | |||
| 168 | } | 168 | } |
| 169 | } // Anonymous namespace | 169 | } // Anonymous namespace |
| 170 | 170 | ||
| 171 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 171 | ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 172 | const Device& device_, TextureCache& texture_cache_, | 172 | Core::Frontend::EmuWindow& emu_window_, const Device& device_, |
| 173 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 173 | TextureCache& texture_cache_, BufferCache& buffer_cache_, |
| 174 | StateTracker& state_tracker_, VideoCore::ShaderNotify& shader_notify_) | 174 | ProgramManager& program_manager_, StateTracker& state_tracker_, |
| 175 | : VideoCommon::ShaderCache{rasterizer_}, emu_window{emu_window_}, device{device_}, | 175 | VideoCore::ShaderNotify& shader_notify_) |
| 176 | : VideoCommon::ShaderCache{device_memory_}, emu_window{emu_window_}, device{device_}, | ||
| 176 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, | 177 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, |
| 177 | state_tracker{state_tracker_}, shader_notify{shader_notify_}, | 178 | state_tracker{state_tracker_}, shader_notify{shader_notify_}, |
| 178 | use_asynchronous_shaders{device.UseAsynchronousShaders()}, | 179 | use_asynchronous_shaders{device.UseAsynchronousShaders()}, |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 6b9732fca..5ac413529 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | namespace Tegra { | 18 | namespace Tegra { |
| 19 | class MemoryManager; | 19 | class MemoryManager; |
| 20 | } | 20 | } // namespace Tegra |
| 21 | 21 | ||
| 22 | namespace OpenGL { | 22 | namespace OpenGL { |
| 23 | 23 | ||
| @@ -28,10 +28,11 @@ using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>; | |||
| 28 | 28 | ||
| 29 | class ShaderCache : public VideoCommon::ShaderCache { | 29 | class ShaderCache : public VideoCommon::ShaderCache { |
| 30 | public: | 30 | public: |
| 31 | explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 31 | explicit ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 32 | const Device& device_, TextureCache& texture_cache_, | 32 | Core::Frontend::EmuWindow& emu_window_, const Device& device_, |
| 33 | BufferCache& buffer_cache_, ProgramManager& program_manager_, | 33 | TextureCache& texture_cache_, BufferCache& buffer_cache_, |
| 34 | StateTracker& state_tracker_, VideoCore::ShaderNotify& shader_notify_); | 34 | ProgramManager& program_manager_, StateTracker& state_tracker_, |
| 35 | VideoCore::ShaderNotify& shader_notify_); | ||
| 35 | ~ShaderCache(); | 36 | ~ShaderCache(); |
| 36 | 37 | ||
| 37 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 38 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 2933718b6..b75376fdb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include "common/telemetry.h" | 15 | #include "common/telemetry.h" |
| 16 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 17 | #include "core/frontend/emu_window.h" | 17 | #include "core/frontend/emu_window.h" |
| 18 | #include "core/memory.h" | ||
| 19 | #include "core/telemetry_session.h" | 18 | #include "core/telemetry_session.h" |
| 20 | #include "video_core/host_shaders/ffx_a_h.h" | 19 | #include "video_core/host_shaders/ffx_a_h.h" |
| 21 | #include "video_core/host_shaders/ffx_fsr1_h.h" | 20 | #include "video_core/host_shaders/ffx_fsr1_h.h" |
| @@ -144,12 +143,13 @@ void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severit | |||
| 144 | 143 | ||
| 145 | RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | 144 | RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, |
| 146 | Core::Frontend::EmuWindow& emu_window_, | 145 | Core::Frontend::EmuWindow& emu_window_, |
| 147 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 146 | Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, |
| 148 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 147 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 149 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, | 148 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, |
| 150 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, device{emu_window_}, | 149 | emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_}, |
| 151 | state_tracker{}, program_manager{device}, | 150 | state_tracker{}, program_manager{device}, |
| 152 | rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { | 151 | rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager, |
| 152 | state_tracker) { | ||
| 153 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | 153 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { |
| 154 | glEnable(GL_DEBUG_OUTPUT); | 154 | glEnable(GL_DEBUG_OUTPUT); |
| 155 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | 155 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); |
| @@ -242,7 +242,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf | |||
| 242 | const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; | 242 | const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; |
| 243 | const u64 size_in_bytes{Tegra::Texture::CalculateSize( | 243 | const u64 size_in_bytes{Tegra::Texture::CalculateSize( |
| 244 | true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; | 244 | true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; |
| 245 | const u8* const host_ptr{cpu_memory.GetPointer(framebuffer_addr)}; | 245 | const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)}; |
| 246 | const std::span<const u8> input_data(host_ptr, size_in_bytes); | 246 | const std::span<const u8> input_data(host_ptr, size_in_bytes); |
| 247 | Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, | 247 | Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, |
| 248 | framebuffer.width, framebuffer.height, 1, block_height_log2, | 248 | framebuffer.width, framebuffer.height, 1, block_height_log2, |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index b70607635..18699610a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -61,7 +61,7 @@ class RendererOpenGL final : public VideoCore::RendererBase { | |||
| 61 | public: | 61 | public: |
| 62 | explicit RendererOpenGL(Core::TelemetrySession& telemetry_session_, | 62 | explicit RendererOpenGL(Core::TelemetrySession& telemetry_session_, |
| 63 | Core::Frontend::EmuWindow& emu_window_, | 63 | Core::Frontend::EmuWindow& emu_window_, |
| 64 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 64 | Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, |
| 65 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); | 65 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); |
| 66 | ~RendererOpenGL() override; | 66 | ~RendererOpenGL() override; |
| 67 | 67 | ||
| @@ -101,7 +101,7 @@ private: | |||
| 101 | 101 | ||
| 102 | Core::TelemetrySession& telemetry_session; | 102 | Core::TelemetrySession& telemetry_session; |
| 103 | Core::Frontend::EmuWindow& emu_window; | 103 | Core::Frontend::EmuWindow& emu_window; |
| 104 | Core::Memory::Memory& cpu_memory; | 104 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 105 | Tegra::GPU& gpu; | 105 | Tegra::GPU& gpu; |
| 106 | 106 | ||
| 107 | Device device; | 107 | Device device; |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index 71c783709..850c34a3a 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include "shader_recompiler/shader_info.h" | 12 | #include "shader_recompiler/shader_info.h" |
| 13 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 13 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 14 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 14 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 15 | #include "video_core/texture_cache/texture_cache.h" | ||
| 16 | #include "video_core/texture_cache/types.h" | 15 | #include "video_core/texture_cache/types.h" |
| 17 | #include "video_core/vulkan_common/vulkan_device.h" | 16 | #include "video_core/vulkan_common/vulkan_device.h" |
| 18 | 17 | ||
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 100b70918..1631276c6 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -82,10 +82,10 @@ Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dl | |||
| 82 | 82 | ||
| 83 | RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | 83 | RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, |
| 84 | Core::Frontend::EmuWindow& emu_window, | 84 | Core::Frontend::EmuWindow& emu_window, |
| 85 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 85 | Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, |
| 86 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) try | 86 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) try |
| 87 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), | 87 | : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), |
| 88 | cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), | 88 | device_memory(device_memory_), gpu(gpu_), library(OpenLibrary(context.get())), |
| 89 | instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | 89 | instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, |
| 90 | Settings::values.renderer_debug.GetValue())), | 90 | Settings::values.renderer_debug.GetValue())), |
| 91 | debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance) | 91 | debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance) |
| @@ -97,9 +97,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 97 | render_window.GetFramebufferLayout().height), | 97 | render_window.GetFramebufferLayout().height), |
| 98 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, | 98 | present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, |
| 99 | surface), | 99 | surface), |
| 100 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, | 100 | blit_screen(device_memory, render_window, device, memory_allocator, swapchain, |
| 101 | scheduler, screen_info), | 101 | present_manager, scheduler, screen_info), |
| 102 | rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, | 102 | rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator, |
| 103 | state_tracker, scheduler) { | 103 | state_tracker, scheduler) { |
| 104 | if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { | 104 | if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { |
| 105 | turbo_mode.emplace(instance, dld); | 105 | turbo_mode.emplace(instance, dld); |
| @@ -128,7 +128,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 128 | screen_info.width = framebuffer->width; | 128 | screen_info.width = framebuffer->width; |
| 129 | screen_info.height = framebuffer->height; | 129 | screen_info.height = framebuffer->height; |
| 130 | 130 | ||
| 131 | const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; | 131 | const DAddr framebuffer_addr = framebuffer->address + framebuffer->offset; |
| 132 | const bool use_accelerated = | 132 | const bool use_accelerated = |
| 133 | rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); | 133 | rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); |
| 134 | RenderScreenshot(*framebuffer, use_accelerated); | 134 | RenderScreenshot(*framebuffer, use_accelerated); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 14e257cf7..11c52287a 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -7,12 +7,12 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <variant> | 8 | #include <variant> |
| 9 | 9 | ||
| 10 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 11 | |||
| 12 | #include "common/dynamic_library.h" | 10 | #include "common/dynamic_library.h" |
| 11 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 13 | #include "video_core/renderer_base.h" | 12 | #include "video_core/renderer_base.h" |
| 14 | #include "video_core/renderer_vulkan/vk_blit_screen.h" | 13 | #include "video_core/renderer_vulkan/vk_blit_screen.h" |
| 15 | #include "video_core/renderer_vulkan/vk_present_manager.h" | 14 | #include "video_core/renderer_vulkan/vk_present_manager.h" |
| 15 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 16 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 16 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 17 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | 17 | #include "video_core/renderer_vulkan/vk_state_tracker.h" |
| 18 | #include "video_core/renderer_vulkan/vk_swapchain.h" | 18 | #include "video_core/renderer_vulkan/vk_swapchain.h" |
| @@ -42,7 +42,7 @@ class RendererVulkan final : public VideoCore::RendererBase { | |||
| 42 | public: | 42 | public: |
| 43 | explicit RendererVulkan(Core::TelemetrySession& telemtry_session, | 43 | explicit RendererVulkan(Core::TelemetrySession& telemtry_session, |
| 44 | Core::Frontend::EmuWindow& emu_window, | 44 | Core::Frontend::EmuWindow& emu_window, |
| 45 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 45 | Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_, |
| 46 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); | 46 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); |
| 47 | ~RendererVulkan() override; | 47 | ~RendererVulkan() override; |
| 48 | 48 | ||
| @@ -62,7 +62,7 @@ private: | |||
| 62 | void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated); | 62 | void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated); |
| 63 | 63 | ||
| 64 | Core::TelemetrySession& telemetry_session; | 64 | Core::TelemetrySession& telemetry_session; |
| 65 | Core::Memory::Memory& cpu_memory; | 65 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 66 | Tegra::GPU& gpu; | 66 | Tegra::GPU& gpu; |
| 67 | 67 | ||
| 68 | std::shared_ptr<Common::DynamicLibrary> library; | 68 | std::shared_ptr<Common::DynamicLibrary> library; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 60432f5ad..610f27c84 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -14,8 +14,8 @@ | |||
| 14 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/frontend/emu_window.h" | 16 | #include "core/frontend/emu_window.h" |
| 17 | #include "core/memory.h" | ||
| 18 | #include "video_core/gpu.h" | 17 | #include "video_core/gpu.h" |
| 18 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 19 | #include "video_core/host_shaders/fxaa_frag_spv.h" | 19 | #include "video_core/host_shaders/fxaa_frag_spv.h" |
| 20 | #include "video_core/host_shaders/fxaa_vert_spv.h" | 20 | #include "video_core/host_shaders/fxaa_vert_spv.h" |
| 21 | #include "video_core/host_shaders/present_bicubic_frag_spv.h" | 21 | #include "video_core/host_shaders/present_bicubic_frag_spv.h" |
| @@ -121,11 +121,12 @@ struct BlitScreen::BufferData { | |||
| 121 | // Unaligned image data goes here | 121 | // Unaligned image data goes here |
| 122 | }; | 122 | }; |
| 123 | 123 | ||
| 124 | BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWindow& render_window_, | 124 | BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 125 | const Device& device_, MemoryAllocator& memory_allocator_, | 125 | Core::Frontend::EmuWindow& render_window_, const Device& device_, |
| 126 | Swapchain& swapchain_, PresentManager& present_manager_, | 126 | MemoryAllocator& memory_allocator_, Swapchain& swapchain_, |
| 127 | Scheduler& scheduler_, const ScreenInfo& screen_info_) | 127 | PresentManager& present_manager_, Scheduler& scheduler_, |
| 128 | : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_}, | 128 | const ScreenInfo& screen_info_) |
| 129 | : device_memory{device_memory_}, render_window{render_window_}, device{device_}, | ||
| 129 | memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, | 130 | memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, |
| 130 | scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { | 131 | scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { |
| 131 | resource_ticks.resize(image_count); | 132 | resource_ticks.resize(image_count); |
| @@ -219,8 +220,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, | |||
| 219 | if (!use_accelerated) { | 220 | if (!use_accelerated) { |
| 220 | const u64 image_offset = GetRawImageOffset(framebuffer); | 221 | const u64 image_offset = GetRawImageOffset(framebuffer); |
| 221 | 222 | ||
| 222 | const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; | 223 | const DAddr framebuffer_addr = framebuffer.address + framebuffer.offset; |
| 223 | const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); | 224 | const u8* const host_ptr = device_memory.GetPointer<u8>(framebuffer_addr); |
| 224 | 225 | ||
| 225 | // TODO(Rodrigo): Read this from HLE | 226 | // TODO(Rodrigo): Read this from HLE |
| 226 | constexpr u32 block_height_log2 = 4; | 227 | constexpr u32 block_height_log2 = 4; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index 78b32416d..3eff76009 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | 7 | ||
| 8 | #include "core/frontend/framebuffer_layout.h" | 8 | #include "core/frontend/framebuffer_layout.h" |
| 9 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 9 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 10 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 11 | 12 | ||
| @@ -13,10 +14,6 @@ namespace Core { | |||
| 13 | class System; | 14 | class System; |
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | namespace Core::Memory { | ||
| 17 | class Memory; | ||
| 18 | } | ||
| 19 | |||
| 20 | namespace Core::Frontend { | 17 | namespace Core::Frontend { |
| 21 | class EmuWindow; | 18 | class EmuWindow; |
| 22 | } | 19 | } |
| @@ -56,8 +53,9 @@ struct ScreenInfo { | |||
| 56 | 53 | ||
| 57 | class BlitScreen { | 54 | class BlitScreen { |
| 58 | public: | 55 | public: |
| 59 | explicit BlitScreen(Core::Memory::Memory& cpu_memory, Core::Frontend::EmuWindow& render_window, | 56 | explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory, |
| 60 | const Device& device, MemoryAllocator& memory_manager, Swapchain& swapchain, | 57 | Core::Frontend::EmuWindow& render_window, const Device& device, |
| 58 | MemoryAllocator& memory_manager, Swapchain& swapchain, | ||
| 61 | PresentManager& present_manager, Scheduler& scheduler, | 59 | PresentManager& present_manager, Scheduler& scheduler, |
| 62 | const ScreenInfo& screen_info); | 60 | const ScreenInfo& screen_info); |
| 63 | ~BlitScreen(); | 61 | ~BlitScreen(); |
| @@ -109,7 +107,7 @@ private: | |||
| 109 | u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; | 107 | u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; |
| 110 | u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer) const; | 108 | u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer) const; |
| 111 | 109 | ||
| 112 | Core::Memory::Memory& cpu_memory; | 110 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 113 | Core::Frontend::EmuWindow& render_window; | 111 | Core::Frontend::EmuWindow& render_window; |
| 114 | const Device& device; | 112 | const Device& device; |
| 115 | MemoryAllocator& memory_allocator; | 113 | MemoryAllocator& memory_allocator; |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 3c61799fa..31001d142 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -79,7 +79,7 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo | |||
| 79 | } // Anonymous namespace | 79 | } // Anonymous namespace |
| 80 | 80 | ||
| 81 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_params) | 81 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_params) |
| 82 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params), tracker{4096} { | 82 | : VideoCommon::BufferBase(null_params), tracker{4096} { |
| 83 | if (runtime.device.HasNullDescriptor()) { | 83 | if (runtime.device.HasNullDescriptor()) { |
| 84 | return; | 84 | return; |
| 85 | } | 85 | } |
| @@ -88,11 +88,9 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_p | |||
| 88 | is_null = true; | 88 | is_null = true; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 91 | Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_) |
| 92 | VAddr cpu_addr_, u64 size_bytes_) | 92 | : VideoCommon::BufferBase(cpu_addr_, size_bytes_), device{&runtime.device}, |
| 93 | : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_), | 93 | buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())}, tracker{SizeBytes()} { |
| 94 | device{&runtime.device}, buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())}, | ||
| 95 | tracker{SizeBytes()} { | ||
| 96 | if (runtime.device.HasDebuggingToolAttached()) { | 94 | if (runtime.device.HasDebuggingToolAttached()) { |
| 97 | buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); | 95 | buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); |
| 98 | } | 96 | } |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index dc300d7cb..e273f4988 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -23,11 +23,10 @@ struct HostVertexBinding; | |||
| 23 | 23 | ||
| 24 | class BufferCacheRuntime; | 24 | class BufferCacheRuntime; |
| 25 | 25 | ||
| 26 | class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> { | 26 | class Buffer : public VideoCommon::BufferBase { |
| 27 | public: | 27 | public: |
| 28 | explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params); | 28 | explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params); |
| 29 | explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, | 29 | explicit Buffer(BufferCacheRuntime& runtime, VAddr cpu_addr_, u64 size_bytes_); |
| 30 | VAddr cpu_addr_, u64 size_bytes_); | ||
| 31 | 30 | ||
| 32 | [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format); | 31 | [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format); |
| 33 | 32 | ||
| @@ -173,7 +172,7 @@ struct BufferCacheParams { | |||
| 173 | using Runtime = Vulkan::BufferCacheRuntime; | 172 | using Runtime = Vulkan::BufferCacheRuntime; |
| 174 | using Buffer = Vulkan::Buffer; | 173 | using Buffer = Vulkan::Buffer; |
| 175 | using Async_Buffer = Vulkan::StagingBufferRef; | 174 | using Async_Buffer = Vulkan::StagingBufferRef; |
| 176 | using MemoryTracker = VideoCommon::MemoryTrackerBase<VideoCore::RasterizerInterface>; | 175 | using MemoryTracker = VideoCommon::MemoryTrackerBase<Tegra::MaxwellDeviceMemoryManager>; |
| 177 | 176 | ||
| 178 | static constexpr bool IS_OPENGL = false; | 177 | static constexpr bool IS_OPENGL = false; |
| 179 | static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = false; | 178 | static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = false; |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index f2fd2670f..ec6b3a4b0 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 19 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 20 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 20 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 21 | #include "video_core/shader_notify.h" | 21 | #include "video_core/shader_notify.h" |
| 22 | #include "video_core/texture_cache/texture_cache.h" | ||
| 22 | #include "video_core/vulkan_common/vulkan_device.h" | 23 | #include "video_core/vulkan_common/vulkan_device.h" |
| 23 | 24 | ||
| 24 | #if defined(_MSC_VER) && defined(NDEBUG) | 25 | #if defined(_MSC_VER) && defined(NDEBUG) |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d1841198d..1e1821b10 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | 30 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" |
| 31 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 31 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 32 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 32 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| 33 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 34 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 33 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 35 | #include "video_core/renderer_vulkan/vk_shader_util.h" | 34 | #include "video_core/renderer_vulkan/vk_shader_util.h" |
| 36 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 35 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| @@ -299,12 +298,13 @@ bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) c | |||
| 299 | return std::memcmp(&rhs, this, Size()) == 0; | 298 | return std::memcmp(&rhs, this, Size()) == 0; |
| 300 | } | 299 | } |
| 301 | 300 | ||
| 302 | PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device_, | 301 | PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 303 | Scheduler& scheduler_, DescriptorPool& descriptor_pool_, | 302 | const Device& device_, Scheduler& scheduler_, |
| 303 | DescriptorPool& descriptor_pool_, | ||
| 304 | GuestDescriptorQueue& guest_descriptor_queue_, | 304 | GuestDescriptorQueue& guest_descriptor_queue_, |
| 305 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, | 305 | RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, |
| 306 | TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) | 306 | TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) |
| 307 | : VideoCommon::ShaderCache{rasterizer_}, device{device_}, scheduler{scheduler_}, | 307 | : VideoCommon::ShaderCache{device_memory_}, device{device_}, scheduler{scheduler_}, |
| 308 | descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, | 308 | descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, |
| 309 | render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, | 309 | render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, |
| 310 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, | 310 | texture_cache{texture_cache_}, shader_notify{shader_notify_}, |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index e323ea0fd..797700128 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include "shader_recompiler/object_pool.h" | 20 | #include "shader_recompiler/object_pool.h" |
| 21 | #include "shader_recompiler/profile.h" | 21 | #include "shader_recompiler/profile.h" |
| 22 | #include "video_core/engines/maxwell_3d.h" | 22 | #include "video_core/engines/maxwell_3d.h" |
| 23 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 23 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 24 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 24 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 25 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 25 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" | 26 | #include "video_core/renderer_vulkan/vk_compute_pipeline.h" |
| @@ -79,7 +80,6 @@ class ComputePipeline; | |||
| 79 | class DescriptorPool; | 80 | class DescriptorPool; |
| 80 | class Device; | 81 | class Device; |
| 81 | class PipelineStatistics; | 82 | class PipelineStatistics; |
| 82 | class RasterizerVulkan; | ||
| 83 | class RenderPassCache; | 83 | class RenderPassCache; |
| 84 | class Scheduler; | 84 | class Scheduler; |
| 85 | 85 | ||
| @@ -99,8 +99,8 @@ struct ShaderPools { | |||
| 99 | 99 | ||
| 100 | class PipelineCache : public VideoCommon::ShaderCache { | 100 | class PipelineCache : public VideoCommon::ShaderCache { |
| 101 | public: | 101 | public: |
| 102 | explicit PipelineCache(RasterizerVulkan& rasterizer, const Device& device, Scheduler& scheduler, | 102 | explicit PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device, |
| 103 | DescriptorPool& descriptor_pool, | 103 | Scheduler& scheduler, DescriptorPool& descriptor_pool, |
| 104 | GuestDescriptorQueue& guest_descriptor_queue, | 104 | GuestDescriptorQueue& guest_descriptor_queue, |
| 105 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, | 105 | RenderPassCache& render_pass_cache, BufferCache& buffer_cache, |
| 106 | TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); | 106 | TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index 792ed9615..5e7518d96 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp | |||
| @@ -329,7 +329,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) { | |||
| 329 | // to account for that. | 329 | // to account for that. |
| 330 | const bool is_suboptimal = swapchain.NeedsRecreation(); | 330 | const bool is_suboptimal = swapchain.NeedsRecreation(); |
| 331 | const bool size_changed = | 331 | const bool size_changed = |
| 332 | swapchain.GetWidth() < frame->width || swapchain.GetHeight() < frame->height; | 332 | swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height; |
| 333 | if (is_suboptimal || size_changed) { | 333 | if (is_suboptimal || size_changed) { |
| 334 | RecreateSwapchain(frame); | 334 | RecreateSwapchain(frame); |
| 335 | } | 335 | } |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index ad4caf688..7cbc9c73c 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -13,9 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | #include "common/bit_util.h" | 14 | #include "common/bit_util.h" |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "core/memory.h" | ||
| 17 | #include "video_core/engines/draw_manager.h" | 16 | #include "video_core/engines/draw_manager.h" |
| 17 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 18 | #include "video_core/query_cache/query_cache.h" | 18 | #include "video_core/query_cache/query_cache.h" |
| 19 | #include "video_core/rasterizer_interface.h" | ||
| 19 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 20 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 20 | #include "video_core/renderer_vulkan/vk_compute_pass.h" | 21 | #include "video_core/renderer_vulkan/vk_compute_pass.h" |
| 21 | #include "video_core/renderer_vulkan/vk_query_cache.h" | 22 | #include "video_core/renderer_vulkan/vk_query_cache.h" |
| @@ -102,7 +103,7 @@ private: | |||
| 102 | using BaseStreamer = VideoCommon::SimpleStreamer<VideoCommon::HostQueryBase>; | 103 | using BaseStreamer = VideoCommon::SimpleStreamer<VideoCommon::HostQueryBase>; |
| 103 | 104 | ||
| 104 | struct HostSyncValues { | 105 | struct HostSyncValues { |
| 105 | VAddr address; | 106 | DAddr address; |
| 106 | size_t size; | 107 | size_t size; |
| 107 | size_t offset; | 108 | size_t offset; |
| 108 | 109 | ||
| @@ -317,7 +318,7 @@ public: | |||
| 317 | pending_sync.clear(); | 318 | pending_sync.clear(); |
| 318 | } | 319 | } |
| 319 | 320 | ||
| 320 | size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, | 321 | size_t WriteCounter(DAddr address, bool has_timestamp, u32 value, |
| 321 | [[maybe_unused]] std::optional<u32> subreport) override { | 322 | [[maybe_unused]] std::optional<u32> subreport) override { |
| 322 | PauseCounter(); | 323 | PauseCounter(); |
| 323 | auto index = BuildQuery(); | 324 | auto index = BuildQuery(); |
| @@ -738,7 +739,7 @@ public: | |||
| 738 | pending_sync.clear(); | 739 | pending_sync.clear(); |
| 739 | } | 740 | } |
| 740 | 741 | ||
| 741 | size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, | 742 | size_t WriteCounter(DAddr address, bool has_timestamp, u32 value, |
| 742 | std::optional<u32> subreport_) override { | 743 | std::optional<u32> subreport_) override { |
| 743 | auto index = BuildQuery(); | 744 | auto index = BuildQuery(); |
| 744 | auto* new_query = GetQuery(index); | 745 | auto* new_query = GetQuery(index); |
| @@ -769,9 +770,9 @@ public: | |||
| 769 | return index; | 770 | return index; |
| 770 | } | 771 | } |
| 771 | 772 | ||
| 772 | std::optional<std::pair<VAddr, size_t>> GetLastQueryStream(size_t stream) { | 773 | std::optional<std::pair<DAddr, size_t>> GetLastQueryStream(size_t stream) { |
| 773 | if (last_queries[stream] != 0) { | 774 | if (last_queries[stream] != 0) { |
| 774 | std::pair<VAddr, size_t> result(last_queries[stream], last_queries_stride[stream]); | 775 | std::pair<DAddr, size_t> result(last_queries[stream], last_queries_stride[stream]); |
| 775 | return result; | 776 | return result; |
| 776 | } | 777 | } |
| 777 | return std::nullopt; | 778 | return std::nullopt; |
| @@ -974,7 +975,7 @@ private: | |||
| 974 | size_t buffers_count{}; | 975 | size_t buffers_count{}; |
| 975 | std::array<VkBuffer, NUM_STREAMS> counter_buffers{}; | 976 | std::array<VkBuffer, NUM_STREAMS> counter_buffers{}; |
| 976 | std::array<VkDeviceSize, NUM_STREAMS> offsets{}; | 977 | std::array<VkDeviceSize, NUM_STREAMS> offsets{}; |
| 977 | std::array<VAddr, NUM_STREAMS> last_queries; | 978 | std::array<DAddr, NUM_STREAMS> last_queries; |
| 978 | std::array<size_t, NUM_STREAMS> last_queries_stride; | 979 | std::array<size_t, NUM_STREAMS> last_queries_stride; |
| 979 | Maxwell3D::Regs::PrimitiveTopology out_topology; | 980 | Maxwell3D::Regs::PrimitiveTopology out_topology; |
| 980 | u64 streams_mask; | 981 | u64 streams_mask; |
| @@ -987,7 +988,7 @@ public: | |||
| 987 | : VideoCommon::QueryBase(0, VideoCommon::QueryFlagBits::IsHostManaged, 0) {} | 988 | : VideoCommon::QueryBase(0, VideoCommon::QueryFlagBits::IsHostManaged, 0) {} |
| 988 | 989 | ||
| 989 | // Parameterized constructor | 990 | // Parameterized constructor |
| 990 | PrimitivesQueryBase(bool has_timestamp, VAddr address) | 991 | PrimitivesQueryBase(bool has_timestamp, DAddr address) |
| 991 | : VideoCommon::QueryBase(address, VideoCommon::QueryFlagBits::IsHostManaged, 0) { | 992 | : VideoCommon::QueryBase(address, VideoCommon::QueryFlagBits::IsHostManaged, 0) { |
| 992 | if (has_timestamp) { | 993 | if (has_timestamp) { |
| 993 | flags |= VideoCommon::QueryFlagBits::HasTimestamp; | 994 | flags |= VideoCommon::QueryFlagBits::HasTimestamp; |
| @@ -995,7 +996,7 @@ public: | |||
| 995 | } | 996 | } |
| 996 | 997 | ||
| 997 | u64 stride{}; | 998 | u64 stride{}; |
| 998 | VAddr dependant_address{}; | 999 | DAddr dependant_address{}; |
| 999 | Maxwell3D::Regs::PrimitiveTopology topology{Maxwell3D::Regs::PrimitiveTopology::Points}; | 1000 | Maxwell3D::Regs::PrimitiveTopology topology{Maxwell3D::Regs::PrimitiveTopology::Points}; |
| 1000 | size_t dependant_index{}; | 1001 | size_t dependant_index{}; |
| 1001 | bool dependant_manage{}; | 1002 | bool dependant_manage{}; |
| @@ -1005,15 +1006,15 @@ class PrimitivesSucceededStreamer : public VideoCommon::SimpleStreamer<Primitive | |||
| 1005 | public: | 1006 | public: |
| 1006 | explicit PrimitivesSucceededStreamer(size_t id_, QueryCacheRuntime& runtime_, | 1007 | explicit PrimitivesSucceededStreamer(size_t id_, QueryCacheRuntime& runtime_, |
| 1007 | TFBCounterStreamer& tfb_streamer_, | 1008 | TFBCounterStreamer& tfb_streamer_, |
| 1008 | Core::Memory::Memory& cpu_memory_) | 1009 | Tegra::MaxwellDeviceMemoryManager& device_memory_) |
| 1009 | : VideoCommon::SimpleStreamer<PrimitivesQueryBase>(id_), runtime{runtime_}, | 1010 | : VideoCommon::SimpleStreamer<PrimitivesQueryBase>(id_), runtime{runtime_}, |
| 1010 | tfb_streamer{tfb_streamer_}, cpu_memory{cpu_memory_} { | 1011 | tfb_streamer{tfb_streamer_}, device_memory{device_memory_} { |
| 1011 | MakeDependent(&tfb_streamer); | 1012 | MakeDependent(&tfb_streamer); |
| 1012 | } | 1013 | } |
| 1013 | 1014 | ||
| 1014 | ~PrimitivesSucceededStreamer() = default; | 1015 | ~PrimitivesSucceededStreamer() = default; |
| 1015 | 1016 | ||
| 1016 | size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, | 1017 | size_t WriteCounter(DAddr address, bool has_timestamp, u32 value, |
| 1017 | std::optional<u32> subreport_) override { | 1018 | std::optional<u32> subreport_) override { |
| 1018 | auto index = BuildQuery(); | 1019 | auto index = BuildQuery(); |
| 1019 | auto* new_query = GetQuery(index); | 1020 | auto* new_query = GetQuery(index); |
| @@ -1063,6 +1064,8 @@ public: | |||
| 1063 | } | 1064 | } |
| 1064 | }); | 1065 | }); |
| 1065 | } | 1066 | } |
| 1067 | auto* ptr = device_memory.GetPointer<u8>(new_query->dependant_address); | ||
| 1068 | ASSERT(ptr != nullptr); | ||
| 1066 | 1069 | ||
| 1067 | new_query->dependant_manage = must_manage_dependance; | 1070 | new_query->dependant_manage = must_manage_dependance; |
| 1068 | pending_flush_queries.push_back(index); | 1071 | pending_flush_queries.push_back(index); |
| @@ -1100,7 +1103,7 @@ public: | |||
| 1100 | num_vertices = dependant_query->value / query->stride; | 1103 | num_vertices = dependant_query->value / query->stride; |
| 1101 | tfb_streamer.Free(query->dependant_index); | 1104 | tfb_streamer.Free(query->dependant_index); |
| 1102 | } else { | 1105 | } else { |
| 1103 | u8* pointer = cpu_memory.GetPointer(query->dependant_address); | 1106 | u8* pointer = device_memory.GetPointer<u8>(query->dependant_address); |
| 1104 | u32 result; | 1107 | u32 result; |
| 1105 | std::memcpy(&result, pointer, sizeof(u32)); | 1108 | std::memcpy(&result, pointer, sizeof(u32)); |
| 1106 | num_vertices = static_cast<u64>(result) / query->stride; | 1109 | num_vertices = static_cast<u64>(result) / query->stride; |
| @@ -1137,7 +1140,7 @@ public: | |||
| 1137 | private: | 1140 | private: |
| 1138 | QueryCacheRuntime& runtime; | 1141 | QueryCacheRuntime& runtime; |
| 1139 | TFBCounterStreamer& tfb_streamer; | 1142 | TFBCounterStreamer& tfb_streamer; |
| 1140 | Core::Memory::Memory& cpu_memory; | 1143 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 1141 | 1144 | ||
| 1142 | // syncing queue | 1145 | // syncing queue |
| 1143 | std::vector<size_t> pending_sync; | 1146 | std::vector<size_t> pending_sync; |
| @@ -1152,12 +1155,13 @@ private: | |||
| 1152 | 1155 | ||
| 1153 | struct QueryCacheRuntimeImpl { | 1156 | struct QueryCacheRuntimeImpl { |
| 1154 | QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, | 1157 | QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, |
| 1155 | Core::Memory::Memory& cpu_memory_, Vulkan::BufferCache& buffer_cache_, | 1158 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 1156 | const Device& device_, const MemoryAllocator& memory_allocator_, | 1159 | Vulkan::BufferCache& buffer_cache_, const Device& device_, |
| 1157 | Scheduler& scheduler_, StagingBufferPool& staging_pool_, | 1160 | const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, |
| 1161 | StagingBufferPool& staging_pool_, | ||
| 1158 | ComputePassDescriptorQueue& compute_pass_descriptor_queue, | 1162 | ComputePassDescriptorQueue& compute_pass_descriptor_queue, |
| 1159 | DescriptorPool& descriptor_pool) | 1163 | DescriptorPool& descriptor_pool) |
| 1160 | : rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, | 1164 | : rasterizer{rasterizer_}, device_memory{device_memory_}, |
| 1161 | buffer_cache{buffer_cache_}, device{device_}, | 1165 | buffer_cache{buffer_cache_}, device{device_}, |
| 1162 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_}, | 1166 | memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_}, |
| 1163 | guest_streamer(0, runtime), | 1167 | guest_streamer(0, runtime), |
| @@ -1168,7 +1172,7 @@ struct QueryCacheRuntimeImpl { | |||
| 1168 | scheduler, memory_allocator, staging_pool), | 1172 | scheduler, memory_allocator, staging_pool), |
| 1169 | primitives_succeeded_streamer( | 1173 | primitives_succeeded_streamer( |
| 1170 | static_cast<size_t>(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, | 1174 | static_cast<size_t>(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, |
| 1171 | cpu_memory_), | 1175 | device_memory_), |
| 1172 | primitives_needed_minus_succeeded_streamer( | 1176 | primitives_needed_minus_succeeded_streamer( |
| 1173 | static_cast<size_t>(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u), | 1177 | static_cast<size_t>(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u), |
| 1174 | hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { | 1178 | hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { |
| @@ -1195,7 +1199,7 @@ struct QueryCacheRuntimeImpl { | |||
| 1195 | } | 1199 | } |
| 1196 | 1200 | ||
| 1197 | VideoCore::RasterizerInterface* rasterizer; | 1201 | VideoCore::RasterizerInterface* rasterizer; |
| 1198 | Core::Memory::Memory& cpu_memory; | 1202 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 1199 | Vulkan::BufferCache& buffer_cache; | 1203 | Vulkan::BufferCache& buffer_cache; |
| 1200 | 1204 | ||
| 1201 | const Device& device; | 1205 | const Device& device; |
| @@ -1210,7 +1214,7 @@ struct QueryCacheRuntimeImpl { | |||
| 1210 | PrimitivesSucceededStreamer primitives_succeeded_streamer; | 1214 | PrimitivesSucceededStreamer primitives_succeeded_streamer; |
| 1211 | VideoCommon::StubStreamer<QueryCacheParams> primitives_needed_minus_succeeded_streamer; | 1215 | VideoCommon::StubStreamer<QueryCacheParams> primitives_needed_minus_succeeded_streamer; |
| 1212 | 1216 | ||
| 1213 | std::vector<std::pair<VAddr, VAddr>> little_cache; | 1217 | std::vector<std::pair<DAddr, DAddr>> little_cache; |
| 1214 | std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to; | 1218 | std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to; |
| 1215 | std::vector<size_t> redirect_cache; | 1219 | std::vector<size_t> redirect_cache; |
| 1216 | std::vector<std::vector<VkBufferCopy>> copies_setup; | 1220 | std::vector<std::vector<VkBufferCopy>> copies_setup; |
| @@ -1229,14 +1233,14 @@ struct QueryCacheRuntimeImpl { | |||
| 1229 | }; | 1233 | }; |
| 1230 | 1234 | ||
| 1231 | QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, | 1235 | QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, |
| 1232 | Core::Memory::Memory& cpu_memory_, | 1236 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 1233 | Vulkan::BufferCache& buffer_cache_, const Device& device_, | 1237 | Vulkan::BufferCache& buffer_cache_, const Device& device_, |
| 1234 | const MemoryAllocator& memory_allocator_, | 1238 | const MemoryAllocator& memory_allocator_, |
| 1235 | Scheduler& scheduler_, StagingBufferPool& staging_pool_, | 1239 | Scheduler& scheduler_, StagingBufferPool& staging_pool_, |
| 1236 | ComputePassDescriptorQueue& compute_pass_descriptor_queue, | 1240 | ComputePassDescriptorQueue& compute_pass_descriptor_queue, |
| 1237 | DescriptorPool& descriptor_pool) { | 1241 | DescriptorPool& descriptor_pool) { |
| 1238 | impl = std::make_unique<QueryCacheRuntimeImpl>( | 1242 | impl = std::make_unique<QueryCacheRuntimeImpl>( |
| 1239 | *this, rasterizer, cpu_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, | 1243 | *this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, |
| 1240 | staging_pool_, compute_pass_descriptor_queue, descriptor_pool); | 1244 | staging_pool_, compute_pass_descriptor_queue, descriptor_pool); |
| 1241 | } | 1245 | } |
| 1242 | 1246 | ||
| @@ -1309,7 +1313,7 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo | |||
| 1309 | ResumeHostConditionalRendering(); | 1313 | ResumeHostConditionalRendering(); |
| 1310 | } | 1314 | } |
| 1311 | 1315 | ||
| 1312 | void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(VAddr address, bool is_equal) { | 1316 | void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal) { |
| 1313 | VkBuffer to_resolve; | 1317 | VkBuffer to_resolve; |
| 1314 | u32 to_resolve_offset; | 1318 | u32 to_resolve_offset; |
| 1315 | { | 1319 | { |
| @@ -1350,11 +1354,11 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku | |||
| 1350 | return false; | 1354 | return false; |
| 1351 | } | 1355 | } |
| 1352 | 1356 | ||
| 1353 | const auto check_in_bc = [&](VAddr address) { | 1357 | const auto check_in_bc = [&](DAddr address) { |
| 1354 | return impl->buffer_cache.IsRegionGpuModified(address, 8); | 1358 | return impl->buffer_cache.IsRegionGpuModified(address, 8); |
| 1355 | }; | 1359 | }; |
| 1356 | const auto check_value = [&](VAddr address) { | 1360 | const auto check_value = [&](DAddr address) { |
| 1357 | u8* ptr = impl->cpu_memory.GetPointer(address); | 1361 | u8* ptr = impl->device_memory.GetPointer<u8>(address); |
| 1358 | u64 value{}; | 1362 | u64 value{}; |
| 1359 | std::memcpy(&value, ptr, sizeof(value)); | 1363 | std::memcpy(&value, ptr, sizeof(value)); |
| 1360 | return value == 0; | 1364 | return value == 0; |
| @@ -1477,8 +1481,8 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba | |||
| 1477 | for (auto& sync_val : values) { | 1481 | for (auto& sync_val : values) { |
| 1478 | total_size += sync_val.size; | 1482 | total_size += sync_val.size; |
| 1479 | bool found = false; | 1483 | bool found = false; |
| 1480 | VAddr base = Common::AlignDown(sync_val.address, Core::Memory::YUZU_PAGESIZE); | 1484 | DAddr base = Common::AlignDown(sync_val.address, Core::DEVICE_PAGESIZE); |
| 1481 | VAddr base_end = base + Core::Memory::YUZU_PAGESIZE; | 1485 | DAddr base_end = base + Core::DEVICE_PAGESIZE; |
| 1482 | for (size_t i = 0; i < impl->little_cache.size(); i++) { | 1486 | for (size_t i = 0; i < impl->little_cache.size(); i++) { |
| 1483 | const auto set_found = [&] { | 1487 | const auto set_found = [&] { |
| 1484 | impl->redirect_cache.push_back(i); | 1488 | impl->redirect_cache.push_back(i); |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h index e9a1ea169..f6151123e 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.h +++ b/src/video_core/renderer_vulkan/vk_query_cache.h | |||
| @@ -27,7 +27,7 @@ struct QueryCacheRuntimeImpl; | |||
| 27 | class QueryCacheRuntime { | 27 | class QueryCacheRuntime { |
| 28 | public: | 28 | public: |
| 29 | explicit QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, | 29 | explicit QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, |
| 30 | Core::Memory::Memory& cpu_memory_, | 30 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 31 | Vulkan::BufferCache& buffer_cache_, const Device& device_, | 31 | Vulkan::BufferCache& buffer_cache_, const Device& device_, |
| 32 | const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | 32 | const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, |
| 33 | StagingBufferPool& staging_pool_, | 33 | StagingBufferPool& staging_pool_, |
| @@ -61,7 +61,7 @@ public: | |||
| 61 | 61 | ||
| 62 | private: | 62 | private: |
| 63 | void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal); | 63 | void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal); |
| 64 | void HostConditionalRenderingCompareBCImpl(VAddr address, bool is_equal); | 64 | void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal); |
| 65 | friend struct QueryCacheRuntimeImpl; | 65 | friend struct QueryCacheRuntimeImpl; |
| 66 | std::unique_ptr<QueryCacheRuntimeImpl> impl; | 66 | std::unique_ptr<QueryCacheRuntimeImpl> impl; |
| 67 | }; | 67 | }; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 241fc34be..5bf41b81f 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "video_core/engines/draw_manager.h" | 18 | #include "video_core/engines/draw_manager.h" |
| 19 | #include "video_core/engines/kepler_compute.h" | 19 | #include "video_core/engines/kepler_compute.h" |
| 20 | #include "video_core/engines/maxwell_3d.h" | 20 | #include "video_core/engines/maxwell_3d.h" |
| 21 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 21 | #include "video_core/renderer_vulkan/blit_image.h" | 22 | #include "video_core/renderer_vulkan/blit_image.h" |
| 22 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 23 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 23 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" | 24 | #include "video_core/renderer_vulkan/maxwell_to_vk.h" |
| @@ -163,10 +164,11 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances, | |||
| 163 | } // Anonymous namespace | 164 | } // Anonymous namespace |
| 164 | 165 | ||
| 165 | RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 166 | RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 166 | Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, | 167 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 167 | const Device& device_, MemoryAllocator& memory_allocator_, | 168 | ScreenInfo& screen_info_, const Device& device_, |
| 168 | StateTracker& state_tracker_, Scheduler& scheduler_) | 169 | MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, |
| 169 | : RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, screen_info{screen_info_}, device{device_}, | 170 | Scheduler& scheduler_) |
| 171 | : gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_}, | ||
| 170 | memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, | 172 | memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, |
| 171 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), | 173 | staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), |
| 172 | guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler), | 174 | guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler), |
| @@ -174,14 +176,14 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 174 | texture_cache_runtime{ | 176 | texture_cache_runtime{ |
| 175 | device, scheduler, memory_allocator, staging_pool, | 177 | device, scheduler, memory_allocator, staging_pool, |
| 176 | blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue}, | 178 | blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue}, |
| 177 | texture_cache(texture_cache_runtime, *this), | 179 | texture_cache(texture_cache_runtime, device_memory), |
| 178 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, | 180 | buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, |
| 179 | guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool), | 181 | guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool), |
| 180 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), | 182 | buffer_cache(device_memory, buffer_cache_runtime), |
| 181 | query_cache_runtime(this, cpu_memory_, buffer_cache, device, memory_allocator, scheduler, | 183 | query_cache_runtime(this, device_memory, buffer_cache, device, memory_allocator, scheduler, |
| 182 | staging_pool, compute_pass_descriptor_queue, descriptor_pool), | 184 | staging_pool, compute_pass_descriptor_queue, descriptor_pool), |
| 183 | query_cache(gpu, *this, cpu_memory_, query_cache_runtime), | 185 | query_cache(gpu, *this, device_memory, query_cache_runtime), |
| 184 | pipeline_cache(*this, device, scheduler, descriptor_pool, guest_descriptor_queue, | 186 | pipeline_cache(device_memory, device, scheduler, descriptor_pool, guest_descriptor_queue, |
| 185 | render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), | 187 | render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), |
| 186 | accelerate_dma(buffer_cache, texture_cache, scheduler), | 188 | accelerate_dma(buffer_cache, texture_cache, scheduler), |
| 187 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), | 189 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), |
| @@ -508,7 +510,7 @@ void Vulkan::RasterizerVulkan::DisableGraphicsUniformBuffer(size_t stage, u32 in | |||
| 508 | 510 | ||
| 509 | void RasterizerVulkan::FlushAll() {} | 511 | void RasterizerVulkan::FlushAll() {} |
| 510 | 512 | ||
| 511 | void RasterizerVulkan::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 513 | void RasterizerVulkan::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 512 | if (addr == 0 || size == 0) { | 514 | if (addr == 0 || size == 0) { |
| 513 | return; | 515 | return; |
| 514 | } | 516 | } |
| @@ -525,7 +527,7 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType | |||
| 525 | } | 527 | } |
| 526 | } | 528 | } |
| 527 | 529 | ||
| 528 | bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 530 | bool RasterizerVulkan::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 529 | if ((True(which & VideoCommon::CacheType::BufferCache))) { | 531 | if ((True(which & VideoCommon::CacheType::BufferCache))) { |
| 530 | std::scoped_lock lock{buffer_cache.mutex}; | 532 | std::scoped_lock lock{buffer_cache.mutex}; |
| 531 | if (buffer_cache.IsRegionGpuModified(addr, size)) { | 533 | if (buffer_cache.IsRegionGpuModified(addr, size)) { |
| @@ -542,7 +544,7 @@ bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheT | |||
| 542 | return false; | 544 | return false; |
| 543 | } | 545 | } |
| 544 | 546 | ||
| 545 | VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(VAddr addr, u64 size) { | 547 | VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(DAddr addr, u64 size) { |
| 546 | { | 548 | { |
| 547 | std::scoped_lock lock{texture_cache.mutex}; | 549 | std::scoped_lock lock{texture_cache.mutex}; |
| 548 | auto area = texture_cache.GetFlushArea(addr, size); | 550 | auto area = texture_cache.GetFlushArea(addr, size); |
| @@ -551,14 +553,14 @@ VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(VAddr addr, u64 | |||
| 551 | } | 553 | } |
| 552 | } | 554 | } |
| 553 | VideoCore::RasterizerDownloadArea new_area{ | 555 | VideoCore::RasterizerDownloadArea new_area{ |
| 554 | .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), | 556 | .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE), |
| 555 | .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), | 557 | .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE), |
| 556 | .preemtive = true, | 558 | .preemtive = true, |
| 557 | }; | 559 | }; |
| 558 | return new_area; | 560 | return new_area; |
| 559 | } | 561 | } |
| 560 | 562 | ||
| 561 | void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { | 563 | void RasterizerVulkan::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType which) { |
| 562 | if (addr == 0 || size == 0) { | 564 | if (addr == 0 || size == 0) { |
| 563 | return; | 565 | return; |
| 564 | } | 566 | } |
| @@ -578,7 +580,7 @@ void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache | |||
| 578 | } | 580 | } |
| 579 | } | 581 | } |
| 580 | 582 | ||
| 581 | void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) { | 583 | void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) { |
| 582 | { | 584 | { |
| 583 | std::scoped_lock lock{texture_cache.mutex}; | 585 | std::scoped_lock lock{texture_cache.mutex}; |
| 584 | for (const auto& [addr, size] : sequences) { | 586 | for (const auto& [addr, size] : sequences) { |
| @@ -599,7 +601,7 @@ void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<VAddr, std::s | |||
| 599 | } | 601 | } |
| 600 | } | 602 | } |
| 601 | 603 | ||
| 602 | bool RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { | 604 | bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) { |
| 603 | if (addr == 0 || size == 0) { | 605 | if (addr == 0 || size == 0) { |
| 604 | return false; | 606 | return false; |
| 605 | } | 607 | } |
| @@ -620,7 +622,7 @@ bool RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { | |||
| 620 | return false; | 622 | return false; |
| 621 | } | 623 | } |
| 622 | 624 | ||
| 623 | void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) { | 625 | void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) { |
| 624 | if (addr == 0 || size == 0) { | 626 | if (addr == 0 || size == 0) { |
| 625 | return; | 627 | return; |
| 626 | } | 628 | } |
| @@ -640,7 +642,7 @@ void RasterizerVulkan::InvalidateGPUCache() { | |||
| 640 | gpu.InvalidateGPUCache(); | 642 | gpu.InvalidateGPUCache(); |
| 641 | } | 643 | } |
| 642 | 644 | ||
| 643 | void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { | 645 | void RasterizerVulkan::UnmapMemory(DAddr addr, u64 size) { |
| 644 | { | 646 | { |
| 645 | std::scoped_lock lock{texture_cache.mutex}; | 647 | std::scoped_lock lock{texture_cache.mutex}; |
| 646 | texture_cache.UnmapMemory(addr, size); | 648 | texture_cache.UnmapMemory(addr, size); |
| @@ -679,7 +681,7 @@ void RasterizerVulkan::ReleaseFences(bool force) { | |||
| 679 | fence_manager.WaitPendingFences(force); | 681 | fence_manager.WaitPendingFences(force); |
| 680 | } | 682 | } |
| 681 | 683 | ||
| 682 | void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size, | 684 | void RasterizerVulkan::FlushAndInvalidateRegion(DAddr addr, u64 size, |
| 683 | VideoCommon::CacheType which) { | 685 | VideoCommon::CacheType which) { |
| 684 | if (Settings::IsGPULevelExtreme()) { | 686 | if (Settings::IsGPULevelExtreme()) { |
| 685 | FlushRegion(addr, size, which); | 687 | FlushRegion(addr, size, which); |
| @@ -782,7 +784,7 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si | |||
| 782 | } | 784 | } |
| 783 | 785 | ||
| 784 | bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 786 | bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 785 | VAddr framebuffer_addr, u32 pixel_stride) { | 787 | DAddr framebuffer_addr, u32 pixel_stride) { |
| 786 | if (!framebuffer_addr) { | 788 | if (!framebuffer_addr) { |
| 787 | return false; | 789 | return false; |
| 788 | } | 790 | } |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index ad069556c..881ee0993 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -7,14 +7,13 @@ | |||
| 7 | 7 | ||
| 8 | #include <boost/container/static_vector.hpp> | 8 | #include <boost/container/static_vector.hpp> |
| 9 | 9 | ||
| 10 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 11 | |||
| 12 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 13 | #include "video_core/control/channel_state_cache.h" | 11 | #include "video_core/control/channel_state_cache.h" |
| 14 | #include "video_core/engines/maxwell_dma.h" | 12 | #include "video_core/engines/maxwell_dma.h" |
| 15 | #include "video_core/rasterizer_accelerated.h" | 13 | #include "video_core/host1x/gpu_device_memory_manager.h" |
| 16 | #include "video_core/rasterizer_interface.h" | 14 | #include "video_core/rasterizer_interface.h" |
| 17 | #include "video_core/renderer_vulkan/blit_image.h" | 15 | #include "video_core/renderer_vulkan/blit_image.h" |
| 16 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||
| 18 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 17 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 19 | #include "video_core/renderer_vulkan/vk_fence_manager.h" | 18 | #include "video_core/renderer_vulkan/vk_fence_manager.h" |
| 20 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" | 19 | #include "video_core/renderer_vulkan/vk_pipeline_cache.h" |
| @@ -34,10 +33,14 @@ namespace Core::Frontend { | |||
| 34 | class EmuWindow; | 33 | class EmuWindow; |
| 35 | } | 34 | } |
| 36 | 35 | ||
| 37 | namespace Tegra::Engines { | 36 | namespace Tegra { |
| 37 | |||
| 38 | namespace Engines { | ||
| 38 | class Maxwell3D; | 39 | class Maxwell3D; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 42 | } // namespace Tegra | ||
| 43 | |||
| 41 | namespace Vulkan { | 44 | namespace Vulkan { |
| 42 | 45 | ||
| 43 | struct ScreenInfo; | 46 | struct ScreenInfo; |
| @@ -70,13 +73,14 @@ private: | |||
| 70 | Scheduler& scheduler; | 73 | Scheduler& scheduler; |
| 71 | }; | 74 | }; |
| 72 | 75 | ||
| 73 | class RasterizerVulkan final : public VideoCore::RasterizerAccelerated, | 76 | class RasterizerVulkan final : public VideoCore::RasterizerInterface, |
| 74 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | 77 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { |
| 75 | public: | 78 | public: |
| 76 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 79 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| 77 | Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, | 80 | Tegra::MaxwellDeviceMemoryManager& device_memory_, |
| 78 | const Device& device_, MemoryAllocator& memory_allocator_, | 81 | ScreenInfo& screen_info_, const Device& device_, |
| 79 | StateTracker& state_tracker_, Scheduler& scheduler_); | 82 | MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, |
| 83 | Scheduler& scheduler_); | ||
| 80 | ~RasterizerVulkan() override; | 84 | ~RasterizerVulkan() override; |
| 81 | 85 | ||
| 82 | void Draw(bool is_indexed, u32 instance_count) override; | 86 | void Draw(bool is_indexed, u32 instance_count) override; |
| @@ -90,18 +94,18 @@ public: | |||
| 90 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; | 94 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; |
| 91 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; | 95 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; |
| 92 | void FlushAll() override; | 96 | void FlushAll() override; |
| 93 | void FlushRegion(VAddr addr, u64 size, | 97 | void FlushRegion(DAddr addr, u64 size, |
| 94 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 98 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 95 | bool MustFlushRegion(VAddr addr, u64 size, | 99 | bool MustFlushRegion(DAddr addr, u64 size, |
| 96 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 100 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 97 | VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; | 101 | VideoCore::RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) override; |
| 98 | void InvalidateRegion(VAddr addr, u64 size, | 102 | void InvalidateRegion(DAddr addr, u64 size, |
| 99 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 103 | VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 100 | void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) override; | 104 | void InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) override; |
| 101 | void OnCacheInvalidation(VAddr addr, u64 size) override; | 105 | void OnCacheInvalidation(DAddr addr, u64 size) override; |
| 102 | bool OnCPUWrite(VAddr addr, u64 size) override; | 106 | bool OnCPUWrite(DAddr addr, u64 size) override; |
| 103 | void InvalidateGPUCache() override; | 107 | void InvalidateGPUCache() override; |
| 104 | void UnmapMemory(VAddr addr, u64 size) override; | 108 | void UnmapMemory(DAddr addr, u64 size) override; |
| 105 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | 109 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; |
| 106 | void SignalFence(std::function<void()>&& func) override; | 110 | void SignalFence(std::function<void()>&& func) override; |
| 107 | void SyncOperation(std::function<void()>&& func) override; | 111 | void SyncOperation(std::function<void()>&& func) override; |
| @@ -109,7 +113,7 @@ public: | |||
| 109 | void SignalReference() override; | 113 | void SignalReference() override; |
| 110 | void ReleaseFences(bool force = true) override; | 114 | void ReleaseFences(bool force = true) override; |
| 111 | void FlushAndInvalidateRegion( | 115 | void FlushAndInvalidateRegion( |
| 112 | VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; | 116 | DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; |
| 113 | void WaitForIdle() override; | 117 | void WaitForIdle() override; |
| 114 | void FragmentBarrier() override; | 118 | void FragmentBarrier() override; |
| 115 | void TiledCacheBarrier() override; | 119 | void TiledCacheBarrier() override; |
| @@ -122,7 +126,7 @@ public: | |||
| 122 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | 126 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; |
| 123 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | 127 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, |
| 124 | std::span<const u8> memory) override; | 128 | std::span<const u8> memory) override; |
| 125 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 129 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr, |
| 126 | u32 pixel_stride) override; | 130 | u32 pixel_stride) override; |
| 127 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 131 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 128 | const VideoCore::DiskResourceLoadCallback& callback) override; | 132 | const VideoCore::DiskResourceLoadCallback& callback) override; |
| @@ -176,6 +180,7 @@ private: | |||
| 176 | void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); | 180 | void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); |
| 177 | 181 | ||
| 178 | Tegra::GPU& gpu; | 182 | Tegra::GPU& gpu; |
| 183 | Tegra::MaxwellDeviceMemoryManager& device_memory; | ||
| 179 | 184 | ||
| 180 | ScreenInfo& screen_info; | 185 | ScreenInfo& screen_info; |
| 181 | const Device& device; | 186 | const Device& device; |
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index e81cd031b..2af32c8f2 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "video_core/dirty_flags.h" | 12 | #include "video_core/dirty_flags.h" |
| 13 | #include "video_core/engines/kepler_compute.h" | 13 | #include "video_core/engines/kepler_compute.h" |
| 14 | #include "video_core/engines/maxwell_3d.h" | 14 | #include "video_core/engines/maxwell_3d.h" |
| 15 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 15 | #include "video_core/memory_manager.h" | 16 | #include "video_core/memory_manager.h" |
| 16 | #include "video_core/shader_cache.h" | 17 | #include "video_core/shader_cache.h" |
| 17 | #include "video_core/shader_environment.h" | 18 | #include "video_core/shader_environment.h" |
| @@ -34,7 +35,8 @@ void ShaderCache::SyncGuestHost() { | |||
| 34 | RemovePendingShaders(); | 35 | RemovePendingShaders(); |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | ShaderCache::ShaderCache(VideoCore::RasterizerInterface& rasterizer_) : rasterizer{rasterizer_} {} | 38 | ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_) |
| 39 | : device_memory{device_memory_} {} | ||
| 38 | 40 | ||
| 39 | bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) { | 41 | bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) { |
| 40 | auto& dirty{maxwell3d->dirty.flags}; | 42 | auto& dirty{maxwell3d->dirty.flags}; |
| @@ -132,7 +134,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t | |||
| 132 | 134 | ||
| 133 | storage.push_back(std::move(data)); | 135 | storage.push_back(std::move(data)); |
| 134 | 136 | ||
| 135 | rasterizer.UpdatePagesCachedCount(addr, size, 1); | 137 | device_memory.UpdatePagesCachedCount(addr, size, 1); |
| 136 | } | 138 | } |
| 137 | 139 | ||
| 138 | void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { | 140 | void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { |
| @@ -209,7 +211,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) { | |||
| 209 | 211 | ||
| 210 | const VAddr addr = entry->addr_start; | 212 | const VAddr addr = entry->addr_start; |
| 211 | const size_t size = entry->addr_end - addr; | 213 | const size_t size = entry->addr_end - addr; |
| 212 | rasterizer.UpdatePagesCachedCount(addr, size, -1); | 214 | device_memory.UpdatePagesCachedCount(addr, size, -1); |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) { | 217 | void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) { |
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index a76896620..fd9bf2562 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/polyfill_ranges.h" | 15 | #include "common/polyfill_ranges.h" |
| 16 | #include "video_core/control/channel_state_cache.h" | 16 | #include "video_core/control/channel_state_cache.h" |
| 17 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 17 | #include "video_core/rasterizer_interface.h" | 18 | #include "video_core/rasterizer_interface.h" |
| 18 | #include "video_core/shader_environment.h" | 19 | #include "video_core/shader_environment.h" |
| 19 | 20 | ||
| @@ -77,7 +78,7 @@ protected: | |||
| 77 | } | 78 | } |
| 78 | }; | 79 | }; |
| 79 | 80 | ||
| 80 | explicit ShaderCache(VideoCore::RasterizerInterface& rasterizer_); | 81 | explicit ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory); |
| 81 | 82 | ||
| 82 | /// @brief Update the hashes and information of shader stages | 83 | /// @brief Update the hashes and information of shader stages |
| 83 | /// @param unique_hashes Shader hashes to store into when a stage is enabled | 84 | /// @param unique_hashes Shader hashes to store into when a stage is enabled |
| @@ -145,7 +146,7 @@ private: | |||
| 145 | /// @brief Create a new shader entry and register it | 146 | /// @brief Create a new shader entry and register it |
| 146 | const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr); | 147 | const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr); |
| 147 | 148 | ||
| 148 | VideoCore::RasterizerInterface& rasterizer; | 149 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 149 | 150 | ||
| 150 | mutable std::mutex lookup_mutex; | 151 | mutable std::mutex lookup_mutex; |
| 151 | std::mutex invalidation_mutex; | 152 | std::mutex invalidation_mutex; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0d5a1709f..7398ed2ec 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -8,10 +8,11 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/alignment.h" | 9 | #include "common/alignment.h" |
| 10 | #include "common/settings.h" | 10 | #include "common/settings.h" |
| 11 | #include "core/memory.h" | ||
| 12 | #include "video_core/control/channel_state.h" | 11 | #include "video_core/control/channel_state.h" |
| 13 | #include "video_core/dirty_flags.h" | 12 | #include "video_core/dirty_flags.h" |
| 14 | #include "video_core/engines/kepler_compute.h" | 13 | #include "video_core/engines/kepler_compute.h" |
| 14 | #include "video_core/guest_memory.h" | ||
| 15 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 15 | #include "video_core/texture_cache/image_view_base.h" | 16 | #include "video_core/texture_cache/image_view_base.h" |
| 16 | #include "video_core/texture_cache/samples_helper.h" | 17 | #include "video_core/texture_cache/samples_helper.h" |
| 17 | #include "video_core/texture_cache/texture_cache_base.h" | 18 | #include "video_core/texture_cache/texture_cache_base.h" |
| @@ -27,8 +28,8 @@ using VideoCore::Surface::SurfaceType; | |||
| 27 | using namespace Common::Literals; | 28 | using namespace Common::Literals; |
| 28 | 29 | ||
| 29 | template <class P> | 30 | template <class P> |
| 30 | TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& rasterizer_) | 31 | TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManager& device_memory_) |
| 31 | : runtime{runtime_}, rasterizer{rasterizer_} { | 32 | : runtime{runtime_}, device_memory{device_memory_} { |
| 32 | // Configure null sampler | 33 | // Configure null sampler |
| 33 | TSCEntry sampler_descriptor{}; | 34 | TSCEntry sampler_descriptor{}; |
| 34 | sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); | 35 | sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); |
| @@ -49,19 +50,19 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | |||
| 49 | void(slot_samplers.insert(runtime, sampler_descriptor)); | 50 | void(slot_samplers.insert(runtime, sampler_descriptor)); |
| 50 | 51 | ||
| 51 | if constexpr (HAS_DEVICE_MEMORY_INFO) { | 52 | if constexpr (HAS_DEVICE_MEMORY_INFO) { |
| 52 | const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); | 53 | const s64 device_local_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); |
| 53 | const s64 min_spacing_expected = device_memory - 1_GiB; | 54 | const s64 min_spacing_expected = device_local_memory - 1_GiB; |
| 54 | const s64 min_spacing_critical = device_memory - 512_MiB; | 55 | const s64 min_spacing_critical = device_local_memory - 512_MiB; |
| 55 | const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD); | 56 | const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD); |
| 56 | const s64 min_vacancy_expected = (6 * mem_threshold) / 10; | 57 | const s64 min_vacancy_expected = (6 * mem_threshold) / 10; |
| 57 | const s64 min_vacancy_critical = (3 * mem_threshold) / 10; | 58 | const s64 min_vacancy_critical = (3 * mem_threshold) / 10; |
| 58 | expected_memory = static_cast<u64>( | 59 | expected_memory = static_cast<u64>( |
| 59 | std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected), | 60 | std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected), |
| 60 | DEFAULT_EXPECTED_MEMORY)); | 61 | DEFAULT_EXPECTED_MEMORY)); |
| 61 | critical_memory = static_cast<u64>( | 62 | critical_memory = static_cast<u64>( |
| 62 | std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical), | 63 | std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical), |
| 63 | DEFAULT_CRITICAL_MEMORY)); | 64 | DEFAULT_CRITICAL_MEMORY)); |
| 64 | minimum_memory = static_cast<u64>((device_memory - mem_threshold) / 2); | 65 | minimum_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2); |
| 65 | } else { | 66 | } else { |
| 66 | expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; | 67 | expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; |
| 67 | critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; | 68 | critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; |
| @@ -513,7 +514,7 @@ FramebufferId TextureCache<P>::GetFramebufferId(const RenderTargets& key) { | |||
| 513 | } | 514 | } |
| 514 | 515 | ||
| 515 | template <class P> | 516 | template <class P> |
| 516 | void TextureCache<P>::WriteMemory(VAddr cpu_addr, size_t size) { | 517 | void TextureCache<P>::WriteMemory(DAddr cpu_addr, size_t size) { |
| 517 | ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) { | 518 | ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) { |
| 518 | if (True(image.flags & ImageFlagBits::CpuModified)) { | 519 | if (True(image.flags & ImageFlagBits::CpuModified)) { |
| 519 | return; | 520 | return; |
| @@ -526,7 +527,7 @@ void TextureCache<P>::WriteMemory(VAddr cpu_addr, size_t size) { | |||
| 526 | } | 527 | } |
| 527 | 528 | ||
| 528 | template <class P> | 529 | template <class P> |
| 529 | void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) { | 530 | void TextureCache<P>::DownloadMemory(DAddr cpu_addr, size_t size) { |
| 530 | boost::container::small_vector<ImageId, 16> images; | 531 | boost::container::small_vector<ImageId, 16> images; |
| 531 | ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) { | 532 | ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) { |
| 532 | if (!image.IsSafeDownload()) { | 533 | if (!image.IsSafeDownload()) { |
| @@ -553,7 +554,7 @@ void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) { | |||
| 553 | } | 554 | } |
| 554 | 555 | ||
| 555 | template <class P> | 556 | template <class P> |
| 556 | std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(VAddr cpu_addr, | 557 | std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(DAddr cpu_addr, |
| 557 | u64 size) { | 558 | u64 size) { |
| 558 | std::optional<VideoCore::RasterizerDownloadArea> area{}; | 559 | std::optional<VideoCore::RasterizerDownloadArea> area{}; |
| 559 | ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) { | 560 | ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) { |
| @@ -579,7 +580,7 @@ std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(V | |||
| 579 | } | 580 | } |
| 580 | 581 | ||
| 581 | template <class P> | 582 | template <class P> |
| 582 | void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | 583 | void TextureCache<P>::UnmapMemory(DAddr cpu_addr, size_t size) { |
| 583 | boost::container::small_vector<ImageId, 16> deleted_images; | 584 | boost::container::small_vector<ImageId, 16> deleted_images; |
| 584 | ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); | 585 | ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); |
| 585 | for (const ImageId id : deleted_images) { | 586 | for (const ImageId id : deleted_images) { |
| @@ -713,7 +714,7 @@ bool TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 713 | 714 | ||
| 714 | template <class P> | 715 | template <class P> |
| 715 | typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView( | 716 | typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView( |
| 716 | const Tegra::FramebufferConfig& config, VAddr cpu_addr) { | 717 | const Tegra::FramebufferConfig& config, DAddr cpu_addr) { |
| 717 | // TODO: Properly implement this | 718 | // TODO: Properly implement this |
| 718 | const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS); | 719 | const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS); |
| 719 | if (it == page_table.end()) { | 720 | if (it == page_table.end()) { |
| @@ -940,7 +941,7 @@ bool TextureCache<P>::IsRescaling(const ImageViewBase& image_view) const noexcep | |||
| 940 | } | 941 | } |
| 941 | 942 | ||
| 942 | template <class P> | 943 | template <class P> |
| 943 | bool TextureCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { | 944 | bool TextureCache<P>::IsRegionGpuModified(DAddr addr, size_t size) { |
| 944 | bool is_modified = false; | 945 | bool is_modified = false; |
| 945 | ForEachImageInRegion(addr, size, [&is_modified](ImageId, ImageBase& image) { | 946 | ForEachImageInRegion(addr, size, [&is_modified](ImageId, ImageBase& image) { |
| 946 | if (False(image.flags & ImageFlagBits::GpuModified)) { | 947 | if (False(image.flags & ImageFlagBits::GpuModified)) { |
| @@ -1059,7 +1060,7 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging) | |||
| 1059 | return; | 1060 | return; |
| 1060 | } | 1061 | } |
| 1061 | 1062 | ||
| 1062 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( | 1063 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( |
| 1063 | *gpu_memory, gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); | 1064 | *gpu_memory, gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); |
| 1064 | 1065 | ||
| 1065 | if (True(image.flags & ImageFlagBits::Converted)) { | 1066 | if (True(image.flags & ImageFlagBits::Converted)) { |
| @@ -1124,7 +1125,7 @@ ImageId TextureCache<P>::FindOrInsertImage(const ImageInfo& info, GPUVAddr gpu_a | |||
| 1124 | template <class P> | 1125 | template <class P> |
| 1125 | ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, | 1126 | ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, |
| 1126 | RelaxedOptions options) { | 1127 | RelaxedOptions options) { |
| 1127 | std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1128 | std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1128 | if (!cpu_addr) { | 1129 | if (!cpu_addr) { |
| 1129 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); | 1130 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); |
| 1130 | if (!cpu_addr) { | 1131 | if (!cpu_addr) { |
| @@ -1265,7 +1266,7 @@ void TextureCache<P>::QueueAsyncDecode(Image& image, ImageId image_id) { | |||
| 1265 | 1266 | ||
| 1266 | static Common::ScratchBuffer<u8> local_unswizzle_data_buffer; | 1267 | static Common::ScratchBuffer<u8> local_unswizzle_data_buffer; |
| 1267 | local_unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes); | 1268 | local_unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes); |
| 1268 | Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( | 1269 | Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( |
| 1269 | *gpu_memory, image.gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); | 1270 | *gpu_memory, image.gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); |
| 1270 | 1271 | ||
| 1271 | auto copies = UnswizzleImage(*gpu_memory, image.gpu_addr, image.info, swizzle_data, | 1272 | auto copies = UnswizzleImage(*gpu_memory, image.gpu_addr, image.info, swizzle_data, |
| @@ -1339,14 +1340,14 @@ bool TextureCache<P>::ScaleDown(Image& image) { | |||
| 1339 | template <class P> | 1340 | template <class P> |
| 1340 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, | 1341 | ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, |
| 1341 | RelaxedOptions options) { | 1342 | RelaxedOptions options) { |
| 1342 | std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1343 | std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1343 | if (!cpu_addr) { | 1344 | if (!cpu_addr) { |
| 1344 | const auto size = CalculateGuestSizeInBytes(info); | 1345 | const auto size = CalculateGuestSizeInBytes(info); |
| 1345 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, size); | 1346 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, size); |
| 1346 | if (!cpu_addr) { | 1347 | if (!cpu_addr) { |
| 1347 | const VAddr fake_addr = ~(1ULL << 40ULL) + virtual_invalid_space; | 1348 | const DAddr fake_addr = ~(1ULL << 40ULL) + virtual_invalid_space; |
| 1348 | virtual_invalid_space += Common::AlignUp(size, 32); | 1349 | virtual_invalid_space += Common::AlignUp(size, 32); |
| 1349 | cpu_addr = std::optional<VAddr>(fake_addr); | 1350 | cpu_addr = std::optional<DAddr>(fake_addr); |
| 1350 | } | 1351 | } |
| 1351 | } | 1352 | } |
| 1352 | ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr); | 1353 | ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr); |
| @@ -1362,7 +1363,7 @@ ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, | |||
| 1362 | } | 1363 | } |
| 1363 | 1364 | ||
| 1364 | template <class P> | 1365 | template <class P> |
| 1365 | ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr) { | 1366 | ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr) { |
| 1366 | ImageInfo new_info = info; | 1367 | ImageInfo new_info = info; |
| 1367 | const size_t size_bytes = CalculateGuestSizeInBytes(new_info); | 1368 | const size_t size_bytes = CalculateGuestSizeInBytes(new_info); |
| 1368 | const bool broken_views = runtime.HasBrokenTextureViewFormats(); | 1369 | const bool broken_views = runtime.HasBrokenTextureViewFormats(); |
| @@ -1650,7 +1651,7 @@ std::optional<typename TextureCache<P>::BlitImages> TextureCache<P>::GetBlitImag | |||
| 1650 | 1651 | ||
| 1651 | template <class P> | 1652 | template <class P> |
| 1652 | ImageId TextureCache<P>::FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr) { | 1653 | ImageId TextureCache<P>::FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr) { |
| 1653 | std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1654 | std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1654 | if (!cpu_addr) { | 1655 | if (!cpu_addr) { |
| 1655 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); | 1656 | cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); |
| 1656 | if (!cpu_addr) { | 1657 | if (!cpu_addr) { |
| @@ -1780,7 +1781,7 @@ ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAdd | |||
| 1780 | 1781 | ||
| 1781 | template <class P> | 1782 | template <class P> |
| 1782 | template <typename Func> | 1783 | template <typename Func> |
| 1783 | void TextureCache<P>::ForEachImageInRegion(VAddr cpu_addr, size_t size, Func&& func) { | 1784 | void TextureCache<P>::ForEachImageInRegion(DAddr cpu_addr, size_t size, Func&& func) { |
| 1784 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; | 1785 | using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; |
| 1785 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; | 1786 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; |
| 1786 | boost::container::small_vector<ImageId, 32> images; | 1787 | boost::container::small_vector<ImageId, 32> images; |
| @@ -1924,11 +1925,11 @@ void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, | |||
| 1924 | template <class P> | 1925 | template <class P> |
| 1925 | template <typename Func> | 1926 | template <typename Func> |
| 1926 | void TextureCache<P>::ForEachSparseSegment(ImageBase& image, Func&& func) { | 1927 | void TextureCache<P>::ForEachSparseSegment(ImageBase& image, Func&& func) { |
| 1927 | using FuncReturn = typename std::invoke_result<Func, GPUVAddr, VAddr, size_t>::type; | 1928 | using FuncReturn = typename std::invoke_result<Func, GPUVAddr, DAddr, size_t>::type; |
| 1928 | static constexpr bool RETURNS_BOOL = std::is_same_v<FuncReturn, bool>; | 1929 | static constexpr bool RETURNS_BOOL = std::is_same_v<FuncReturn, bool>; |
| 1929 | const auto segments = gpu_memory->GetSubmappedRange(image.gpu_addr, image.guest_size_bytes); | 1930 | const auto segments = gpu_memory->GetSubmappedRange(image.gpu_addr, image.guest_size_bytes); |
| 1930 | for (const auto& [gpu_addr, size] : segments) { | 1931 | for (const auto& [gpu_addr, size] : segments) { |
| 1931 | std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 1932 | std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 1932 | ASSERT(cpu_addr); | 1933 | ASSERT(cpu_addr); |
| 1933 | if constexpr (RETURNS_BOOL) { | 1934 | if constexpr (RETURNS_BOOL) { |
| 1934 | if (func(gpu_addr, *cpu_addr, size)) { | 1935 | if (func(gpu_addr, *cpu_addr, size)) { |
| @@ -1980,7 +1981,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { | |||
| 1980 | } | 1981 | } |
| 1981 | boost::container::small_vector<ImageViewId, 16> sparse_maps; | 1982 | boost::container::small_vector<ImageViewId, 16> sparse_maps; |
| 1982 | ForEachSparseSegment( | 1983 | ForEachSparseSegment( |
| 1983 | image, [this, image_id, &sparse_maps](GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { | 1984 | image, [this, image_id, &sparse_maps](GPUVAddr gpu_addr, DAddr cpu_addr, size_t size) { |
| 1984 | auto map_id = slot_map_views.insert(gpu_addr, cpu_addr, size, image_id); | 1985 | auto map_id = slot_map_views.insert(gpu_addr, cpu_addr, size, image_id); |
| 1985 | ForEachCPUPage(cpu_addr, size, | 1986 | ForEachCPUPage(cpu_addr, size, |
| 1986 | [this, map_id](u64 page) { page_table[page].push_back(map_id); }); | 1987 | [this, map_id](u64 page) { page_table[page].push_back(map_id); }); |
| @@ -2048,7 +2049,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 2048 | auto& sparse_maps = it->second; | 2049 | auto& sparse_maps = it->second; |
| 2049 | for (auto& map_view_id : sparse_maps) { | 2050 | for (auto& map_view_id : sparse_maps) { |
| 2050 | const auto& map_range = slot_map_views[map_view_id]; | 2051 | const auto& map_range = slot_map_views[map_view_id]; |
| 2051 | const VAddr cpu_addr = map_range.cpu_addr; | 2052 | const DAddr cpu_addr = map_range.cpu_addr; |
| 2052 | const std::size_t size = map_range.size; | 2053 | const std::size_t size = map_range.size; |
| 2053 | ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) { | 2054 | ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) { |
| 2054 | const auto page_it = page_table.find(page); | 2055 | const auto page_it = page_table.find(page); |
| @@ -2080,7 +2081,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { | |||
| 2080 | ASSERT(False(image.flags & ImageFlagBits::Tracked)); | 2081 | ASSERT(False(image.flags & ImageFlagBits::Tracked)); |
| 2081 | image.flags |= ImageFlagBits::Tracked; | 2082 | image.flags |= ImageFlagBits::Tracked; |
| 2082 | if (False(image.flags & ImageFlagBits::Sparse)) { | 2083 | if (False(image.flags & ImageFlagBits::Sparse)) { |
| 2083 | rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); | 2084 | device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); |
| 2084 | return; | 2085 | return; |
| 2085 | } | 2086 | } |
| 2086 | if (True(image.flags & ImageFlagBits::Registered)) { | 2087 | if (True(image.flags & ImageFlagBits::Registered)) { |
| @@ -2089,15 +2090,15 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { | |||
| 2089 | auto& sparse_maps = it->second; | 2090 | auto& sparse_maps = it->second; |
| 2090 | for (auto& map_view_id : sparse_maps) { | 2091 | for (auto& map_view_id : sparse_maps) { |
| 2091 | const auto& map = slot_map_views[map_view_id]; | 2092 | const auto& map = slot_map_views[map_view_id]; |
| 2092 | const VAddr cpu_addr = map.cpu_addr; | 2093 | const DAddr cpu_addr = map.cpu_addr; |
| 2093 | const std::size_t size = map.size; | 2094 | const std::size_t size = map.size; |
| 2094 | rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); | 2095 | device_memory.UpdatePagesCachedCount(cpu_addr, size, 1); |
| 2095 | } | 2096 | } |
| 2096 | return; | 2097 | return; |
| 2097 | } | 2098 | } |
| 2098 | ForEachSparseSegment(image, | 2099 | ForEachSparseSegment(image, |
| 2099 | [this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { | 2100 | [this]([[maybe_unused]] GPUVAddr gpu_addr, DAddr cpu_addr, size_t size) { |
| 2100 | rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); | 2101 | device_memory.UpdatePagesCachedCount(cpu_addr, size, 1); |
| 2101 | }); | 2102 | }); |
| 2102 | } | 2103 | } |
| 2103 | 2104 | ||
| @@ -2106,7 +2107,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { | |||
| 2106 | ASSERT(True(image.flags & ImageFlagBits::Tracked)); | 2107 | ASSERT(True(image.flags & ImageFlagBits::Tracked)); |
| 2107 | image.flags &= ~ImageFlagBits::Tracked; | 2108 | image.flags &= ~ImageFlagBits::Tracked; |
| 2108 | if (False(image.flags & ImageFlagBits::Sparse)) { | 2109 | if (False(image.flags & ImageFlagBits::Sparse)) { |
| 2109 | rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); | 2110 | device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); |
| 2110 | return; | 2111 | return; |
| 2111 | } | 2112 | } |
| 2112 | ASSERT(True(image.flags & ImageFlagBits::Registered)); | 2113 | ASSERT(True(image.flags & ImageFlagBits::Registered)); |
| @@ -2115,9 +2116,9 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { | |||
| 2115 | auto& sparse_maps = it->second; | 2116 | auto& sparse_maps = it->second; |
| 2116 | for (auto& map_view_id : sparse_maps) { | 2117 | for (auto& map_view_id : sparse_maps) { |
| 2117 | const auto& map = slot_map_views[map_view_id]; | 2118 | const auto& map = slot_map_views[map_view_id]; |
| 2118 | const VAddr cpu_addr = map.cpu_addr; | 2119 | const DAddr cpu_addr = map.cpu_addr; |
| 2119 | const std::size_t size = map.size; | 2120 | const std::size_t size = map.size; |
| 2120 | rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); | 2121 | device_memory.UpdatePagesCachedCount(cpu_addr, size, -1); |
| 2121 | } | 2122 | } |
| 2122 | } | 2123 | } |
| 2123 | 2124 | ||
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 6caf75b46..8699d40d4 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -36,9 +36,11 @@ | |||
| 36 | #include "video_core/texture_cache/types.h" | 36 | #include "video_core/texture_cache/types.h" |
| 37 | #include "video_core/textures/texture.h" | 37 | #include "video_core/textures/texture.h" |
| 38 | 38 | ||
| 39 | namespace Tegra::Control { | 39 | namespace Tegra { |
| 40 | namespace Control { | ||
| 40 | struct ChannelState; | 41 | struct ChannelState; |
| 41 | } | 42 | } |
| 43 | } // namespace Tegra | ||
| 42 | 44 | ||
| 43 | namespace VideoCommon { | 45 | namespace VideoCommon { |
| 44 | 46 | ||
| @@ -126,7 +128,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI | |||
| 126 | }; | 128 | }; |
| 127 | 129 | ||
| 128 | public: | 130 | public: |
| 129 | explicit TextureCache(Runtime&, VideoCore::RasterizerInterface&); | 131 | explicit TextureCache(Runtime&, Tegra::MaxwellDeviceMemoryManager&); |
| 130 | 132 | ||
| 131 | /// Notify the cache that a new frame has been queued | 133 | /// Notify the cache that a new frame has been queued |
| 132 | void TickFrame(); | 134 | void TickFrame(); |
| @@ -190,15 +192,15 @@ public: | |||
| 190 | Framebuffer* GetFramebuffer(); | 192 | Framebuffer* GetFramebuffer(); |
| 191 | 193 | ||
| 192 | /// Mark images in a range as modified from the CPU | 194 | /// Mark images in a range as modified from the CPU |
| 193 | void WriteMemory(VAddr cpu_addr, size_t size); | 195 | void WriteMemory(DAddr cpu_addr, size_t size); |
| 194 | 196 | ||
| 195 | /// Download contents of host images to guest memory in a region | 197 | /// Download contents of host images to guest memory in a region |
| 196 | void DownloadMemory(VAddr cpu_addr, size_t size); | 198 | void DownloadMemory(DAddr cpu_addr, size_t size); |
| 197 | 199 | ||
| 198 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); | 200 | std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(DAddr cpu_addr, u64 size); |
| 199 | 201 | ||
| 200 | /// Remove images in a region | 202 | /// Remove images in a region |
| 201 | void UnmapMemory(VAddr cpu_addr, size_t size); | 203 | void UnmapMemory(DAddr cpu_addr, size_t size); |
| 202 | 204 | ||
| 203 | /// Remove images in a region | 205 | /// Remove images in a region |
| 204 | void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size); | 206 | void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size); |
| @@ -210,7 +212,7 @@ public: | |||
| 210 | 212 | ||
| 211 | /// Try to find a cached image view in the given CPU address | 213 | /// Try to find a cached image view in the given CPU address |
| 212 | [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config, | 214 | [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config, |
| 213 | VAddr cpu_addr); | 215 | DAddr cpu_addr); |
| 214 | 216 | ||
| 215 | /// Return true when there are uncommitted images to be downloaded | 217 | /// Return true when there are uncommitted images to be downloaded |
| 216 | [[nodiscard]] bool HasUncommittedFlushes() const noexcept; | 218 | [[nodiscard]] bool HasUncommittedFlushes() const noexcept; |
| @@ -235,7 +237,7 @@ public: | |||
| 235 | GPUVAddr address = 0, size_t size = 0); | 237 | GPUVAddr address = 0, size_t size = 0); |
| 236 | 238 | ||
| 237 | /// Return true when a CPU region is modified from the GPU | 239 | /// Return true when a CPU region is modified from the GPU |
| 238 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); | 240 | [[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size); |
| 239 | 241 | ||
| 240 | [[nodiscard]] bool IsRescaling() const noexcept; | 242 | [[nodiscard]] bool IsRescaling() const noexcept; |
| 241 | 243 | ||
| @@ -252,7 +254,7 @@ public: | |||
| 252 | private: | 254 | private: |
| 253 | /// Iterate over all page indices in a range | 255 | /// Iterate over all page indices in a range |
| 254 | template <typename Func> | 256 | template <typename Func> |
| 255 | static void ForEachCPUPage(VAddr addr, size_t size, Func&& func) { | 257 | static void ForEachCPUPage(DAddr addr, size_t size, Func&& func) { |
| 256 | static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>; | 258 | static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>; |
| 257 | const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS; | 259 | const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS; |
| 258 | for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) { | 260 | for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) { |
| @@ -326,7 +328,7 @@ private: | |||
| 326 | 328 | ||
| 327 | /// Create a new image and join perfectly matching existing images | 329 | /// Create a new image and join perfectly matching existing images |
| 328 | /// Remove joined images from the cache | 330 | /// Remove joined images from the cache |
| 329 | [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); | 331 | [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr); |
| 330 | 332 | ||
| 331 | [[nodiscard]] ImageId FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr); | 333 | [[nodiscard]] ImageId FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr); |
| 332 | 334 | ||
| @@ -349,7 +351,7 @@ private: | |||
| 349 | 351 | ||
| 350 | /// Iterates over all the images in a region calling func | 352 | /// Iterates over all the images in a region calling func |
| 351 | template <typename Func> | 353 | template <typename Func> |
| 352 | void ForEachImageInRegion(VAddr cpu_addr, size_t size, Func&& func); | 354 | void ForEachImageInRegion(DAddr cpu_addr, size_t size, Func&& func); |
| 353 | 355 | ||
| 354 | template <typename Func> | 356 | template <typename Func> |
| 355 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); | 357 | void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); |
| @@ -421,7 +423,7 @@ private: | |||
| 421 | 423 | ||
| 422 | Runtime& runtime; | 424 | Runtime& runtime; |
| 423 | 425 | ||
| 424 | VideoCore::RasterizerInterface& rasterizer; | 426 | Tegra::MaxwellDeviceMemoryManager& device_memory; |
| 425 | std::deque<TextureCacheGPUMap> gpu_page_table_storage; | 427 | std::deque<TextureCacheGPUMap> gpu_page_table_storage; |
| 426 | 428 | ||
| 427 | RenderTargets render_targets; | 429 | RenderTargets render_targets; |
| @@ -432,7 +434,7 @@ private: | |||
| 432 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; | 434 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; |
| 433 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; | 435 | std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; |
| 434 | 436 | ||
| 435 | VAddr virtual_invalid_space{}; | 437 | DAddr virtual_invalid_space{}; |
| 436 | 438 | ||
| 437 | bool has_deleted_images = false; | 439 | bool has_deleted_images = false; |
| 438 | bool is_rescaling = false; | 440 | bool is_rescaling = false; |
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index fcf70068e..1a6f0d1ad 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -20,9 +20,9 @@ | |||
| 20 | #include "common/div_ceil.h" | 20 | #include "common/div_ceil.h" |
| 21 | #include "common/scratch_buffer.h" | 21 | #include "common/scratch_buffer.h" |
| 22 | #include "common/settings.h" | 22 | #include "common/settings.h" |
| 23 | #include "core/memory.h" | ||
| 24 | #include "video_core/compatible_formats.h" | 23 | #include "video_core/compatible_formats.h" |
| 25 | #include "video_core/engines/maxwell_3d.h" | 24 | #include "video_core/engines/maxwell_3d.h" |
| 25 | #include "video_core/guest_memory.h" | ||
| 26 | #include "video_core/memory_manager.h" | 26 | #include "video_core/memory_manager.h" |
| 27 | #include "video_core/surface.h" | 27 | #include "video_core/surface.h" |
| 28 | #include "video_core/texture_cache/decode_bc.h" | 28 | #include "video_core/texture_cache/decode_bc.h" |
| @@ -552,7 +552,8 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr | |||
| 552 | for (s32 layer = 0; layer < info.resources.layers; ++layer) { | 552 | for (s32 layer = 0; layer < info.resources.layers; ++layer) { |
| 553 | const std::span<const u8> src = input.subspan(host_offset); | 553 | const std::span<const u8> src = input.subspan(host_offset); |
| 554 | { | 554 | { |
| 555 | Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadWrite> | 555 | Tegra::Memory::GpuGuestMemoryScoped<u8, |
| 556 | Tegra::Memory::GuestMemoryFlags::UnsafeReadWrite> | ||
| 556 | dst(gpu_memory, gpu_addr + guest_offset, subresource_size, &tmp_buffer); | 557 | dst(gpu_memory, gpu_addr + guest_offset, subresource_size, &tmp_buffer); |
| 557 | 558 | ||
| 558 | SwizzleTexture(dst, src, bytes_per_block, num_tiles.width, num_tiles.height, | 559 | SwizzleTexture(dst, src, bytes_per_block, num_tiles.width, num_tiles.height, |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index b42d48416..0efb7b49d 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "video_core/host1x/gpu_device_memory_manager.h" | ||
| 10 | #include "video_core/host1x/host1x.h" | ||
| 9 | #include "video_core/renderer_base.h" | 11 | #include "video_core/renderer_base.h" |
| 10 | #include "video_core/renderer_null/renderer_null.h" | 12 | #include "video_core/renderer_null/renderer_null.h" |
| 11 | #include "video_core/renderer_opengl/renderer_opengl.h" | 13 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| @@ -18,18 +20,17 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer( | |||
| 18 | Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, | 20 | Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, |
| 19 | std::unique_ptr<Core::Frontend::GraphicsContext> context) { | 21 | std::unique_ptr<Core::Frontend::GraphicsContext> context) { |
| 20 | auto& telemetry_session = system.TelemetrySession(); | 22 | auto& telemetry_session = system.TelemetrySession(); |
| 21 | auto& cpu_memory = system.ApplicationMemory(); | 23 | auto& device_memory = system.Host1x().MemoryManager(); |
| 22 | 24 | ||
| 23 | switch (Settings::values.renderer_backend.GetValue()) { | 25 | switch (Settings::values.renderer_backend.GetValue()) { |
| 24 | case Settings::RendererBackend::OpenGL: | 26 | case Settings::RendererBackend::OpenGL: |
| 25 | return std::make_unique<OpenGL::RendererOpenGL>(telemetry_session, emu_window, cpu_memory, | 27 | return std::make_unique<OpenGL::RendererOpenGL>(telemetry_session, emu_window, |
| 26 | gpu, std::move(context)); | 28 | device_memory, gpu, std::move(context)); |
| 27 | case Settings::RendererBackend::Vulkan: | 29 | case Settings::RendererBackend::Vulkan: |
| 28 | return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, cpu_memory, | 30 | return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, |
| 29 | gpu, std::move(context)); | 31 | device_memory, gpu, std::move(context)); |
| 30 | case Settings::RendererBackend::Null: | 32 | case Settings::RendererBackend::Null: |
| 31 | return std::make_unique<Null::RendererNull>(emu_window, cpu_memory, gpu, | 33 | return std::make_unique<Null::RendererNull>(emu_window, gpu, std::move(context)); |
| 32 | std::move(context)); | ||
| 33 | default: | 34 | default: |
| 34 | return nullptr; | 35 | return nullptr; |
| 35 | } | 36 | } |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 074aed964..3966bd61e 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -39,6 +39,10 @@ void SortPhysicalDevicesPerVendor(std::vector<VkPhysicalDevice>& devices, | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | bool IsMicrosoftDozen(const char* device_name) { | ||
| 43 | return std::strstr(device_name, "Microsoft") != nullptr; | ||
| 44 | } | ||
| 45 | |||
| 42 | void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) { | 46 | void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) { |
| 43 | // Sort by name, this will set a base and make GPUs with higher numbers appear first | 47 | // Sort by name, this will set a base and make GPUs with higher numbers appear first |
| 44 | // (e.g. GTX 1650 will intentionally be listed before a GTX 1080). | 48 | // (e.g. GTX 1650 will intentionally be listed before a GTX 1080). |
| @@ -52,6 +56,12 @@ void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceD | |||
| 52 | }); | 56 | }); |
| 53 | // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest. | 57 | // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest. |
| 54 | SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086}); | 58 | SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086}); |
| 59 | // Demote Microsoft's Dozen devices to the bottom. | ||
| 60 | SortPhysicalDevices( | ||
| 61 | devices, dld, | ||
| 62 | [](const VkPhysicalDeviceProperties& lhs, const VkPhysicalDeviceProperties& rhs) { | ||
| 63 | return IsMicrosoftDozen(rhs.deviceName) && !IsMicrosoftDozen(lhs.deviceName); | ||
| 64 | }); | ||
| 55 | } | 65 | } |
| 56 | 66 | ||
| 57 | template <typename T> | 67 | template <typename T> |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 90278052a..93b03b917 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -351,7 +351,7 @@ if (APPLE) | |||
| 351 | 351 | ||
| 352 | if (NOT USE_SYSTEM_MOLTENVK) | 352 | if (NOT USE_SYSTEM_MOLTENVK) |
| 353 | set(MOLTENVK_PLATFORM "macOS") | 353 | set(MOLTENVK_PLATFORM "macOS") |
| 354 | set(MOLTENVK_VERSION "v1.2.5") | 354 | set(MOLTENVK_VERSION "v1.2.7") |
| 355 | download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) | 355 | download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) |
| 356 | endif() | 356 | endif() |
| 357 | find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) | 357 | find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) |
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 140a7fe5d..568775027 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp | |||
| @@ -122,9 +122,8 @@ void ConfigurePerGameAddons::LoadConfiguration() { | |||
| 122 | 122 | ||
| 123 | const auto& disabled = Settings::values.disabled_addons[title_id]; | 123 | const auto& disabled = Settings::values.disabled_addons[title_id]; |
| 124 | 124 | ||
| 125 | for (const auto& patch : pm.GetPatchVersionNames(update_raw)) { | 125 | for (const auto& patch : pm.GetPatches(update_raw)) { |
| 126 | const auto name = | 126 | const auto name = QString::fromStdString(patch.name); |
| 127 | QString::fromStdString(patch.first).replace(QStringLiteral("[D] "), QString{}); | ||
| 128 | 127 | ||
| 129 | auto* const first_item = new QStandardItem; | 128 | auto* const first_item = new QStandardItem; |
| 130 | first_item->setText(name); | 129 | first_item->setText(name); |
| @@ -136,7 +135,7 @@ void ConfigurePerGameAddons::LoadConfiguration() { | |||
| 136 | first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked); | 135 | first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked); |
| 137 | 136 | ||
| 138 | list_items.push_back(QList<QStandardItem*>{ | 137 | list_items.push_back(QList<QStandardItem*>{ |
| 139 | first_item, new QStandardItem{QString::fromStdString(patch.second)}}); | 138 | first_item, new QStandardItem{QString::fromStdString(patch.version)}}); |
| 140 | item_model->appendRow(list_items.back()); | 139 | item_model->appendRow(list_items.back()); |
| 141 | } | 140 | } |
| 142 | 141 | ||
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index d898d8acc..6b1f4527b 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp | |||
| @@ -116,8 +116,8 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type | |||
| 116 | .high_amplitude = 1.0f, | 116 | .high_amplitude = 1.0f, |
| 117 | .high_frequency = 320.0f, | 117 | .high_frequency = 320.0f, |
| 118 | }; | 118 | }; |
| 119 | controller->SetVibration(0, vibration); | 119 | controller->SetVibration(Core::HID::DeviceIndex::Left, vibration); |
| 120 | controller->SetVibration(1, vibration); | 120 | controller->SetVibration(Core::HID::DeviceIndex::Right, vibration); |
| 121 | 121 | ||
| 122 | // Restore previous values | 122 | // Restore previous values |
| 123 | player.vibration_enabled = old_vibration_enabled; | 123 | player.vibration_enabled = old_vibration_enabled; |
| @@ -127,7 +127,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type | |||
| 127 | void ConfigureVibration::StopVibrations() { | 127 | void ConfigureVibration::StopVibrations() { |
| 128 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { | 128 | for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { |
| 129 | auto controller = hid_core.GetEmulatedControllerByIndex(i); | 129 | auto controller = hid_core.GetEmulatedControllerByIndex(i); |
| 130 | controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); | 130 | controller->SetVibration(Core::HID::DeviceIndex::Left, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 131 | controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); | 131 | controller->SetVibration(Core::HID::DeviceIndex::Right, Core::HID::DEFAULT_VIBRATION_VALUE); |
| 132 | } | 132 | } |
| 133 | } | 133 | } |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index dc006832e..9747e3fb3 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -164,18 +164,19 @@ QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager, | |||
| 164 | QString out; | 164 | QString out; |
| 165 | FileSys::VirtualFile update_raw; | 165 | FileSys::VirtualFile update_raw; |
| 166 | loader.ReadUpdateRaw(update_raw); | 166 | loader.ReadUpdateRaw(update_raw); |
| 167 | for (const auto& kv : patch_manager.GetPatchVersionNames(update_raw)) { | 167 | for (const auto& patch : patch_manager.GetPatches(update_raw)) { |
| 168 | const bool is_update = kv.first == "Update" || kv.first == "[D] Update"; | 168 | const bool is_update = patch.name == "Update"; |
| 169 | if (!updatable && is_update) { | 169 | if (!updatable && is_update) { |
| 170 | continue; | 170 | continue; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | const QString type = QString::fromStdString(kv.first); | 173 | const QString type = |
| 174 | QString::fromStdString(patch.enabled ? patch.name : "[D] " + patch.name); | ||
| 174 | 175 | ||
| 175 | if (kv.second.empty()) { | 176 | if (patch.version.empty()) { |
| 176 | out.append(QStringLiteral("%1\n").arg(type)); | 177 | out.append(QStringLiteral("%1\n").arg(type)); |
| 177 | } else { | 178 | } else { |
| 178 | auto ver = kv.second; | 179 | auto ver = patch.version; |
| 179 | 180 | ||
| 180 | // Display container name for packed updates | 181 | // Display container name for packed updates |
| 181 | if (is_update && ver == "PACKED") { | 182 | if (is_update && ver == "PACKED") { |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 33756febf..d8b0beadf 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include "core/hle/service/am/applet_oe.h" | 47 | #include "core/hle/service/am/applet_oe.h" |
| 48 | #include "core/hle/service/am/applets/applets.h" | 48 | #include "core/hle/service/am/applets/applets.h" |
| 49 | #include "core/hle/service/set/system_settings_server.h" | 49 | #include "core/hle/service/set/system_settings_server.h" |
| 50 | #include "frontend_common/content_manager.h" | ||
| 50 | #include "hid_core/frontend/emulated_controller.h" | 51 | #include "hid_core/frontend/emulated_controller.h" |
| 51 | #include "hid_core/hid_core.h" | 52 | #include "hid_core/hid_core.h" |
| 52 | #include "yuzu/multiplayer/state.h" | 53 | #include "yuzu/multiplayer/state.h" |
| @@ -518,12 +519,21 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk | |||
| 518 | continue; | 519 | continue; |
| 519 | } | 520 | } |
| 520 | 521 | ||
| 522 | int user_arg_idx = ++i; | ||
| 521 | bool argument_ok; | 523 | bool argument_ok; |
| 522 | const std::size_t selected_user = args[++i].toUInt(&argument_ok); | 524 | std::size_t selected_user = args[user_arg_idx].toUInt(&argument_ok); |
| 523 | 525 | ||
| 524 | if (!argument_ok) { | 526 | if (!argument_ok) { |
| 525 | LOG_ERROR(Frontend, "Invalid user argument"); | 527 | // try to look it up by username, only finds the first username that matches. |
| 526 | continue; | 528 | const std::string user_arg_str = args[user_arg_idx].toStdString(); |
| 529 | const auto user_idx = system->GetProfileManager().GetUserIndex(user_arg_str); | ||
| 530 | |||
| 531 | if (user_idx == std::nullopt) { | ||
| 532 | LOG_ERROR(Frontend, "Invalid user argument"); | ||
| 533 | continue; | ||
| 534 | } | ||
| 535 | |||
| 536 | selected_user = user_idx.value(); | ||
| 527 | } | 537 | } |
| 528 | 538 | ||
| 529 | if (!system->GetProfileManager().UserExistsIndex(selected_user)) { | 539 | if (!system->GetProfileManager().UserExistsIndex(selected_user)) { |
| @@ -532,6 +542,8 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk | |||
| 532 | } | 542 | } |
| 533 | 543 | ||
| 534 | Settings::values.current_user = static_cast<s32>(selected_user); | 544 | Settings::values.current_user = static_cast<s32>(selected_user); |
| 545 | |||
| 546 | user_flag_cmd_line = true; | ||
| 535 | continue; | 547 | continue; |
| 536 | } | 548 | } |
| 537 | 549 | ||
| @@ -1942,7 +1954,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1942 | 1954 | ||
| 1943 | Settings::LogSettings(); | 1955 | Settings::LogSettings(); |
| 1944 | 1956 | ||
| 1945 | if (UISettings::values.select_user_on_boot) { | 1957 | if (UISettings::values.select_user_on_boot && !user_flag_cmd_line) { |
| 1946 | const Core::Frontend::ProfileSelectParameters parameters{ | 1958 | const Core::Frontend::ProfileSelectParameters parameters{ |
| 1947 | .mode = Service::AM::Applets::UiMode::UserSelector, | 1959 | .mode = Service::AM::Applets::UiMode::UserSelector, |
| 1948 | .invalid_uid_list = {}, | 1960 | .invalid_uid_list = {}, |
| @@ -1954,6 +1966,11 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1954 | } | 1966 | } |
| 1955 | } | 1967 | } |
| 1956 | 1968 | ||
| 1969 | // If the user specifies -u (successfully) on the cmd line, don't prompt for a user on first | ||
| 1970 | // game startup only. If the user stops emulation and starts a new one, go back to the expected | ||
| 1971 | // behavior of asking. | ||
| 1972 | user_flag_cmd_line = false; | ||
| 1973 | |||
| 1957 | if (!LoadROM(filename, program_id, program_index, launch_type)) { | 1974 | if (!LoadROM(filename, program_id, program_index, launch_type)) { |
| 1958 | return; | 1975 | return; |
| 1959 | } | 1976 | } |
| @@ -2460,10 +2477,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT | |||
| 2460 | } | 2477 | } |
| 2461 | 2478 | ||
| 2462 | void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { | 2479 | void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { |
| 2463 | const auto& fs_controller = system->GetFileSystemController(); | 2480 | const auto res = |
| 2464 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || | 2481 | ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id); |
| 2465 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); | ||
| 2466 | |||
| 2467 | if (res) { | 2482 | if (res) { |
| 2468 | QMessageBox::information(this, tr("Successfully Removed"), | 2483 | QMessageBox::information(this, tr("Successfully Removed"), |
| 2469 | tr("Successfully removed the installed base game.")); | 2484 | tr("Successfully removed the installed base game.")); |
| @@ -2475,11 +2490,7 @@ void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { | |||
| 2475 | } | 2490 | } |
| 2476 | 2491 | ||
| 2477 | void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { | 2492 | void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { |
| 2478 | const auto update_id = program_id | 0x800; | 2493 | const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id); |
| 2479 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 2480 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || | ||
| 2481 | fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id); | ||
| 2482 | |||
| 2483 | if (res) { | 2494 | if (res) { |
| 2484 | QMessageBox::information(this, tr("Successfully Removed"), | 2495 | QMessageBox::information(this, tr("Successfully Removed"), |
| 2485 | tr("Successfully removed the installed update.")); | 2496 | tr("Successfully removed the installed update.")); |
| @@ -2490,22 +2501,7 @@ void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { | |||
| 2490 | } | 2501 | } |
| 2491 | 2502 | ||
| 2492 | void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { | 2503 | void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { |
| 2493 | u32 count{}; | 2504 | const size_t count = ContentManager::RemoveAllDLC(system.get(), program_id); |
| 2494 | const auto& fs_controller = system->GetFileSystemController(); | ||
| 2495 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( | ||
| 2496 | FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | ||
| 2497 | |||
| 2498 | for (const auto& entry : dlc_entries) { | ||
| 2499 | if (FileSys::GetBaseTitleID(entry.title_id) == program_id) { | ||
| 2500 | const auto res = | ||
| 2501 | fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) || | ||
| 2502 | fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id); | ||
| 2503 | if (res) { | ||
| 2504 | ++count; | ||
| 2505 | } | ||
| 2506 | } | ||
| 2507 | } | ||
| 2508 | |||
| 2509 | if (count == 0) { | 2505 | if (count == 0) { |
| 2510 | QMessageBox::warning(this, GetGameListErrorRemoving(type), | 2506 | QMessageBox::warning(this, GetGameListErrorRemoving(type), |
| 2511 | tr("There are no DLC installed for this title.")); | 2507 | tr("There are no DLC installed for this title.")); |
| @@ -2790,16 +2786,6 @@ void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) { | |||
| 2790 | QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"), | 2786 | QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"), |
| 2791 | tr("File contents were not checked for validity.")); | 2787 | tr("File contents were not checked for validity.")); |
| 2792 | }; | 2788 | }; |
| 2793 | const auto Failed = [this] { | ||
| 2794 | QMessageBox::critical(this, tr("Integrity verification failed!"), | ||
| 2795 | tr("File contents may be corrupt.")); | ||
| 2796 | }; | ||
| 2797 | |||
| 2798 | const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read)); | ||
| 2799 | if (loader == nullptr) { | ||
| 2800 | NotImplemented(); | ||
| 2801 | return; | ||
| 2802 | } | ||
| 2803 | 2789 | ||
| 2804 | QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); | 2790 | QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); |
| 2805 | progress.setWindowModality(Qt::WindowModal); | 2791 | progress.setWindowModality(Qt::WindowModal); |
| @@ -2807,30 +2793,26 @@ void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) { | |||
| 2807 | progress.setAutoClose(false); | 2793 | progress.setAutoClose(false); |
| 2808 | progress.setAutoReset(false); | 2794 | progress.setAutoReset(false); |
| 2809 | 2795 | ||
| 2810 | const auto QtProgressCallback = [&](size_t processed_size, size_t total_size) { | 2796 | const auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { |
| 2811 | if (progress.wasCanceled()) { | ||
| 2812 | return false; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | progress.setValue(static_cast<int>((processed_size * 100) / total_size)); | 2797 | progress.setValue(static_cast<int>((processed_size * 100) / total_size)); |
| 2816 | return true; | 2798 | return progress.wasCanceled(); |
| 2817 | }; | 2799 | }; |
| 2818 | 2800 | ||
| 2819 | const auto status = loader->VerifyIntegrity(QtProgressCallback); | 2801 | const auto result = |
| 2820 | if (progress.wasCanceled() || | 2802 | ContentManager::VerifyGameContents(system.get(), game_path, QtProgressCallback); |
| 2821 | status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) { | 2803 | progress.close(); |
| 2804 | switch (result) { | ||
| 2805 | case ContentManager::GameVerificationResult::Success: | ||
| 2806 | QMessageBox::information(this, tr("Integrity verification succeeded!"), | ||
| 2807 | tr("The operation completed successfully.")); | ||
| 2808 | break; | ||
| 2809 | case ContentManager::GameVerificationResult::Failed: | ||
| 2810 | QMessageBox::critical(this, tr("Integrity verification failed!"), | ||
| 2811 | tr("File contents may be corrupt.")); | ||
| 2812 | break; | ||
| 2813 | case ContentManager::GameVerificationResult::NotImplemented: | ||
| 2822 | NotImplemented(); | 2814 | NotImplemented(); |
| 2823 | return; | ||
| 2824 | } | 2815 | } |
| 2825 | |||
| 2826 | if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) { | ||
| 2827 | Failed(); | ||
| 2828 | return; | ||
| 2829 | } | ||
| 2830 | |||
| 2831 | progress.close(); | ||
| 2832 | QMessageBox::information(this, tr("Integrity verification succeeded!"), | ||
| 2833 | tr("The operation completed successfully.")); | ||
| 2834 | } | 2816 | } |
| 2835 | 2817 | ||
| 2836 | void GMainWindow::OnGameListCopyTID(u64 program_id) { | 2818 | void GMainWindow::OnGameListCopyTID(u64 program_id) { |
| @@ -3274,12 +3256,21 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3274 | install_progress->setLabelText( | 3256 | install_progress->setLabelText( |
| 3275 | tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); | 3257 | tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); |
| 3276 | 3258 | ||
| 3277 | QFuture<InstallResult> future; | 3259 | QFuture<ContentManager::InstallResult> future; |
| 3278 | InstallResult result; | 3260 | ContentManager::InstallResult result; |
| 3279 | 3261 | ||
| 3280 | if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { | 3262 | if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { |
| 3281 | 3263 | const auto progress_callback = [this](size_t size, size_t progress) { | |
| 3282 | future = QtConcurrent::run([this, &file] { return InstallNSP(file); }); | 3264 | emit UpdateInstallProgress(); |
| 3265 | if (install_progress->wasCanceled()) { | ||
| 3266 | return true; | ||
| 3267 | } | ||
| 3268 | return false; | ||
| 3269 | }; | ||
| 3270 | future = QtConcurrent::run([this, &file, progress_callback] { | ||
| 3271 | return ContentManager::InstallNSP(system.get(), vfs.get(), file.toStdString(), | ||
| 3272 | progress_callback); | ||
| 3273 | }); | ||
| 3283 | 3274 | ||
| 3284 | while (!future.isFinished()) { | 3275 | while (!future.isFinished()) { |
| 3285 | QCoreApplication::processEvents(); | 3276 | QCoreApplication::processEvents(); |
| @@ -3295,16 +3286,16 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3295 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); | 3286 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); |
| 3296 | 3287 | ||
| 3297 | switch (result) { | 3288 | switch (result) { |
| 3298 | case InstallResult::Success: | 3289 | case ContentManager::InstallResult::Success: |
| 3299 | new_files.append(QFileInfo(file).fileName()); | 3290 | new_files.append(QFileInfo(file).fileName()); |
| 3300 | break; | 3291 | break; |
| 3301 | case InstallResult::Overwrite: | 3292 | case ContentManager::InstallResult::Overwrite: |
| 3302 | overwritten_files.append(QFileInfo(file).fileName()); | 3293 | overwritten_files.append(QFileInfo(file).fileName()); |
| 3303 | break; | 3294 | break; |
| 3304 | case InstallResult::Failure: | 3295 | case ContentManager::InstallResult::Failure: |
| 3305 | failed_files.append(QFileInfo(file).fileName()); | 3296 | failed_files.append(QFileInfo(file).fileName()); |
| 3306 | break; | 3297 | break; |
| 3307 | case InstallResult::BaseInstallAttempted: | 3298 | case ContentManager::InstallResult::BaseInstallAttempted: |
| 3308 | failed_files.append(QFileInfo(file).fileName()); | 3299 | failed_files.append(QFileInfo(file).fileName()); |
| 3309 | detected_base_install = true; | 3300 | detected_base_install = true; |
| 3310 | break; | 3301 | break; |
| @@ -3338,96 +3329,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 3338 | ui->action_Install_File_NAND->setEnabled(true); | 3329 | ui->action_Install_File_NAND->setEnabled(true); |
| 3339 | } | 3330 | } |
| 3340 | 3331 | ||
| 3341 | InstallResult GMainWindow::InstallNSP(const QString& filename) { | 3332 | ContentManager::InstallResult GMainWindow::InstallNCA(const QString& filename) { |
| 3342 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, | ||
| 3343 | const FileSys::VirtualFile& dest, std::size_t block_size) { | ||
| 3344 | if (src == nullptr || dest == nullptr) { | ||
| 3345 | return false; | ||
| 3346 | } | ||
| 3347 | if (!dest->Resize(src->GetSize())) { | ||
| 3348 | return false; | ||
| 3349 | } | ||
| 3350 | |||
| 3351 | std::vector<u8> buffer(CopyBufferSize); | ||
| 3352 | |||
| 3353 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 3354 | if (install_progress->wasCanceled()) { | ||
| 3355 | dest->Resize(0); | ||
| 3356 | return false; | ||
| 3357 | } | ||
| 3358 | |||
| 3359 | emit UpdateInstallProgress(); | ||
| 3360 | |||
| 3361 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 3362 | dest->Write(buffer.data(), read, i); | ||
| 3363 | } | ||
| 3364 | return true; | ||
| 3365 | }; | ||
| 3366 | |||
| 3367 | std::shared_ptr<FileSys::NSP> nsp; | ||
| 3368 | if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { | ||
| 3369 | nsp = std::make_shared<FileSys::NSP>( | ||
| 3370 | vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 3371 | if (nsp->IsExtractedType()) { | ||
| 3372 | return InstallResult::Failure; | ||
| 3373 | } | ||
| 3374 | } else { | ||
| 3375 | return InstallResult::Failure; | ||
| 3376 | } | ||
| 3377 | |||
| 3378 | if (nsp->GetStatus() != Loader::ResultStatus::Success) { | ||
| 3379 | return InstallResult::Failure; | ||
| 3380 | } | ||
| 3381 | const auto res = system->GetFileSystemController().GetUserNANDContents()->InstallEntry( | ||
| 3382 | *nsp, true, qt_raw_copy); | ||
| 3383 | switch (res) { | ||
| 3384 | case FileSys::InstallResult::Success: | ||
| 3385 | return InstallResult::Success; | ||
| 3386 | case FileSys::InstallResult::OverwriteExisting: | ||
| 3387 | return InstallResult::Overwrite; | ||
| 3388 | case FileSys::InstallResult::ErrorBaseInstall: | ||
| 3389 | return InstallResult::BaseInstallAttempted; | ||
| 3390 | default: | ||
| 3391 | return InstallResult::Failure; | ||
| 3392 | } | ||
| 3393 | } | ||
| 3394 | |||
| 3395 | InstallResult GMainWindow::InstallNCA(const QString& filename) { | ||
| 3396 | const auto qt_raw_copy = [this](const FileSys::VirtualFile& src, | ||
| 3397 | const FileSys::VirtualFile& dest, std::size_t block_size) { | ||
| 3398 | if (src == nullptr || dest == nullptr) { | ||
| 3399 | return false; | ||
| 3400 | } | ||
| 3401 | if (!dest->Resize(src->GetSize())) { | ||
| 3402 | return false; | ||
| 3403 | } | ||
| 3404 | |||
| 3405 | std::vector<u8> buffer(CopyBufferSize); | ||
| 3406 | |||
| 3407 | for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { | ||
| 3408 | if (install_progress->wasCanceled()) { | ||
| 3409 | dest->Resize(0); | ||
| 3410 | return false; | ||
| 3411 | } | ||
| 3412 | |||
| 3413 | emit UpdateInstallProgress(); | ||
| 3414 | |||
| 3415 | const auto read = src->Read(buffer.data(), buffer.size(), i); | ||
| 3416 | dest->Write(buffer.data(), read, i); | ||
| 3417 | } | ||
| 3418 | return true; | ||
| 3419 | }; | ||
| 3420 | |||
| 3421 | const auto nca = | ||
| 3422 | std::make_shared<FileSys::NCA>(vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read)); | ||
| 3423 | const auto id = nca->GetStatus(); | ||
| 3424 | |||
| 3425 | // Game updates necessary are missing base RomFS | ||
| 3426 | if (id != Loader::ResultStatus::Success && | ||
| 3427 | id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | ||
| 3428 | return InstallResult::Failure; | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | const QStringList tt_options{tr("System Application"), | 3333 | const QStringList tt_options{tr("System Application"), |
| 3432 | tr("System Archive"), | 3334 | tr("System Archive"), |
| 3433 | tr("System Application Update"), | 3335 | tr("System Application Update"), |
| @@ -3448,7 +3350,7 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) { | |||
| 3448 | if (!ok || index == -1) { | 3350 | if (!ok || index == -1) { |
| 3449 | QMessageBox::warning(this, tr("Failed to Install"), | 3351 | QMessageBox::warning(this, tr("Failed to Install"), |
| 3450 | tr("The title type you selected for the NCA is invalid.")); | 3352 | tr("The title type you selected for the NCA is invalid.")); |
| 3451 | return InstallResult::Failure; | 3353 | return ContentManager::InstallResult::Failure; |
| 3452 | } | 3354 | } |
| 3453 | 3355 | ||
| 3454 | // If index is equal to or past Game, add the jump in TitleType. | 3356 | // If index is equal to or past Game, add the jump in TitleType. |
| @@ -3462,15 +3364,15 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) { | |||
| 3462 | auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() | 3364 | auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() |
| 3463 | : fs_controller.GetSystemNANDContents(); | 3365 | : fs_controller.GetSystemNANDContents(); |
| 3464 | 3366 | ||
| 3465 | const auto res = registered_cache->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), | 3367 | const auto progress_callback = [this](size_t size, size_t progress) { |
| 3466 | true, qt_raw_copy); | 3368 | emit UpdateInstallProgress(); |
| 3467 | if (res == FileSys::InstallResult::Success) { | 3369 | if (install_progress->wasCanceled()) { |
| 3468 | return InstallResult::Success; | 3370 | return true; |
| 3469 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | 3371 | } |
| 3470 | return InstallResult::Overwrite; | 3372 | return false; |
| 3471 | } else { | 3373 | }; |
| 3472 | return InstallResult::Failure; | 3374 | return ContentManager::InstallNCA(vfs.get(), filename.toStdString(), registered_cache, |
| 3473 | } | 3375 | static_cast<FileSys::TitleType>(index), progress_callback); |
| 3474 | } | 3376 | } |
| 3475 | 3377 | ||
| 3476 | void GMainWindow::OnMenuRecentFile() { | 3378 | void GMainWindow::OnMenuRecentFile() { |
| @@ -4205,10 +4107,6 @@ void GMainWindow::OnOpenYuzuFolder() { | |||
| 4205 | } | 4107 | } |
| 4206 | 4108 | ||
| 4207 | void GMainWindow::OnVerifyInstalledContents() { | 4109 | void GMainWindow::OnVerifyInstalledContents() { |
| 4208 | // Declare sizes. | ||
| 4209 | size_t total_size = 0; | ||
| 4210 | size_t processed_size = 0; | ||
| 4211 | |||
| 4212 | // Initialize a progress dialog. | 4110 | // Initialize a progress dialog. |
| 4213 | QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); | 4111 | QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); |
| 4214 | progress.setWindowModality(Qt::WindowModal); | 4112 | progress.setWindowModality(Qt::WindowModal); |
| @@ -4216,93 +4114,25 @@ void GMainWindow::OnVerifyInstalledContents() { | |||
| 4216 | progress.setAutoClose(false); | 4114 | progress.setAutoClose(false); |
| 4217 | progress.setAutoReset(false); | 4115 | progress.setAutoReset(false); |
| 4218 | 4116 | ||
| 4219 | // Declare a list of file names which failed to verify. | ||
| 4220 | std::vector<std::string> failed; | ||
| 4221 | |||
| 4222 | // Declare progress callback. | 4117 | // Declare progress callback. |
| 4223 | auto QtProgressCallback = [&](size_t nca_processed, size_t nca_total) { | 4118 | auto QtProgressCallback = [&](size_t total_size, size_t processed_size) { |
| 4224 | if (progress.wasCanceled()) { | 4119 | progress.setValue(static_cast<int>((processed_size * 100) / total_size)); |
| 4225 | return false; | 4120 | return progress.wasCanceled(); |
| 4226 | } | ||
| 4227 | progress.setValue(static_cast<int>(((processed_size + nca_processed) * 100) / total_size)); | ||
| 4228 | return true; | ||
| 4229 | }; | 4121 | }; |
| 4230 | 4122 | ||
| 4231 | // Get content registries. | 4123 | const std::vector<std::string> result = |
| 4232 | auto bis_contents = system->GetFileSystemController().GetSystemNANDContents(); | 4124 | ContentManager::VerifyInstalledContents(system.get(), provider.get(), QtProgressCallback); |
| 4233 | auto user_contents = system->GetFileSystemController().GetUserNANDContents(); | ||
| 4234 | |||
| 4235 | std::vector<FileSys::RegisteredCache*> content_providers; | ||
| 4236 | if (bis_contents) { | ||
| 4237 | content_providers.push_back(bis_contents); | ||
| 4238 | } | ||
| 4239 | if (user_contents) { | ||
| 4240 | content_providers.push_back(user_contents); | ||
| 4241 | } | ||
| 4242 | |||
| 4243 | // Get associated NCA files. | ||
| 4244 | std::vector<FileSys::VirtualFile> nca_files; | ||
| 4245 | |||
| 4246 | // Get all installed IDs. | ||
| 4247 | for (auto nca_provider : content_providers) { | ||
| 4248 | const auto entries = nca_provider->ListEntriesFilter(); | ||
| 4249 | |||
| 4250 | for (const auto& entry : entries) { | ||
| 4251 | auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type); | ||
| 4252 | if (!nca_file) { | ||
| 4253 | continue; | ||
| 4254 | } | ||
| 4255 | |||
| 4256 | total_size += nca_file->GetSize(); | ||
| 4257 | nca_files.push_back(std::move(nca_file)); | ||
| 4258 | } | ||
| 4259 | } | ||
| 4260 | |||
| 4261 | // Using the NCA loader, determine if all NCAs are valid. | ||
| 4262 | for (auto& nca_file : nca_files) { | ||
| 4263 | Loader::AppLoader_NCA nca_loader(nca_file); | ||
| 4264 | |||
| 4265 | auto status = nca_loader.VerifyIntegrity(QtProgressCallback); | ||
| 4266 | if (progress.wasCanceled()) { | ||
| 4267 | break; | ||
| 4268 | } | ||
| 4269 | if (status != Loader::ResultStatus::Success) { | ||
| 4270 | FileSys::NCA nca(nca_file); | ||
| 4271 | const auto title_id = nca.GetTitleId(); | ||
| 4272 | std::string title_name = "unknown"; | ||
| 4273 | |||
| 4274 | const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id), | ||
| 4275 | FileSys::ContentRecordType::Control); | ||
| 4276 | if (control && control->GetStatus() == Loader::ResultStatus::Success) { | ||
| 4277 | const FileSys::PatchManager pm{title_id, system->GetFileSystemController(), | ||
| 4278 | *provider}; | ||
| 4279 | const auto [nacp, logo] = pm.ParseControlNCA(*control); | ||
| 4280 | if (nacp) { | ||
| 4281 | title_name = nacp->GetApplicationName(); | ||
| 4282 | } | ||
| 4283 | } | ||
| 4284 | |||
| 4285 | if (title_id > 0) { | ||
| 4286 | failed.push_back( | ||
| 4287 | fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name)); | ||
| 4288 | } else { | ||
| 4289 | failed.push_back(fmt::format("{} (unknown)", nca_file->GetName())); | ||
| 4290 | } | ||
| 4291 | } | ||
| 4292 | |||
| 4293 | processed_size += nca_file->GetSize(); | ||
| 4294 | } | ||
| 4295 | |||
| 4296 | progress.close(); | 4125 | progress.close(); |
| 4297 | 4126 | ||
| 4298 | if (failed.size() > 0) { | 4127 | if (result.empty()) { |
| 4299 | auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(failed, "\n"))); | 4128 | QMessageBox::information(this, tr("Integrity verification succeeded!"), |
| 4129 | tr("The operation completed successfully.")); | ||
| 4130 | } else { | ||
| 4131 | const auto failed_names = | ||
| 4132 | QString::fromStdString(fmt::format("{}", fmt::join(result, "\n"))); | ||
| 4300 | QMessageBox::critical( | 4133 | QMessageBox::critical( |
| 4301 | this, tr("Integrity verification failed!"), | 4134 | this, tr("Integrity verification failed!"), |
| 4302 | tr("Verification failed for the following files:\n\n%1").arg(failed_names)); | 4135 | tr("Verification failed for the following files:\n\n%1").arg(failed_names)); |
| 4303 | } else { | ||
| 4304 | QMessageBox::information(this, tr("Integrity verification succeeded!"), | ||
| 4305 | tr("The operation completed successfully.")); | ||
| 4306 | } | 4136 | } |
| 4307 | } | 4137 | } |
| 4308 | 4138 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 366e806d5..280fae5c3 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "common/announce_multiplayer_room.h" | 16 | #include "common/announce_multiplayer_room.h" |
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "configuration/qt_config.h" | 18 | #include "configuration/qt_config.h" |
| 19 | #include "frontend_common/content_manager.h" | ||
| 19 | #include "input_common/drivers/tas_input.h" | 20 | #include "input_common/drivers/tas_input.h" |
| 20 | #include "yuzu/compatibility_list.h" | 21 | #include "yuzu/compatibility_list.h" |
| 21 | #include "yuzu/hotkeys.h" | 22 | #include "yuzu/hotkeys.h" |
| @@ -124,13 +125,6 @@ enum class EmulatedDirectoryTarget { | |||
| 124 | SDMC, | 125 | SDMC, |
| 125 | }; | 126 | }; |
| 126 | 127 | ||
| 127 | enum class InstallResult { | ||
| 128 | Success, | ||
| 129 | Overwrite, | ||
| 130 | Failure, | ||
| 131 | BaseInstallAttempted, | ||
| 132 | }; | ||
| 133 | |||
| 134 | enum class ReinitializeKeyBehavior { | 128 | enum class ReinitializeKeyBehavior { |
| 135 | NoWarning, | 129 | NoWarning, |
| 136 | Warning, | 130 | Warning, |
| @@ -427,8 +421,7 @@ private: | |||
| 427 | void RemoveCacheStorage(u64 program_id); | 421 | void RemoveCacheStorage(u64 program_id); |
| 428 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, | 422 | bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, |
| 429 | u64* selected_title_id, u8* selected_content_record_type); | 423 | u64* selected_title_id, u8* selected_content_record_type); |
| 430 | InstallResult InstallNSP(const QString& filename); | 424 | ContentManager::InstallResult InstallNCA(const QString& filename); |
| 431 | InstallResult InstallNCA(const QString& filename); | ||
| 432 | void MigrateConfigFiles(); | 425 | void MigrateConfigFiles(); |
| 433 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, | 426 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, |
| 434 | std::string_view gpu_vendor = {}); | 427 | std::string_view gpu_vendor = {}); |
| @@ -523,6 +516,8 @@ private: | |||
| 523 | std::unique_ptr<EmuThread> emu_thread; | 516 | std::unique_ptr<EmuThread> emu_thread; |
| 524 | // The path to the game currently running | 517 | // The path to the game currently running |
| 525 | QString current_game_path; | 518 | QString current_game_path; |
| 519 | // Whether a user was set on the command line (skips UserSelector if it's forced to show up) | ||
| 520 | bool user_flag_cmd_line = false; | ||
| 526 | 521 | ||
| 527 | bool auto_paused = false; | 522 | bool auto_paused = false; |
| 528 | bool auto_muted = false; | 523 | bool auto_muted = false; |