mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 12:55:45 +00:00
Driver Fetcher (#130)
Lets the user download & install drivers from various repositories. Co-authored-by: swurl <swurl@swurl.xyz> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/130 Co-authored-by: Aleksandr Popovich <alekpopo@pm.me> Co-committed-by: Aleksandr Popovich <alekpopo@pm.me>
This commit is contained in:
parent
810df8d01c
commit
972576d2c5
45 changed files with 1131 additions and 254 deletions
|
@ -225,11 +225,14 @@ dependencies {
|
||||||
implementation("com.google.android.material:material:1.12.0")
|
implementation("com.google.android.material:material:1.12.0")
|
||||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
implementation("io.coil-kt:coil:2.2.2")
|
implementation("io.coil-kt:coil:2.2.2")
|
||||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||||
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2")
|
||||||
implementation("androidx.window:window:1.3.0")
|
implementation("androidx.window:window:1.3.0")
|
||||||
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
|
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
|
||||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||||
|
implementation("org.commonmark:commonmark:0.22.0")
|
||||||
implementation("androidx.navigation:navigation-fragment-ktx:2.8.9")
|
implementation("androidx.navigation:navigation-fragment-ktx:2.8.9")
|
||||||
implementation("androidx.navigation:navigation-ui-ktx:2.8.9")
|
implementation("androidx.navigation:navigation-ui-ktx:2.8.9")
|
||||||
implementation("info.debatty:java-string-similarity:2.0.0")
|
implementation("info.debatty:java-string-similarity:2.0.0")
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
package org.yuzu.yuzu_emu.features.fetcher
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.yuzu.yuzu_emu.databinding.ItemDriverGroupBinding
|
||||||
|
import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment.DriverGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.transition.AutoTransition
|
||||||
|
import androidx.transition.ChangeBounds
|
||||||
|
import androidx.transition.Fade
|
||||||
|
import androidx.transition.TransitionManager
|
||||||
|
import androidx.transition.TransitionSet
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
|
|
||||||
|
class DriverGroupAdapter(
|
||||||
|
private val activity: FragmentActivity,
|
||||||
|
private val driverViewModel: DriverViewModel
|
||||||
|
) : RecyclerView.Adapter<DriverGroupAdapter.DriverGroupViewHolder>() {
|
||||||
|
private var driverGroups: List<DriverGroup> = emptyList()
|
||||||
|
|
||||||
|
inner class DriverGroupViewHolder(
|
||||||
|
private val binding: ItemDriverGroupBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(group: DriverGroup) {
|
||||||
|
val onClick = {
|
||||||
|
TransitionManager.beginDelayedTransition(
|
||||||
|
binding.root,
|
||||||
|
TransitionSet().addTransition(Fade()).addTransition(ChangeBounds())
|
||||||
|
.setDuration(200)
|
||||||
|
)
|
||||||
|
val isVisible = binding.recyclerReleases.isVisible
|
||||||
|
|
||||||
|
binding.recyclerReleases.visibility = if (isVisible) View.GONE else View.VISIBLE
|
||||||
|
binding.imageDropdownArrow.rotation = if (isVisible) 0f else 180f
|
||||||
|
|
||||||
|
if (!isVisible && binding.recyclerReleases.adapter == null) {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
binding.recyclerReleases.layoutManager =
|
||||||
|
LinearLayoutManager(binding.root.context)
|
||||||
|
binding.recyclerReleases.adapter =
|
||||||
|
ReleaseAdapter(group.releases, activity, driverViewModel)
|
||||||
|
|
||||||
|
binding.recyclerReleases.addItemDecoration(
|
||||||
|
SpacingItemDecoration(
|
||||||
|
(activity.resources.displayMetrics.density * 8).toInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.textGroupName.text = group.name
|
||||||
|
binding.textGroupName.setOnClickListener { onClick() }
|
||||||
|
|
||||||
|
binding.imageDropdownArrow.setOnClickListener { onClick() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DriverGroupViewHolder {
|
||||||
|
val binding = ItemDriverGroupBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context), parent, false
|
||||||
|
)
|
||||||
|
return DriverGroupViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: DriverGroupViewHolder, position: Int) {
|
||||||
|
holder.bind(driverGroups[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = driverGroups.size
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun updateDriverGroups(newDriverGroups: List<DriverGroup>) {
|
||||||
|
driverGroups = newDriverGroups
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,267 @@
|
||||||
|
package org.yuzu.yuzu_emu.features.fetcher
|
||||||
|
|
||||||
|
import android.animation.LayoutTransition
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.text.Html
|
||||||
|
import android.text.Html.FROM_HTML_MODE_COMPACT
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.databinding.ItemReleaseBinding
|
||||||
|
import org.yuzu.yuzu_emu.fragments.DriverFetcherFragment.Release
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import androidx.transition.ChangeBounds
|
||||||
|
import androidx.transition.Fade
|
||||||
|
import androidx.transition.TransitionManager
|
||||||
|
import androidx.transition.TransitionSet
|
||||||
|
import com.google.android.material.color.MaterialColors
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import org.commonmark.parser.Parser
|
||||||
|
import org.commonmark.renderer.html.HtmlRenderer
|
||||||
|
import org.yuzu.yuzu_emu.databinding.DialogProgressBinding
|
||||||
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
|
import org.yuzu.yuzu_emu.utils.FileUtil
|
||||||
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class ReleaseAdapter(
|
||||||
|
private val releases: List<Release>,
|
||||||
|
private val activity: FragmentActivity,
|
||||||
|
private val driverViewModel: DriverViewModel
|
||||||
|
) : RecyclerView.Adapter<ReleaseAdapter.ReleaseViewHolder>() {
|
||||||
|
|
||||||
|
inner class ReleaseViewHolder(
|
||||||
|
private val binding: ItemReleaseBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
private var isPreview: Boolean = true
|
||||||
|
private val client = OkHttpClient()
|
||||||
|
private val markdownParser = Parser.builder().build()
|
||||||
|
private val htmlRenderer = HtmlRenderer.builder().build()
|
||||||
|
|
||||||
|
init {
|
||||||
|
binding.root.let { root ->
|
||||||
|
val layoutTransition = root.layoutTransition ?: LayoutTransition().apply {
|
||||||
|
enableTransitionType(LayoutTransition.CHANGING)
|
||||||
|
setDuration(125)
|
||||||
|
}
|
||||||
|
root.layoutTransition = layoutTransition
|
||||||
|
}
|
||||||
|
|
||||||
|
(binding.textBody.parent as ViewGroup).isTransitionGroup = false
|
||||||
|
binding.containerDownloads.isTransitionGroup = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(release: Release) {
|
||||||
|
binding.textReleaseName.text = release.title
|
||||||
|
binding.badgeLatest.isVisible = release.latest
|
||||||
|
|
||||||
|
// truncates to 150 chars so it does not take up too much space.
|
||||||
|
var bodyPreview = release.body.take(150)
|
||||||
|
bodyPreview = bodyPreview.replace("#", "").removeSurrounding(" ");
|
||||||
|
|
||||||
|
val body =
|
||||||
|
bodyPreview.replace("\\r\\n", "\n").replace("\\n", "\n").replace("\n", "<br>")
|
||||||
|
|
||||||
|
binding.textBody.text = Html.fromHtml(body, FROM_HTML_MODE_COMPACT)
|
||||||
|
|
||||||
|
binding.textBody.setOnClickListener {
|
||||||
|
TransitionManager.beginDelayedTransition(
|
||||||
|
binding.root,
|
||||||
|
TransitionSet().addTransition(Fade()).addTransition(ChangeBounds())
|
||||||
|
.setDuration(100)
|
||||||
|
)
|
||||||
|
|
||||||
|
isPreview = !isPreview
|
||||||
|
if (isPreview) {
|
||||||
|
val body = bodyPreview.replace("\\r\\n", "\n").replace("\\n", "\n")
|
||||||
|
.replace("\n", "<br>")
|
||||||
|
|
||||||
|
binding.textBody.text = Html.fromHtml(body, FROM_HTML_MODE_COMPACT)
|
||||||
|
binding.textBody.maxLines = 3
|
||||||
|
binding.textBody.ellipsize = TextUtils.TruncateAt.END
|
||||||
|
} else {
|
||||||
|
val body = release.body.replace("\\r\\n", "\n\n").replace("\\n", "\n\n")
|
||||||
|
|
||||||
|
try {
|
||||||
|
val doc = markdownParser.parse(body)
|
||||||
|
val html = htmlRenderer.render(doc)
|
||||||
|
binding.textBody.text = Html.fromHtml(html, Html.FROM_HTML_MODE_COMPACT)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
binding.textBody.text = body
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.textBody.maxLines = Integer.MAX_VALUE
|
||||||
|
binding.textBody.ellipsize = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val onDownloadsClick = {
|
||||||
|
val isVisible = binding.containerDownloads.isVisible
|
||||||
|
TransitionManager.beginDelayedTransition(
|
||||||
|
binding.root,
|
||||||
|
TransitionSet().addTransition(Fade()).addTransition(ChangeBounds())
|
||||||
|
.setDuration(100)
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.containerDownloads.isVisible = !isVisible
|
||||||
|
|
||||||
|
binding.imageDownloadsArrow.rotation = if (isVisible) 0f else 180f
|
||||||
|
binding.buttonToggleDownloads.text =
|
||||||
|
if (isVisible) activity.getString(R.string.show_downloads)
|
||||||
|
else activity.getString(R.string.hide_downloads)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.buttonToggleDownloads.setOnClickListener {
|
||||||
|
onDownloadsClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.imageDownloadsArrow.setOnClickListener {
|
||||||
|
onDownloadsClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.containerDownloads.removeAllViews()
|
||||||
|
|
||||||
|
release.artifacts.forEach { artifact ->
|
||||||
|
val button = MaterialButton(binding.root.context).apply {
|
||||||
|
text = artifact.name
|
||||||
|
setTextAppearance(com.google.android.material.R.style.TextAppearance_Material3_LabelLarge)
|
||||||
|
textAlignment = MaterialButton.TEXT_ALIGNMENT_VIEW_START
|
||||||
|
setBackgroundColor(context.getColor(com.google.android.material.R.color.m3_button_background_color_selector))
|
||||||
|
setIconResource(R.drawable.ic_import)
|
||||||
|
iconTint = ColorStateList.valueOf(
|
||||||
|
MaterialColors.getColor(
|
||||||
|
this,
|
||||||
|
com.google.android.material.R.attr.colorPrimary
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
elevation = 6f
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
setOnClickListener {
|
||||||
|
val dialogBinding =
|
||||||
|
DialogProgressBinding.inflate(LayoutInflater.from(context))
|
||||||
|
dialogBinding.progressBar.isIndeterminate = true
|
||||||
|
dialogBinding.title.text = context.getString(R.string.installing_driver)
|
||||||
|
dialogBinding.status.text = context.getString(R.string.downloading)
|
||||||
|
|
||||||
|
val progressDialog = MaterialAlertDialogBuilder(context)
|
||||||
|
.setView(dialogBinding.root)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
progressDialog.show()
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
try {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(artifact.url)
|
||||||
|
.header("Accept", "application/octet-stream")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val cacheDir = context.externalCacheDir ?: throw IOException(
|
||||||
|
context.getString(R.string.failed_cache_dir)
|
||||||
|
)
|
||||||
|
|
||||||
|
cacheDir.mkdirs()
|
||||||
|
|
||||||
|
val file = File(cacheDir, artifact.name)
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
client.newBuilder()
|
||||||
|
.followRedirects(true)
|
||||||
|
.followSslRedirects(true)
|
||||||
|
.build()
|
||||||
|
.newCall(request).execute().use { response ->
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
throw IOException("${response.code}")
|
||||||
|
}
|
||||||
|
|
||||||
|
response.body?.byteStream()?.use { input ->
|
||||||
|
FileOutputStream(file).use { output ->
|
||||||
|
input.copyTo(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?: throw IOException(context.getString(R.string.empty_response_body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.length() == 0L) {
|
||||||
|
throw IOException(context.getString(R.string.driver_empty))
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogBinding.status.text = context.getString(R.string.installing)
|
||||||
|
|
||||||
|
val driverData = GpuDriverHelper.getMetadataFromZip(file)
|
||||||
|
val driverPath =
|
||||||
|
"${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(file.toUri())}"
|
||||||
|
|
||||||
|
if (GpuDriverHelper.copyDriverToInternalStorage(file.toUri())) {
|
||||||
|
driverViewModel.onDriverAdded(Pair(driverPath, driverData))
|
||||||
|
|
||||||
|
progressDialog.dismiss()
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
context.getString(
|
||||||
|
R.string.successfully_installed,
|
||||||
|
driverData.name
|
||||||
|
),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} else {
|
||||||
|
throw IOException(
|
||||||
|
context.getString(
|
||||||
|
R.string.failed_install_driver,
|
||||||
|
artifact.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
progressDialog.dismiss()
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle(context.getString(R.string.driver_failed_title))
|
||||||
|
.setMessage(e.message)
|
||||||
|
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||||
|
dialog.cancel()
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.containerDownloads.addView(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReleaseViewHolder {
|
||||||
|
val binding = ItemReleaseBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context), parent, false
|
||||||
|
)
|
||||||
|
return ReleaseViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ReleaseViewHolder, position: Int) {
|
||||||
|
holder.bind(releases[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = releases.size
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.yuzu.yuzu_emu.features.fetcher
|
||||||
|
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
||||||
|
class SpacingItemDecoration(private val spacing: Int) : RecyclerView.ItemDecoration() {
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: RecyclerView,
|
||||||
|
state: RecyclerView.State
|
||||||
|
) {
|
||||||
|
outRect.bottom = spacing
|
||||||
|
if (parent.getChildAdapterPosition(view) == 0) {
|
||||||
|
outRect.top = spacing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ object Settings {
|
||||||
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
||||||
|
|
||||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||||
|
const val PREF_SHOULD_SHOW_DRIVER_WARNING = "ShouldShowDriverWarning"
|
||||||
const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning"
|
const val PREF_SHOULD_SHOW_PRE_ALPHA_WARNING = "ShouldShowPreAlphaWarning"
|
||||||
const val PREF_SHOULD_SHOW_PRE_ALPHA_BANNER = "ShouldShowPreAlphaBanner"
|
const val PREF_SHOULD_SHOW_PRE_ALPHA_BANNER = "ShouldShowPreAlphaBanner"
|
||||||
const val PREF_SHOULD_SHOW_EDENS_VEIL_DIALOG = "ShouldShowEdensVeilDialog"
|
const val PREF_SHOULD_SHOW_EDENS_VEIL_DIALOG = "ShouldShowEdensVeilDialog"
|
||||||
|
|
|
@ -0,0 +1,307 @@
|
||||||
|
package org.yuzu.yuzu_emu.fragments
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.view.updatePadding
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import org.yuzu.yuzu_emu.R
|
||||||
|
import org.yuzu.yuzu_emu.databinding.FragmentDriverFetcherBinding
|
||||||
|
import org.yuzu.yuzu_emu.features.fetcher.DriverGroupAdapter
|
||||||
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
|
import org.yuzu.yuzu_emu.utils.Log
|
||||||
|
import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.URL
|
||||||
|
import kotlin.getValue
|
||||||
|
|
||||||
|
class DriverFetcherFragment : Fragment() {
|
||||||
|
private var _binding: FragmentDriverFetcherBinding? = null
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val client = OkHttpClient()
|
||||||
|
|
||||||
|
private val gpuModel: String?
|
||||||
|
get() = GpuDriverHelper.getGpuModel()
|
||||||
|
|
||||||
|
private val adrenoModel: Int
|
||||||
|
get() = parseAdrenoModel()
|
||||||
|
|
||||||
|
private val recommendedDriver: String
|
||||||
|
get() = driverMap.firstOrNull { adrenoModel in it.first }?.second ?: "Unsupported"
|
||||||
|
|
||||||
|
private data class DriverRepo(
|
||||||
|
val name: String = "",
|
||||||
|
val path: String = "",
|
||||||
|
val sort: Int = 0,
|
||||||
|
val useTagName: Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
private val repoList: List<DriverRepo> = listOf(
|
||||||
|
DriverRepo("Mr. Purple Turnip", "MrPurple666/purple-turnip", 0),
|
||||||
|
DriverRepo("GameHub Adreno 8xx", "crueter/GameHub-8Elite-Drivers", 1),
|
||||||
|
DriverRepo("KIMCHI Turnip", "K11MCH1/AdrenoToolsDrivers", 2, true),
|
||||||
|
DriverRepo("Weab-Chan Freedreno", "Weab-chan/freedreno_turnip-CI", 3),
|
||||||
|
)
|
||||||
|
|
||||||
|
private val driverMap = listOf(
|
||||||
|
IntRange(Integer.MIN_VALUE, 9) to "Unsupported",
|
||||||
|
IntRange(10, 99) to "KIMCHI Latest",
|
||||||
|
IntRange(100, 599) to "Unsupported",
|
||||||
|
IntRange(600, 639) to "Mr. Purple EOL-24.3.4",
|
||||||
|
IntRange(640, 699) to "Mr. Purple T19",
|
||||||
|
IntRange(700, 799) to "Mr. Purple T20", // TODO: Await T21 and update accordingly
|
||||||
|
IntRange(800, 899) to "GameHub Adreno 8xx",
|
||||||
|
IntRange(900, Int.MAX_VALUE) to "Unsupported",
|
||||||
|
)
|
||||||
|
|
||||||
|
private lateinit var driverGroupAdapter: DriverGroupAdapter
|
||||||
|
private val driverViewModel: DriverViewModel by activityViewModels()
|
||||||
|
|
||||||
|
fun parseAdrenoModel(): Int {
|
||||||
|
if (gpuModel == null) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val modelList = gpuModel!!.split(" ")
|
||||||
|
|
||||||
|
// format: Adreno (TM) <ModelNumber>
|
||||||
|
if (modelList.size < 3 || modelList[0] != "Adreno") {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val model = modelList[2]
|
||||||
|
|
||||||
|
try {
|
||||||
|
// special case for Axx GPUs (e.g. AYANEO Pocket S2)
|
||||||
|
// driverMap has specific ranges for this
|
||||||
|
// needs to be fixed
|
||||||
|
if (model.startsWith("A")) {
|
||||||
|
return model.substring(1).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
return model.toInt()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// Model parse error, just say unsupported
|
||||||
|
e.printStackTrace()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = FragmentDriverFetcherBinding.inflate(inflater)
|
||||||
|
binding.badgeRecommendedDriver.text = recommendedDriver
|
||||||
|
binding.badgeGpuModel.text = gpuModel
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.toolbarDrivers.setNavigationOnClickListener {
|
||||||
|
binding.root.findNavController().popBackStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.listDrivers.layoutManager = LinearLayoutManager(context)
|
||||||
|
driverGroupAdapter = DriverGroupAdapter(requireActivity(), driverViewModel)
|
||||||
|
binding.listDrivers.adapter = driverGroupAdapter
|
||||||
|
|
||||||
|
setInsets()
|
||||||
|
|
||||||
|
fetchDrivers()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchDrivers() {
|
||||||
|
binding.loadingIndicator.isVisible = true
|
||||||
|
|
||||||
|
val driverGroups = arrayListOf<DriverGroup>()
|
||||||
|
|
||||||
|
repoList.forEach { driver ->
|
||||||
|
val name = driver.name
|
||||||
|
val path = driver.path
|
||||||
|
val useTagName = driver.useTagName
|
||||||
|
val sort = driver.sort
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://api.github.com/repos/$path/releases")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
var releases: ArrayList<Release>
|
||||||
|
try {
|
||||||
|
client.newCall(request).execute().use { response ->
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
throw IOException(response.body.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
val body = response.body?.string() ?: return@withContext
|
||||||
|
releases = Release.fromJsonArray(body, useTagName)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
MaterialAlertDialogBuilder(requireActivity().applicationContext)
|
||||||
|
.setTitle(getString(R.string.error_during_fetch))
|
||||||
|
.setMessage("${getString(R.string.failed_to_fetch)} ${name}:\n${e.message}")
|
||||||
|
.setPositiveButton(getString(R.string.ok)) { dialog, _ -> dialog.cancel() }
|
||||||
|
.show()
|
||||||
|
|
||||||
|
releases = ArrayList<Release>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val driver = DriverGroup(
|
||||||
|
name,
|
||||||
|
releases,
|
||||||
|
sort
|
||||||
|
)
|
||||||
|
|
||||||
|
synchronized(driverGroups) {
|
||||||
|
driverGroups.add(driver)
|
||||||
|
driverGroups.sortBy {
|
||||||
|
it.sort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
driverGroupAdapter.updateDriverGroups(driverGroups)
|
||||||
|
|
||||||
|
if (driverGroups.size >= repoList.size) {
|
||||||
|
binding.loadingIndicator.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setInsets() =
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
|
binding.root
|
||||||
|
) { _: View, windowInsets: WindowInsetsCompat ->
|
||||||
|
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||||
|
|
||||||
|
val leftInsets = barInsets.left + cutoutInsets.left
|
||||||
|
val rightInsets = barInsets.right + cutoutInsets.right
|
||||||
|
|
||||||
|
binding.toolbarDrivers.updateMargins(left = leftInsets, right = rightInsets)
|
||||||
|
binding.listDrivers.updateMargins(left = leftInsets, right = rightInsets)
|
||||||
|
|
||||||
|
binding.listDrivers.updatePadding(
|
||||||
|
bottom = barInsets.bottom +
|
||||||
|
resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab)
|
||||||
|
)
|
||||||
|
|
||||||
|
windowInsets
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Artifact(val url: URL, val name: String)
|
||||||
|
|
||||||
|
data class Release(
|
||||||
|
var tagName: String = "",
|
||||||
|
var title: String = "",
|
||||||
|
var body: String = "",
|
||||||
|
var artifacts: List<Artifact> = ArrayList<Artifact>(),
|
||||||
|
var prerelease: Boolean = false,
|
||||||
|
var latest: Boolean = false
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
fun fromJsonArray(jsonString: String, useTagName: Boolean): ArrayList<Release> {
|
||||||
|
val mapper = jacksonObjectMapper()
|
||||||
|
|
||||||
|
try {
|
||||||
|
val rootNode = mapper.readTree(jsonString)
|
||||||
|
|
||||||
|
val releases = ArrayList<Release>()
|
||||||
|
|
||||||
|
var latestRelease: Release? = null
|
||||||
|
|
||||||
|
if (rootNode.isArray) {
|
||||||
|
rootNode.forEach { node ->
|
||||||
|
val release = fromJson(node, useTagName)
|
||||||
|
|
||||||
|
if (latestRelease == null && !release.prerelease) {
|
||||||
|
latestRelease = release
|
||||||
|
release.latest = true
|
||||||
|
}
|
||||||
|
|
||||||
|
releases.add(release)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return releases
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
return ArrayList<Release>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromJson(node: JsonNode, useTagName: Boolean): Release {
|
||||||
|
try {
|
||||||
|
val tagName = node.get("tag_name").toString().removeSurrounding("\"")
|
||||||
|
val body = node.get("body").toString().removeSurrounding("\"")
|
||||||
|
val prerelease = node.get("prerelease").toString().toBoolean()
|
||||||
|
val title = if (useTagName) tagName else node.get("name").toString().removeSurrounding("\"")
|
||||||
|
|
||||||
|
val assets = node.get("assets")
|
||||||
|
val artifacts = ArrayList<Artifact>()
|
||||||
|
if (assets?.isArray == true) {
|
||||||
|
assets.forEach { node ->
|
||||||
|
val urlStr =
|
||||||
|
node.get("browser_download_url").toString().removeSurrounding("\"")
|
||||||
|
|
||||||
|
val url = URL(urlStr)
|
||||||
|
val name = node.get("name").toString().removeSurrounding("\"")
|
||||||
|
|
||||||
|
val artifact = Artifact(url, name)
|
||||||
|
artifacts.add(artifact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Release(tagName, title, body, artifacts, prerelease)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// TODO: handle malformed input.
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class DriverGroup(
|
||||||
|
val name: String,
|
||||||
|
val releases: ArrayList<Release>,
|
||||||
|
val sort: Int,
|
||||||
|
)
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.core.content.edit
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
|
@ -15,6 +16,7 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -23,6 +25,8 @@ import kotlinx.coroutines.withContext
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.adapters.DriverAdapter
|
import org.yuzu.yuzu_emu.adapters.DriverAdapter
|
||||||
import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding
|
import org.yuzu.yuzu_emu.databinding.FragmentDriverManagerBinding
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||||
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
||||||
import org.yuzu.yuzu_emu.model.DriverViewModel
|
import org.yuzu.yuzu_emu.model.DriverViewModel
|
||||||
|
@ -103,6 +107,10 @@ class DriverManagerFragment : Fragment() {
|
||||||
getDriver.launch(arrayOf("application/zip"))
|
getDriver.launch(arrayOf("application/zip"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.buttonFetch.setOnClickListener {
|
||||||
|
binding.root.findNavController().navigate(R.id.action_driverManagerFragment_to_driverFetcherFragment)
|
||||||
|
}
|
||||||
|
|
||||||
binding.listDrivers.apply {
|
binding.listDrivers.apply {
|
||||||
layoutManager = GridLayoutManager(
|
layoutManager = GridLayoutManager(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
|
@ -112,6 +120,10 @@ class DriverManagerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
setInsets()
|
setInsets()
|
||||||
|
|
||||||
|
if (!GpuDriverHelper.supportsCustomDriverLoading()) {
|
||||||
|
showDriverWarningDialog()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -139,6 +151,12 @@ class DriverManagerFragment : Fragment() {
|
||||||
bottom = barInsets.bottom + fabSpacing
|
bottom = barInsets.bottom + fabSpacing
|
||||||
)
|
)
|
||||||
|
|
||||||
|
binding.buttonFetch.updateMargins(
|
||||||
|
left = leftInsets + fabSpacing,
|
||||||
|
right = rightInsets + fabSpacing,
|
||||||
|
bottom = barInsets.bottom + fabSpacing
|
||||||
|
)
|
||||||
|
|
||||||
binding.listDrivers.updatePadding(
|
binding.listDrivers.updatePadding(
|
||||||
bottom = barInsets.bottom +
|
bottom = barInsets.bottom +
|
||||||
resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab)
|
resources.getDimensionPixelSize(R.dimen.spacing_bottom_list_fab)
|
||||||
|
@ -195,4 +213,26 @@ class DriverManagerFragment : Fragment() {
|
||||||
return@newInstance Any()
|
return@newInstance Any()
|
||||||
}.show(childFragmentManager, ProgressDialogFragment.TAG)
|
}.show(childFragmentManager, ProgressDialogFragment.TAG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showDriverWarningDialog() {
|
||||||
|
val shouldDisplayGpuWarning =
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
|
.getBoolean(Settings.PREF_SHOULD_SHOW_DRIVER_WARNING, true)
|
||||||
|
if (shouldDisplayGpuWarning) {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
activity,
|
||||||
|
titleId = R.string.unsupported_gpu,
|
||||||
|
descriptionId = R.string.unsupported_gpu_warning,
|
||||||
|
positiveButtonTitleId = R.string.dont_show_again,
|
||||||
|
negativeButtonTitleId = R.string.close,
|
||||||
|
showNegativeButton = true,
|
||||||
|
positiveAction = {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
|
.edit() {
|
||||||
|
putBoolean(Settings.PREF_SHOULD_SHOW_DRIVER_WARNING, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).show(requireActivity().supportFragmentManager, MessageDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ class HomeSettingsFragment : Fragment() {
|
||||||
.actionHomeSettingsFragmentToDriverManagerFragment(null)
|
.actionHomeSettingsFragmentToDriverManagerFragment(null)
|
||||||
binding.root.findNavController().navigate(action)
|
binding.root.findNavController().navigate(action)
|
||||||
},
|
},
|
||||||
{ GpuDriverHelper.supportsCustomDriverLoading() },
|
{true},
|
||||||
R.string.custom_driver_not_supported,
|
R.string.custom_driver_not_supported,
|
||||||
R.string.custom_driver_not_supported_description,
|
R.string.custom_driver_not_supported_description,
|
||||||
driverViewModel.selectedDriverTitle
|
driverViewModel.selectedDriverTitle
|
||||||
|
|
|
@ -455,7 +455,7 @@ class GamesFragment : Fragment() {
|
||||||
val leftInsets = barInsets.left + cutoutInsets.left
|
val leftInsets = barInsets.left + cutoutInsets.left
|
||||||
val rightInsets = barInsets.right + cutoutInsets.right
|
val rightInsets = barInsets.right + cutoutInsets.right
|
||||||
val mlpSwipe = binding.swipeRefresh.layoutParams as ViewGroup.MarginLayoutParams
|
val mlpSwipe = binding.swipeRefresh.layoutParams as ViewGroup.MarginLayoutParams
|
||||||
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
|
if (view.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
|
||||||
mlpSwipe.leftMargin = leftInsets
|
mlpSwipe.leftMargin = leftInsets
|
||||||
mlpSwipe.rightMargin = rightInsets
|
mlpSwipe.rightMargin = rightInsets
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -25,13 +25,10 @@ import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.ui.setupWithNavController
|
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import com.google.android.material.navigation.NavigationBarView
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FilenameFilter
|
import java.io.FilenameFilter
|
||||||
import org.yuzu.yuzu_emu.HomeNavigationDirections
|
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets
|
||||||
import java.util.zip.Deflater
|
import java.util.zip.Deflater
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
import kotlin.IllegalStateException
|
import kotlin.IllegalStateException
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
object FileUtil {
|
object FileUtil {
|
||||||
const val PATH_TREE = "tree"
|
const val PATH_TREE = "tree"
|
||||||
|
@ -195,6 +196,10 @@ object FileUtil {
|
||||||
* @return String display name
|
* @return String display name
|
||||||
*/
|
*/
|
||||||
fun getFilename(uri: Uri): String {
|
fun getFilename(uri: Uri): String {
|
||||||
|
if (uri.scheme == "file") {
|
||||||
|
return uri.lastPathSegment?.takeIf { it.isNotEmpty() } ?: throw IOException("Invalid file URI: $uri")
|
||||||
|
}
|
||||||
|
|
||||||
val resolver = YuzuApplication.appContext.contentResolver
|
val resolver = YuzuApplication.appContext.contentResolver
|
||||||
val columns = arrayOf(
|
val columns = arrayOf(
|
||||||
DocumentsContract.Document.COLUMN_DISPLAY_NAME
|
DocumentsContract.Document.COLUMN_DISPLAY_NAME
|
||||||
|
@ -236,7 +241,7 @@ object FileUtil {
|
||||||
var size: Long = 0
|
var size: Long = 0
|
||||||
var c: Cursor? = null
|
var c: Cursor? = null
|
||||||
try {
|
try {
|
||||||
val mUri = Uri.parse(path)
|
val mUri = path.toUri()
|
||||||
c = resolver.query(mUri, columns, null, null, null)
|
c = resolver.query(mUri, columns, null, null, null)
|
||||||
c!!.moveToNext()
|
c!!.moveToNext()
|
||||||
size = c.getLong(0)
|
size = c.getLong(0)
|
||||||
|
|
|
@ -202,6 +202,11 @@ object GpuDriverHelper {
|
||||||
hookLibPath: String = GpuDriverHelper.hookLibPath!!
|
hookLibPath: String = GpuDriverHelper.hookLibPath!!
|
||||||
): Array<String>?
|
): Array<String>?
|
||||||
|
|
||||||
|
external fun getGpuModel(
|
||||||
|
surface: Surface = Surface(SurfaceTexture(true)),
|
||||||
|
hookLibPath: String = GpuDriverHelper.hookLibPath!!
|
||||||
|
): String?
|
||||||
|
|
||||||
// Parse the custom driver metadata to retrieve the name.
|
// Parse the custom driver metadata to retrieve the name.
|
||||||
val installedCustomDriverData: GpuDriverMetadata
|
val installedCustomDriverData: GpuDriverMetadata
|
||||||
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
|
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
|
||||||
|
|
|
@ -567,6 +567,30 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo(
|
||||||
return j_driver_info;
|
return j_driver_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jstring Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getGpuModel(JNIEnv *env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) {
|
||||||
|
const char* file_redirect_dir_{};
|
||||||
|
int featureFlags{};
|
||||||
|
std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir);
|
||||||
|
auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
|
||||||
|
nullptr, nullptr, file_redirect_dir_, nullptr);
|
||||||
|
auto driver_library = std::make_shared<Common::DynamicLibrary>(handle);
|
||||||
|
InputCommon::InputSubsystem input_subsystem;
|
||||||
|
auto window =
|
||||||
|
std::make_unique<EmuWindow_Android>(ANativeWindow_fromSurface(env, j_surf), driver_library);
|
||||||
|
|
||||||
|
Vulkan::vk::InstanceDispatch dld;
|
||||||
|
Vulkan::vk::Instance vk_instance = Vulkan::CreateInstance(
|
||||||
|
*driver_library, dld, VK_API_VERSION_1_1, Core::Frontend::WindowSystemType::Android);
|
||||||
|
|
||||||
|
auto surface = Vulkan::CreateSurface(vk_instance, window->GetWindowInfo());
|
||||||
|
|
||||||
|
auto device = Vulkan::CreateDevice(vk_instance, dld, *surface);
|
||||||
|
|
||||||
|
const std::string model_name{device.GetModelName()};
|
||||||
|
|
||||||
|
return Common::Android::ToJString(env, model_name);
|
||||||
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) {
|
||||||
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||||
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
|
return static_cast<jboolean>(Core::Crypto::KeyManager::Instance().AreKeysLoaded());
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M7,10l5,5 5,-5" />
|
||||||
|
</vector>
|
14
src/android/app/src/main/res/drawable/item_release_box.xml
Normal file
14
src/android/app/src/main/res/drawable/item_release_box.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/colorSurface" />
|
||||||
|
<stroke
|
||||||
|
android:width="1dp"
|
||||||
|
android:color="?attr/colorOutline" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<padding
|
||||||
|
android:left="12dp"
|
||||||
|
android:top="12dp"
|
||||||
|
android:right="12dp"
|
||||||
|
android:bottom="12dp" />
|
||||||
|
</shape>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/colorSurfaceVariant" />
|
||||||
|
<corners android:radius="8dp" />
|
||||||
|
<padding
|
||||||
|
android:left="8dp"
|
||||||
|
android:right="8dp"
|
||||||
|
android:top="0dp"
|
||||||
|
android:bottom="0dp" />
|
||||||
|
</shape>
|
34
src/android/app/src/main/res/layout/dialog_progress.xml
Normal file
34
src/android/app/src/main/res/layout/dialog_progress.xml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/dialog_progress_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||||
|
android:textColor="?attr/colorPrimary" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/status"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textAppearance="?attr/textAppearanceBody1"
|
||||||
|
android:textColor="?attr/colorOnSurface" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
116
src/android/app/src/main/res/layout/fragment_driver_fetcher.xml
Normal file
116
src/android/app/src/main/res/layout/fragment_driver_fetcher.xml
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/coordinator_licenses"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appbar_drivers"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
|
||||||
|
app:liftOnScrollTargetViewId="@id/list_drivers">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar_drivers"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:touchscreenBlocksFocus="false"
|
||||||
|
app:navigationIcon="@drawable/ic_back"
|
||||||
|
app:title="@string/gpu_driver_fetcher" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_gpu_model"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:text="@string/gpu_model"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/appbar_drivers" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/badge_gpu_model"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="@drawable/item_release_latest_badge_background"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/label_gpu_model"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/label_gpu_model"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/label_gpu_model" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/label_recommended_driver"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:text="@string/recommended_driver"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/label_gpu_model" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/badge_recommended_driver"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:background="@drawable/item_release_latest_badge_background"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/label_recommended_driver"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/label_recommended_driver"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/label_recommended_driver" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:background="?attr/colorOutline"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/label_recommended_driver" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/list_drivers"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/divider"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loadingIndicator"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/list_drivers"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/list_drivers"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/list_drivers" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,6 +7,7 @@
|
||||||
android:background="?attr/colorSurface">
|
android:background="?attr/colorSurface">
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/coordinatorLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
@ -47,4 +48,14 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/button_fetch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|start"
|
||||||
|
android:text="@string/fetch"
|
||||||
|
app:icon="@drawable/ic_import"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
39
src/android/app/src/main/res/layout/item_driver_group.xml
Normal file
39
src/android/app/src/main/res/layout/item_driver_group.xml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_group_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="?attr/colorControlNormal"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/image_dropdown_arrow" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_dropdown_arrow"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:src="@drawable/ic_dropdown_arrow"
|
||||||
|
app:tint="?attr/colorControlNormal"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
android:contentDescription="@string/show_releases" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_releases"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/text_group_name"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
82
src/android/app/src/main/res/layout/item_release.xml
Normal file
82
src/android/app/src/main/res/layout/item_release.xml
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/item_release_box"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_release_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/badge_latest"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/latest"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:background="@drawable/item_release_latest_badge_background"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/text_release_name"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/text_release_name"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/text_release_name"
|
||||||
|
android:layout_marginStart="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_body"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/text_release_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/button_toggle_downloads"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/show_downloads"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/text_body"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_downloads_arrow"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:contentDescription="@string/show_downloads"
|
||||||
|
android:src="@drawable/ic_dropdown_arrow"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/button_toggle_downloads"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/button_toggle_downloads"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/button_toggle_downloads"
|
||||||
|
app:tint="?attr/colorControlNormal" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/container_downloads"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/button_toggle_downloads"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
android:layout_marginTop="8dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/home_navigation"
|
android:id="@+id/home_navigation"
|
||||||
app:startDestination="@id/gamesFragment">
|
app:startDestination="@id/gamesFragment">
|
||||||
|
|
||||||
|
@ -111,6 +112,9 @@
|
||||||
app:argType="org.yuzu.yuzu_emu.model.Game"
|
app:argType="org.yuzu.yuzu_emu.model.Game"
|
||||||
app:nullable="true"
|
app:nullable="true"
|
||||||
android:defaultValue="@null" />
|
android:defaultValue="@null" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_driverManagerFragment_to_driverFetcherFragment"
|
||||||
|
app:destination="@id/driverFetcherFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/appletLauncherFragment"
|
android:id="@+id/appletLauncherFragment"
|
||||||
|
@ -164,5 +168,10 @@
|
||||||
android:name="game"
|
android:name="game"
|
||||||
app:argType="org.yuzu.yuzu_emu.model.Game" />
|
app:argType="org.yuzu.yuzu_emu.model.Game" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/driverFetcherFragment"
|
||||||
|
android:name="org.yuzu.yuzu_emu.fragments.DriverFetcherFragment"
|
||||||
|
android:label="fragment_driver_fetcher"
|
||||||
|
tools:layout="@layout/fragment_driver_fetcher" />
|
||||||
|
|
||||||
</navigation>
|
</navigation>
|
||||||
|
|
|
@ -365,17 +365,6 @@
|
||||||
<string name="user_data_import_success">تم استيراد بيانات المستخدم بنجاح</string>
|
<string name="user_data_import_success">تم استيراد بيانات المستخدم بنجاح</string>
|
||||||
<string name="user_data_export_cancelled">تم إلغاء التصدير</string>
|
<string name="user_data_export_cancelled">تم إلغاء التصدير</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">الوصول المبكر</string>
|
|
||||||
<string name="early_access_benefits">مزايا الوصول المبكر</string>
|
|
||||||
<string name="cutting_edge_features">ميزات متطورة</string>
|
|
||||||
<string name="early_access_updates">الوصول المبكر إلى التحديثات</string>
|
|
||||||
<string name="no_manual_installation">لا يوجد التثبيت اليدوي</string>
|
|
||||||
<string name="prioritized_support">الدعم ذو الأولوية</string>
|
|
||||||
<string name="helping_game_preservation">المساعدة في الحفاظ على اللعبة</string>
|
|
||||||
<string name="our_eternal_gratitude">امتناننا الأبدي</string>
|
|
||||||
<string name="are_you_interested">هل انت مهتم؟</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">الحد من السرعة</string>
|
<string name="frame_limit_enable">الحد من السرعة</string>
|
||||||
<string name="frame_limit_enable_description">يحد من سرعة المحاكاة بنسبة محددة من السرعة العادية</string>
|
<string name="frame_limit_enable_description">يحد من سرعة المحاكاة بنسبة محددة من السرعة العادية</string>
|
||||||
|
|
|
@ -334,17 +334,6 @@
|
||||||
<string name="licenses_description">ئەو پڕۆژانەی کە یوزوی بۆ ئەندرۆید ڕەخساند</string>
|
<string name="licenses_description">ئەو پڕۆژانەی کە یوزوی بۆ ئەندرۆید ڕەخساند</string>
|
||||||
<string name="build">بونیات</string>
|
<string name="build">بونیات</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">بەزوویی دەسپێگەشتن</string>
|
|
||||||
<string name="early_access_benefits">سوودەکانی بەزوویی دەسپێگەشتن</string>
|
|
||||||
<string name="cutting_edge_features">تایبەتمەندییە پێشکەوتووەکان</string>
|
|
||||||
<string name="early_access_updates">زوو دەستگەیشتن بە نوێکارییەکان</string>
|
|
||||||
<string name="no_manual_installation">چیتر دامەزراندنی دەستی نییە</string>
|
|
||||||
<string name="prioritized_support">پشتگیری لە پێشینە</string>
|
|
||||||
<string name="helping_game_preservation">یارمەتیدانی پاراستنی یارییەکان</string>
|
|
||||||
<string name="our_eternal_gratitude">سوپاس و پێزانینی هەمیشەییمان</string>
|
|
||||||
<string name="are_you_interested">ئایا تۆ خوازیاریت؟</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">سنووردارکردنی خێرایی</string>
|
<string name="frame_limit_enable">سنووردارکردنی خێرایی</string>
|
||||||
<string name="frame_limit_enable_description">خێرایی ئیمولەیشن سنووردار دەکات بۆ ڕێژەیەکی دیاریکراو لە خێرایی ئاسایی.</string>
|
<string name="frame_limit_enable_description">خێرایی ئیمولەیشن سنووردار دەکات بۆ ڕێژەیەکی دیاریکراو لە خێرایی ئاسایی.</string>
|
||||||
|
|
|
@ -326,10 +326,6 @@
|
||||||
<string name="user_data_import_success">Uživatelská data byla úspěšně importována.</string>
|
<string name="user_data_import_success">Uživatelská data byla úspěšně importována.</string>
|
||||||
<string name="user_data_export_cancelled">Export zrušen</string>
|
<string name="user_data_export_cancelled">Export zrušen</string>
|
||||||
|
|
||||||
<string name="no_manual_installation">Žádná manuální instalace</string>
|
|
||||||
<string name="prioritized_support">Prioritní podpora</string>
|
|
||||||
<string name="our_eternal_gratitude">Naše věčná vděčnost</string>
|
|
||||||
<string name="are_you_interested">Máte zájem?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Omezit rychlost</string>
|
<string name="frame_limit_enable">Omezit rychlost</string>
|
||||||
|
|
|
@ -358,17 +358,6 @@ Wirklich fortfahren?</string>
|
||||||
<string name="user_data_import_success">Nutzerdaten erfolgreich importiert</string>
|
<string name="user_data_import_success">Nutzerdaten erfolgreich importiert</string>
|
||||||
<string name="user_data_export_cancelled">Export abgebrochen</string>
|
<string name="user_data_export_cancelled">Export abgebrochen</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Early Access</string>
|
|
||||||
<string name="early_access_benefits">Early Access Vorteile</string>
|
|
||||||
<string name="cutting_edge_features">Neueste Features</string>
|
|
||||||
<string name="early_access_updates">Früherer Zugriff auf Updates</string>
|
|
||||||
<string name="no_manual_installation">Keine manuelle Installation</string>
|
|
||||||
<string name="prioritized_support">Priorisierte Unterstützung</string>
|
|
||||||
<string name="helping_game_preservation">Beitrag zur Erhaltung der Spiele</string>
|
|
||||||
<string name="our_eternal_gratitude">Unsere ewige Dankbarkeit</string>
|
|
||||||
<string name="are_you_interested">Bist du interessiert?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limitierte Geschwindigkeit</string>
|
<string name="frame_limit_enable">Limitierte Geschwindigkeit</string>
|
||||||
<string name="frame_limit_enable_description">Limitiert die Geschwindigkeit auf einen von dir festgelegten Prozentsatz.</string>
|
<string name="frame_limit_enable_description">Limitiert die Geschwindigkeit auf einen von dir festgelegten Prozentsatz.</string>
|
||||||
|
|
|
@ -390,17 +390,6 @@
|
||||||
<string name="user_data_export_cancelled">Exportación cancelada</string>
|
<string name="user_data_export_cancelled">Exportación cancelada</string>
|
||||||
<string name="user_data_import_failed_description">Asegúrese de que las carpetas de datos de usuario estén en la raíz de la carpeta del zip y contengan un archivo config en config/config.ini e inténtelo de nuevo.</string>
|
<string name="user_data_import_failed_description">Asegúrese de que las carpetas de datos de usuario estén en la raíz de la carpeta del zip y contengan un archivo config en config/config.ini e inténtelo de nuevo.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Early Access</string>
|
|
||||||
<string name="early_access_benefits">Beneficios Early Access</string>
|
|
||||||
<string name="cutting_edge_features">Características de vanguardia</string>
|
|
||||||
<string name="early_access_updates">Acceso anticipado a las actualizaciones</string>
|
|
||||||
<string name="no_manual_installation">Sin instalación manual</string>
|
|
||||||
<string name="prioritized_support">Soporte prioritario</string>
|
|
||||||
<string name="helping_game_preservation">Ayudarás a la preservación de juegos</string>
|
|
||||||
<string name="our_eternal_gratitude">Nuestra eterna gratitud</string>
|
|
||||||
<string name="are_you_interested">¿Estás interesado?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limitar velocidad</string>
|
<string name="frame_limit_enable">Limitar velocidad</string>
|
||||||
<string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje específico de la velocidad normal.</string>
|
<string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje específico de la velocidad normal.</string>
|
||||||
|
|
|
@ -388,17 +388,6 @@
|
||||||
<string name="user_data_export_cancelled">صدور لغو شد</string>
|
<string name="user_data_export_cancelled">صدور لغو شد</string>
|
||||||
<string name="user_data_import_failed_description">مطمئن شوید که پوشههای داده کاربر در ریشه پوشه zip و حاوی یک فایل پیکربندی در config/config.ini هستند سپس دوباره امتحان کنید.</string>
|
<string name="user_data_import_failed_description">مطمئن شوید که پوشههای داده کاربر در ریشه پوشه zip و حاوی یک فایل پیکربندی در config/config.ini هستند سپس دوباره امتحان کنید.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">دسترسی زودهنگام</string>
|
|
||||||
<string name="early_access_benefits">مزایای دسترسی زودهنگام</string>
|
|
||||||
<string name="cutting_edge_features">ویژگیهای پیشرفته</string>
|
|
||||||
<string name="early_access_updates">دسترسی زودهنگام به بروزرسانیها</string>
|
|
||||||
<string name="no_manual_installation">بدون نصب دستی</string>
|
|
||||||
<string name="prioritized_support">پشتیبانی اولویت بندی شده</string>
|
|
||||||
<string name="helping_game_preservation">کمک به حفظ بازی</string>
|
|
||||||
<string name="our_eternal_gratitude">سپاس ابدی ما</string>
|
|
||||||
<string name="are_you_interested">مشتاق هستید؟</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">محدودیت سرعت</string>
|
<string name="frame_limit_enable">محدودیت سرعت</string>
|
||||||
<string name="frame_limit_enable_description">سرعت شبیهسازی را به درصد مشخصی از سرعت عادی محدود میکند.</string>
|
<string name="frame_limit_enable_description">سرعت شبیهسازی را به درصد مشخصی از سرعت عادی محدود میکند.</string>
|
||||||
|
|
|
@ -390,17 +390,6 @@
|
||||||
<string name="user_data_export_cancelled">Exportation annulée</string>
|
<string name="user_data_export_cancelled">Exportation annulée</string>
|
||||||
<string name="user_data_import_failed_description">Assurez-vous que les dossiers de données utilisateur se trouvent à la racine du dossier ZIP et contiennent un fichier de configuration à config/config.ini, puis réessayez.</string>
|
<string name="user_data_import_failed_description">Assurez-vous que les dossiers de données utilisateur se trouvent à la racine du dossier ZIP et contiennent un fichier de configuration à config/config.ini, puis réessayez.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Early Access</string>
|
|
||||||
<string name="early_access_benefits">Avantages de l\'Early Access</string>
|
|
||||||
<string name="cutting_edge_features">Fonctionnalités de pointe</string>
|
|
||||||
<string name="early_access_updates">Accès anticipé aux mises à jour</string>
|
|
||||||
<string name="no_manual_installation">Pas d\'installation manuelle</string>
|
|
||||||
<string name="prioritized_support">Assistance prioritaire</string>
|
|
||||||
<string name="helping_game_preservation">Contribuer à la préservation des jeux</string>
|
|
||||||
<string name="our_eternal_gratitude">Notre gratitude éternelle</string>
|
|
||||||
<string name="are_you_interested">Es tu intéressé ?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limiter la vitesse</string>
|
<string name="frame_limit_enable">Limiter la vitesse</string>
|
||||||
<string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string>
|
<string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string>
|
||||||
|
|
|
@ -376,17 +376,6 @@
|
||||||
<string name="user_data_export_cancelled">ייצוא בוטל</string>
|
<string name="user_data_export_cancelled">ייצוא בוטל</string>
|
||||||
<string name="user_data_import_failed_description">ודא שנתוני המשתמש נמצאים בשורש קובץ ה zip ושהוא מכיל קובץ סידור ב config/config.ini ונסה שוב.</string>
|
<string name="user_data_import_failed_description">ודא שנתוני המשתמש נמצאים בשורש קובץ ה zip ושהוא מכיל קובץ סידור ב config/config.ini ונסה שוב.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">גישה מוקדמת</string>
|
|
||||||
<string name="early_access_benefits">יתרונות של גישה מקודמת</string>
|
|
||||||
<string name="cutting_edge_features">תכונות חותכות קצה</string>
|
|
||||||
<string name="early_access_updates">גישה מוקדמת לעדכונים</string>
|
|
||||||
<string name="no_manual_installation">ללא התקנה ידנית</string>
|
|
||||||
<string name="prioritized_support">תמיכה בעדיפות</string>
|
|
||||||
<string name="helping_game_preservation">עוזר בשמירת משחקים</string>
|
|
||||||
<string name="our_eternal_gratitude">התודה האינסופית שלנו</string>
|
|
||||||
<string name="are_you_interested">אתה מעוניין?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">הגבל מהירות</string>
|
<string name="frame_limit_enable">הגבל מהירות</string>
|
||||||
<string name="frame_limit_enable_description">מגביל את מהירות האמולציה לאחוז מהירות המבוקש מהמהירות הרגילה.</string>
|
<string name="frame_limit_enable_description">מגביל את מהירות האמולציה לאחוז מהירות המבוקש מהמהירות הרגילה.</string>
|
||||||
|
|
|
@ -385,16 +385,6 @@
|
||||||
<string name="user_data_export_cancelled">Exportálás megszakítva</string>
|
<string name="user_data_export_cancelled">Exportálás megszakítva</string>
|
||||||
<string name="user_data_import_failed_description">Ellenőrizd, hogy a felhasználói adatok mappái a zip mappa gyökerében vannak, és tartalmaznak egy konfig fájlt a config/config.ini címen, majd próbáld meg újra.</string>
|
<string name="user_data_import_failed_description">Ellenőrizd, hogy a felhasználói adatok mappái a zip mappa gyökerében vannak, és tartalmaznak egy konfig fájlt a config/config.ini címen, majd próbáld meg újra.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Korai hozzáférés</string>
|
|
||||||
<string name="early_access_benefits">Korai hozzáférés előnyei</string>
|
|
||||||
<string name="cutting_edge_features">Legújabb funkciók</string>
|
|
||||||
<string name="early_access_updates">Korai hozzáférés a frissítésekhez</string>
|
|
||||||
<string name="no_manual_installation">Automatikus telepítések</string>
|
|
||||||
<string name="prioritized_support">Priorizált támogatás</string>
|
|
||||||
<string name="our_eternal_gratitude">Valamint az örök hálánk</string>
|
|
||||||
<string name="are_you_interested">Érdekel a dolog?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Sebességkorlát</string>
|
<string name="frame_limit_enable">Sebességkorlát</string>
|
||||||
<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>
|
<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>
|
||||||
|
|
|
@ -386,17 +386,6 @@
|
||||||
<string name="user_data_export_cancelled">Ekspor Dibatalkan</string>
|
<string name="user_data_export_cancelled">Ekspor Dibatalkan</string>
|
||||||
<string name="user_data_import_failed_description">Pastikan folder data pengguna berada di akar folder zip dan berisi file konfigurasi di config/config.ini dan coba lagi.</string>
|
<string name="user_data_import_failed_description">Pastikan folder data pengguna berada di akar folder zip dan berisi file konfigurasi di config/config.ini dan coba lagi.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Akses lebih awal</string>
|
|
||||||
<string name="early_access_benefits">Manfaat Akses Awal</string>
|
|
||||||
<string name="cutting_edge_features">Fitur-fitur yang paling baru</string>
|
|
||||||
<string name="early_access_updates">Akses lebih awal untuk pembaruan</string>
|
|
||||||
<string name="no_manual_installation">Tidak ada instalasi manual</string>
|
|
||||||
<string name="prioritized_support">Dukungan yang diprioritaskan</string>
|
|
||||||
<string name="helping_game_preservation">Membantu pemeliharaan game</string>
|
|
||||||
<string name="our_eternal_gratitude">Ucapan terima kasih kami yang tak terhingga</string>
|
|
||||||
<string name="are_you_interested">Apa kamu tertarik?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Batas kecepatan</string>
|
<string name="frame_limit_enable">Batas kecepatan</string>
|
||||||
<string name="frame_limit_enable_description">Membatasi kecepatan emulasi ke persentase tertentu dari kecepatan normal</string>
|
<string name="frame_limit_enable_description">Membatasi kecepatan emulasi ke persentase tertentu dari kecepatan normal</string>
|
||||||
|
|
|
@ -378,17 +378,6 @@
|
||||||
<string name="user_data_export_cancelled">Esportazione annullata</string>
|
<string name="user_data_export_cancelled">Esportazione annullata</string>
|
||||||
<string name="user_data_import_failed_description">Assicurati che la cartella dei Dati dell\'utente stiano nella radice del file.zip e che sia presente una cartella config in config/config.ini, poi, riprova.</string>
|
<string name="user_data_import_failed_description">Assicurati che la cartella dei Dati dell\'utente stiano nella radice del file.zip e che sia presente una cartella config in config/config.ini, poi, riprova.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Accesso Anticipato</string>
|
|
||||||
<string name="early_access_benefits">Vantaggi dell\'accesso anticipato</string>
|
|
||||||
<string name="cutting_edge_features">Funzionalità all\'avanguardia</string>
|
|
||||||
<string name="early_access_updates">Accesso anticipato agli aggiornamenti</string>
|
|
||||||
<string name="no_manual_installation">Non installare manualmente.</string>
|
|
||||||
<string name="prioritized_support">Supporto prioritario</string>
|
|
||||||
<string name="helping_game_preservation">Aiuta a preservare il gioco</string>
|
|
||||||
<string name="our_eternal_gratitude">La nostra gratitudine eterna</string>
|
|
||||||
<string name="are_you_interested">Sei interessato?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limita velocità</string>
|
<string name="frame_limit_enable">Limita velocità</string>
|
||||||
<string name="frame_limit_enable_description">Limita la velocità dell\'emulazione a una specifica percentuale della velocità normale.</string>
|
<string name="frame_limit_enable_description">Limita la velocità dell\'emulazione a una specifica percentuale della velocità normale.</string>
|
||||||
|
|
|
@ -357,17 +357,6 @@
|
||||||
<string name="user_data_import_success">ユーザデータのインポートに成功しました</string>
|
<string name="user_data_import_success">ユーザデータのインポートに成功しました</string>
|
||||||
<string name="user_data_export_cancelled">エクスポートをキャンセルしました</string>
|
<string name="user_data_export_cancelled">エクスポートをキャンセルしました</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">早期アクセス</string>
|
|
||||||
<string name="early_access_benefits">早期アクセスのメリット</string>
|
|
||||||
<string name="cutting_edge_features">最先端の機能</string>
|
|
||||||
<string name="early_access_updates">アップデートへの早期アクセス</string>
|
|
||||||
<string name="no_manual_installation">手動インストールが不要</string>
|
|
||||||
<string name="prioritized_support">優先サポート</string>
|
|
||||||
<string name="helping_game_preservation">ゲームの保存に貢献</string>
|
|
||||||
<string name="our_eternal_gratitude">私たちから永遠の感謝</string>
|
|
||||||
<string name="are_you_interested">興味がありますか?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">エミュレーション速度を制限</string>
|
<string name="frame_limit_enable">エミュレーション速度を制限</string>
|
||||||
<string name="frame_limit_enable_description">エミュレーション速度を指定した割合に制限します。</string>
|
<string name="frame_limit_enable_description">エミュレーション速度を指定した割合に制限します。</string>
|
||||||
|
|
|
@ -385,17 +385,6 @@
|
||||||
<string name="user_data_export_cancelled">내보내기 취소됨</string>
|
<string name="user_data_export_cancelled">내보내기 취소됨</string>
|
||||||
<string name="user_data_import_failed_description">유저 데이터 폴더가 ZIP 폴더의 루트 디렉토리에 위치하고 config/config.ini 구성 파일이 있는지 확인하고 다시 시도하세요.</string>
|
<string name="user_data_import_failed_description">유저 데이터 폴더가 ZIP 폴더의 루트 디렉토리에 위치하고 config/config.ini 구성 파일이 있는지 확인하고 다시 시도하세요.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">앞서 해보기</string>
|
|
||||||
<string name="early_access_benefits">앞서 해보기 혜택</string>
|
|
||||||
<string name="cutting_edge_features">최신 기능</string>
|
|
||||||
<string name="early_access_updates">업데이트 미리 체험</string>
|
|
||||||
<string name="no_manual_installation">수동 설치 불필요</string>
|
|
||||||
<string name="prioritized_support">우선 지원</string>
|
|
||||||
<string name="helping_game_preservation">게임 보존 지원</string>
|
|
||||||
<string name="our_eternal_gratitude">우리의 영원한 감사의 마음</string>
|
|
||||||
<string name="are_you_interested">관심 있으세요?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">속도 제한</string>
|
<string name="frame_limit_enable">속도 제한</string>
|
||||||
<string name="frame_limit_enable_description">에뮬레이션 속도를 정상 속도의 지정된 비율로 제한합니다.</string>
|
<string name="frame_limit_enable_description">에뮬레이션 속도를 정상 속도의 지정된 비율로 제한합니다.</string>
|
||||||
|
|
|
@ -334,17 +334,6 @@
|
||||||
<string name="licenses_description">Prosjekter som gjør Eden for Android mulig</string>
|
<string name="licenses_description">Prosjekter som gjør Eden for Android mulig</string>
|
||||||
<string name="build">Bygg</string>
|
<string name="build">Bygg</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Tidlig tilgang</string>
|
|
||||||
<string name="early_access_benefits">Fordeler ved tidlig tilgang</string>
|
|
||||||
<string name="cutting_edge_features">Avanserte funksjoner</string>
|
|
||||||
<string name="early_access_updates">Tidlig tilgang til oppdateringer</string>
|
|
||||||
<string name="no_manual_installation">Ingen manuell installasjon</string>
|
|
||||||
<string name="prioritized_support">Prioritert støtte</string>
|
|
||||||
<string name="helping_game_preservation">Bidra til bevaring av spill</string>
|
|
||||||
<string name="our_eternal_gratitude">Vår evige takknemlighet</string>
|
|
||||||
<string name="are_you_interested">Er du interessert?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Begrense hastigheten</string>
|
<string name="frame_limit_enable">Begrense hastigheten</string>
|
||||||
<string name="frame_limit_enable_description">Begrenser emuleringshastigheten til en spesifisert prosentandel av normal hastighet.</string>
|
<string name="frame_limit_enable_description">Begrenser emuleringshastigheten til en spesifisert prosentandel av normal hastighet.</string>
|
||||||
|
|
|
@ -334,17 +334,6 @@
|
||||||
<string name="licenses_description">Projekty dzięki którym Eden mógł zostać stworzony</string>
|
<string name="licenses_description">Projekty dzięki którym Eden mógł zostać stworzony</string>
|
||||||
<string name="build">Wersja</string>
|
<string name="build">Wersja</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Wczesny dostęp</string>
|
|
||||||
<string name="early_access_benefits">Korzyści z wcześniejszego dostępu</string>
|
|
||||||
<string name="cutting_edge_features">Nowatorskie funkcje</string>
|
|
||||||
<string name="early_access_updates">Częste aktualizacje</string>
|
|
||||||
<string name="no_manual_installation">Automatyczne aktualizacje</string>
|
|
||||||
<string name="prioritized_support">Priorytetowe wsparcie</string>
|
|
||||||
<string name="helping_game_preservation">Pomoc w problemach z grami</string>
|
|
||||||
<string name="our_eternal_gratitude">Nasza wdzięczność</string>
|
|
||||||
<string name="are_you_interested">Jesteś zainteresowany?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limit szybkość</string>
|
<string name="frame_limit_enable">Limit szybkość</string>
|
||||||
<string name="frame_limit_enable_description">Włącz, aby ustawić procentowy limit szybkości emulacji</string>
|
<string name="frame_limit_enable_description">Włącz, aby ustawić procentowy limit szybkości emulacji</string>
|
||||||
|
|
|
@ -390,17 +390,6 @@
|
||||||
<string name="user_data_export_cancelled">Exportação cancelada</string>
|
<string name="user_data_export_cancelled">Exportação cancelada</string>
|
||||||
<string name="user_data_import_failed_description">Verifique se as pastas de dados do usuário estão na raiz da pasta zip, se possuem um arquivo de configuração em config/config.ini e tente novamente.</string>
|
<string name="user_data_import_failed_description">Verifique se as pastas de dados do usuário estão na raiz da pasta zip, se possuem um arquivo de configuração em config/config.ini e tente novamente.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Acesso Antecipado</string>
|
|
||||||
<string name="early_access_benefits">Benefícios do Acesso Antecipado</string>
|
|
||||||
<string name="cutting_edge_features">Recursos de ponta</string>
|
|
||||||
<string name="early_access_updates">Acesso antecipado a atualizações</string>
|
|
||||||
<string name="no_manual_installation">Sem instalação manual</string>
|
|
||||||
<string name="prioritized_support">Suporte prioritário</string>
|
|
||||||
<string name="helping_game_preservation">Ajuda na preservação dos jogos</string>
|
|
||||||
<string name="our_eternal_gratitude">A nossa eterna gratidão</string>
|
|
||||||
<string name="are_you_interested">Tem interesse?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limite de velocidade</string>
|
<string name="frame_limit_enable">Limite de velocidade</string>
|
||||||
<string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
|
<string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
|
||||||
|
|
|
@ -390,17 +390,6 @@
|
||||||
<string name="user_data_export_cancelled">Exportação cancelada</string>
|
<string name="user_data_export_cancelled">Exportação cancelada</string>
|
||||||
<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>
|
<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>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Acesso antecipado</string>
|
|
||||||
<string name="early_access_benefits">Benefícios do Acesso Antecipado</string>
|
|
||||||
<string name="cutting_edge_features">Recursos de ponta</string>
|
|
||||||
<string name="early_access_updates">Acesso antecipado a atualizações</string>
|
|
||||||
<string name="no_manual_installation">Sem instalação manual</string>
|
|
||||||
<string name="prioritized_support">Suporte prioritário</string>
|
|
||||||
<string name="helping_game_preservation">Ajuda na preservação dos jogos</string>
|
|
||||||
<string name="our_eternal_gratitude">A nossa eterna gratidão</string>
|
|
||||||
<string name="are_you_interested">Estás interessado?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limite de velocidade</string>
|
<string name="frame_limit_enable">Limite de velocidade</string>
|
||||||
<string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
|
<string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
|
||||||
|
|
|
@ -391,17 +391,6 @@
|
||||||
<string name="user_data_export_cancelled">Экспорт отменен</string>
|
<string name="user_data_export_cancelled">Экспорт отменен</string>
|
||||||
<string name="user_data_import_failed_description">Убедитесь что папки пользовательских данных находятся в корне zip-папки и содержат файл конфигурации config/config.ini и повторите попытку.</string>
|
<string name="user_data_import_failed_description">Убедитесь что папки пользовательских данных находятся в корне zip-папки и содержат файл конфигурации config/config.ini и повторите попытку.</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Ранний доступ</string>
|
|
||||||
<string name="early_access_benefits">Преимущества раннего доступа</string>
|
|
||||||
<string name="cutting_edge_features">Новейшие возможности</string>
|
|
||||||
<string name="early_access_updates">Ранний доступ к обновлениям</string>
|
|
||||||
<string name="no_manual_installation">Без ручной установки</string>
|
|
||||||
<string name="prioritized_support">Приоритетная поддержка</string>
|
|
||||||
<string name="helping_game_preservation">Помощь в презервации игр</string>
|
|
||||||
<string name="our_eternal_gratitude">Наша бесконечная благодарность</string>
|
|
||||||
<string name="are_you_interested">Вы заинтересованы?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Ограничить скорость</string>
|
<string name="frame_limit_enable">Ограничить скорость</string>
|
||||||
<string name="frame_limit_enable_description">Ограничивает скорость эмуляции указанным процентом от нормальной скорости.</string>
|
<string name="frame_limit_enable_description">Ограничивает скорость эмуляции указанным процентом от нормальной скорости.</string>
|
||||||
|
|
|
@ -320,17 +320,6 @@
|
||||||
<string name="contributors_description">Зроблено з \u2764 від команди Eden</string>
|
<string name="contributors_description">Зроблено з \u2764 від команди Eden</string>
|
||||||
<string name="build">Збірка</string>
|
<string name="build">Збірка</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Ранній доступ</string>
|
|
||||||
<string name="early_access_benefits">Переваги раннього доступу</string>
|
|
||||||
<string name="cutting_edge_features">Новітні можливості</string>
|
|
||||||
<string name="early_access_updates">Ранній доступ до оновлень</string>
|
|
||||||
<string name="no_manual_installation">Без ручного встановлення</string>
|
|
||||||
<string name="prioritized_support">Пріоритетна підтримка</string>
|
|
||||||
<string name="helping_game_preservation">Допомога в презервації ігор</string>
|
|
||||||
<string name="our_eternal_gratitude">Наша нескінченна вдячність</string>
|
|
||||||
<string name="are_you_interested">Ви зацікавлені?</string>
|
|
||||||
|
|
||||||
<string name="frame_limit_enable">Обмеження швидкості</string>
|
<string name="frame_limit_enable">Обмеження швидкості</string>
|
||||||
<string name="frame_limit_enable_description">Обмежує швидкість емуляції у відсотках від нормальної.</string>
|
<string name="frame_limit_enable_description">Обмежує швидкість емуляції у відсотках від нормальної.</string>
|
||||||
<string name="frame_limit_slider">Відсоток обмеження</string>
|
<string name="frame_limit_slider">Відсоток обмеження</string>
|
||||||
|
|
|
@ -334,17 +334,6 @@
|
||||||
<string name="licenses_description">Các dự án làm cho Eden trên Android trở thành điều có thể</string>
|
<string name="licenses_description">Các dự án làm cho Eden trên Android trở thành điều có thể</string>
|
||||||
<string name="build">Dựng</string>
|
<string name="build">Dựng</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Early Access</string>
|
|
||||||
<string name="early_access_benefits">Lợi ích của Early Access</string>
|
|
||||||
<string name="cutting_edge_features">Tính năng tiên tiến</string>
|
|
||||||
<string name="early_access_updates">Truy cập sớm vào cập nhật</string>
|
|
||||||
<string name="no_manual_installation">Không có cài đặt thủ công</string>
|
|
||||||
<string name="prioritized_support">Ưu tiên hỗ trợ</string>
|
|
||||||
<string name="helping_game_preservation">Hỗ trợ bảo tồn trò chơi</string>
|
|
||||||
<string name="our_eternal_gratitude">Sự biết ơn vô hạn của chúng tôi</string>
|
|
||||||
<string name="are_you_interested">Bạn có thấy thú vị không?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Giới hạn tốc độ</string>
|
<string name="frame_limit_enable">Giới hạn tốc độ</string>
|
||||||
<string name="frame_limit_enable_description">Giới hạn tốc độ giả lập ở một phần trăm cụ thể của tốc độ bình thường.</string>
|
<string name="frame_limit_enable_description">Giới hạn tốc độ giả lập ở một phần trăm cụ thể của tốc độ bình thường.</string>
|
||||||
|
|
|
@ -385,17 +385,6 @@
|
||||||
<string name="user_data_export_cancelled">已取消导出数据</string>
|
<string name="user_data_export_cancelled">已取消导出数据</string>
|
||||||
<string name="user_data_import_failed_description">请确保用户数据文件夹位于 zip 压缩包的根目录,并在 config/config.ini 路径中包含配置文件,然后重试。</string>
|
<string name="user_data_import_failed_description">请确保用户数据文件夹位于 zip 压缩包的根目录,并在 config/config.ini 路径中包含配置文件,然后重试。</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">抢先体验</string>
|
|
||||||
<string name="early_access_benefits">抢先体验的权益</string>
|
|
||||||
<string name="cutting_edge_features">最新功能</string>
|
|
||||||
<string name="early_access_updates">抢先更新</string>
|
|
||||||
<string name="no_manual_installation">无需手动安装</string>
|
|
||||||
<string name="prioritized_support">优先支持</string>
|
|
||||||
<string name="helping_game_preservation">帮助保留游玩历史</string>
|
|
||||||
<string name="our_eternal_gratitude">我们真诚的感激</string>
|
|
||||||
<string name="are_you_interested">您对此感兴趣吗?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">运行速度限制</string>
|
<string name="frame_limit_enable">运行速度限制</string>
|
||||||
<string name="frame_limit_enable_description">将运行速度限制为正常速度的指定百分比。</string>
|
<string name="frame_limit_enable_description">将运行速度限制为正常速度的指定百分比。</string>
|
||||||
|
|
|
@ -391,17 +391,6 @@
|
||||||
<string name="user_data_export_cancelled">匯出已取消</string>
|
<string name="user_data_export_cancelled">匯出已取消</string>
|
||||||
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次。</string>
|
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次。</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">搶先體驗</string>
|
|
||||||
<string name="early_access_benefits">搶先體驗權益</string>
|
|
||||||
<string name="cutting_edge_features">最新功能</string>
|
|
||||||
<string name="early_access_updates">搶先版更新</string>
|
|
||||||
<string name="no_manual_installation">無需手動安裝</string>
|
|
||||||
<string name="prioritized_support">優先支援</string>
|
|
||||||
<string name="helping_game_preservation">協助遊戲保留</string>
|
|
||||||
<string name="our_eternal_gratitude">我們永遠的感激</string>
|
|
||||||
<string name="are_you_interested">您仍感興趣嗎?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">限制速度</string>
|
<string name="frame_limit_enable">限制速度</string>
|
||||||
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比。</string>
|
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比。</string>
|
||||||
|
|
|
@ -104,9 +104,10 @@
|
||||||
<string name="multiplayer">Multiplayer</string>
|
<string name="multiplayer">Multiplayer</string>
|
||||||
<string name="multiplayer_description">Host your own game room or join an existing one to play with people</string>
|
<string name="multiplayer_description">Host your own game room or join an existing one to play with people</string>
|
||||||
<string name="multiplayer_room_title">Room: %1$s</string>
|
<string name="multiplayer_room_title">Room: %1$s</string>
|
||||||
<string name="multiplayer_console_id">Console ID: %1$s</string>
|
<string name="multiplayer_console_id">Console ID:%1$s</string>
|
||||||
<string name="multiplayer_create_room">Create</string>
|
<string name="multiplayer_create_room">Create</string>
|
||||||
<string name="multiplayer_join_room">Join</string>
|
<string name="multiplayer_join_room">Join</string>
|
||||||
|
<string name="multiplayer_public_room">Browse Public Rooms</string>
|
||||||
<string name="multiplayer_username">Username</string>
|
<string name="multiplayer_username">Username</string>
|
||||||
<string name="multiplayer_ip_address">IP Address</string>
|
<string name="multiplayer_ip_address">IP Address</string>
|
||||||
<string name="multiplayer_ip_port">Port</string>
|
<string name="multiplayer_ip_port">Port</string>
|
||||||
|
@ -167,9 +168,26 @@
|
||||||
<string name="multiplayer_unban">Unban</string>
|
<string name="multiplayer_unban">Unban</string>
|
||||||
<string name="multiplayer_unban_message">Are you sure you want to unban %1$s?</string>
|
<string name="multiplayer_unban_message">Are you sure you want to unban %1$s?</string>
|
||||||
<string name="multiplayer_ban">Ban User</string>
|
<string name="multiplayer_ban">Ban User</string>
|
||||||
|
<string name="multiplayer_room_browser">Public Rooms</string>
|
||||||
|
<string name="multiplayer_no_rooms_found">No public rooms found</string>
|
||||||
|
<string name="multiplayer_password_required">Password Required</string>
|
||||||
|
<string name="multiplayer_player_count">: %1$d/%2$d</string>
|
||||||
|
<string name="multiplayer_game">Game</string>
|
||||||
|
<string name="multiplayer_no_game_info">Any Game</string>
|
||||||
|
<string name="multiplayer_password_protected">Password protected room</string>
|
||||||
|
<string name="multiplayer_hide_full_rooms">Hide Full Rooms</string>
|
||||||
|
<string name="multiplayer_hide_empty_rooms">Hide Empty Rooms</string>
|
||||||
|
<string name="multiplayer_tap_refresh_to_check_again">Tap refresh to check again</string>
|
||||||
|
<string name="multiplayer_search_public_lobbies">Search Lobbies…</string>
|
||||||
<string name="emulation_multiplayer">Multiplayer</string>
|
<string name="emulation_multiplayer">Multiplayer</string>
|
||||||
|
<string name="multiplayer_game_name">Preferred Games</string>
|
||||||
|
<string name="multiplayer_preferred_game_name">Preferred Game</string>
|
||||||
|
<string name="multiplayer_no_game">No Games Found</string>
|
||||||
|
<string name="multiplayer_preferred_game_name_invalid">You must choose a Preferred Game to host a room.</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
<string name="ok">Ok</string>
|
<string name="ok">Ok</string>
|
||||||
|
<string name="refresh">Refresh</string>
|
||||||
|
<string name="room_list">Room List</string>
|
||||||
|
|
||||||
<!-- Setup strings -->
|
<!-- Setup strings -->
|
||||||
<string name="welcome">Welcome!</string>
|
<string name="welcome">Welcome!</string>
|
||||||
|
@ -240,6 +258,7 @@
|
||||||
<string name="invalid_keys_error">Invalid encryption keys</string>
|
<string name="invalid_keys_error">Invalid encryption keys</string>
|
||||||
<string name="dumping_keys_quickstart_link">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
|
<string name="dumping_keys_quickstart_link">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
|
||||||
<string name="install_keys_failure_description">The selected file is incorrect or corrupt. Please redump your keys.</string>
|
<string name="install_keys_failure_description">The selected file is incorrect or corrupt. Please redump your keys.</string>
|
||||||
|
<string name="gpu_driver_fetcher">GPU driver fetcher</string>
|
||||||
<string name="gpu_driver_manager">GPU driver manager</string>
|
<string name="gpu_driver_manager">GPU driver manager</string>
|
||||||
<string name="install_gpu_driver">Install GPU driver</string>
|
<string name="install_gpu_driver">Install GPU driver</string>
|
||||||
<string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
|
<string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
|
||||||
|
@ -355,22 +374,10 @@
|
||||||
<string name="user_data_import_success">User data imported successfully</string>
|
<string name="user_data_import_success">User data imported successfully</string>
|
||||||
<string name="user_data_export_cancelled">Export cancelled</string>
|
<string name="user_data_export_cancelled">Export cancelled</string>
|
||||||
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
||||||
<string name="support_link">https://discord.gg/hab4Sh8qj6</string>
|
<string name="support_link">https://discord.gg/edenemu</string>
|
||||||
<string name="website_link">https://eden-emulator.github.io</string>
|
<string name="website_link">https://eden-emulator.github.io</string>
|
||||||
<string name="github_link">https://git.eden-emu.dev/eden-emu</string>
|
<string name="github_link">https://git.eden-emu.dev/eden-emu</string>
|
||||||
|
|
||||||
<!-- Early access upgrade strings -->
|
|
||||||
<string name="early_access">Early Access</string>
|
|
||||||
<string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
|
|
||||||
<string name="early_access_benefits">Early Access Benefits</string>
|
|
||||||
<string name="cutting_edge_features">Cutting-edge features</string>
|
|
||||||
<string name="early_access_updates">Early access to updates</string>
|
|
||||||
<string name="no_manual_installation">No manual installation</string>
|
|
||||||
<string name="prioritized_support">Prioritized support</string>
|
|
||||||
<string name="helping_game_preservation">Helping game preservation</string>
|
|
||||||
<string name="our_eternal_gratitude">Our eternal gratitude</string>
|
|
||||||
<string name="are_you_interested">Are you interested?</string>
|
|
||||||
|
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">Limit speed</string>
|
<string name="frame_limit_enable">Limit speed</string>
|
||||||
<string name="frame_limit_enable_description">Limits emulation speed to a specified percentage of normal speed.</string>
|
<string name="frame_limit_enable_description">Limits emulation speed to a specified percentage of normal speed.</string>
|
||||||
|
@ -552,6 +559,7 @@
|
||||||
<string name="import_failed">Import failed</string>
|
<string name="import_failed">Import failed</string>
|
||||||
<string name="cancelling">Cancelling</string>
|
<string name="cancelling">Cancelling</string>
|
||||||
<string name="install">Install</string>
|
<string name="install">Install</string>
|
||||||
|
<string name="fetch">Fetch</string>
|
||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
<string name="edit">Edit</string>
|
<string name="edit">Edit</string>
|
||||||
<string name="export_success">Exported successfully</string>
|
<string name="export_success">Exported successfully</string>
|
||||||
|
@ -580,6 +588,31 @@
|
||||||
<string name="system_gpu_driver">System GPU driver</string>
|
<string name="system_gpu_driver">System GPU driver</string>
|
||||||
<string name="installing_driver">Installing driver…</string>
|
<string name="installing_driver">Installing driver…</string>
|
||||||
|
|
||||||
|
<!-- GPU driver fetcher -->
|
||||||
|
<string name="fetch_error">Error while Fetching</string>
|
||||||
|
<string name="check_connection">Check your connection and try again.</string>
|
||||||
|
<string name="show_releases">Show Releases</string>
|
||||||
|
<string name="view_full_release_notes">Release Notes</string>
|
||||||
|
<string name="failed_to_fetch">Failed to fetch</string>
|
||||||
|
<string name="error_during_fetch">Error during Fetch</string>
|
||||||
|
<string name="toggle_release_notes">Toggle release notes</string>
|
||||||
|
<string name="downloads">Downloads</string>
|
||||||
|
<string name="show_downloads">Show Downloads</string>
|
||||||
|
<string name="hide_downloads">Hide Downloads</string>
|
||||||
|
<string name="failed_cache_dir">Cache directory unavailable</string>
|
||||||
|
<string name="empty_response_body">Empty response body</string>
|
||||||
|
<string name="successfully_installed">%1$s Successfully Installed</string>
|
||||||
|
<string name="driver_failed_title">Driver installation failed</string>
|
||||||
|
<string name="failed_install_driver">Failed to install %1$s driver, does your system support it?</string>
|
||||||
|
<string name="driver_empty">Downloaded driver is empty, check your internet</string>
|
||||||
|
<string name="downloading">Downloading…</string>
|
||||||
|
<string name="installing">Installing…</string>
|
||||||
|
<string name="latest">Latest</string>
|
||||||
|
<string name="recommended_driver">Recommended Driver:</string>
|
||||||
|
<string name="gpu_model">GPU Model:</string>
|
||||||
|
<string name="unsupported_gpu">Unsupported GPU</string>
|
||||||
|
<string name="unsupported_gpu_warning">Your GPU does not support driver injection. Attempting to set custom drivers is not recommended.</string>
|
||||||
|
|
||||||
<!-- Preferences Screen -->
|
<!-- Preferences Screen -->
|
||||||
<string name="preferences_settings">Settings</string>
|
<string name="preferences_settings">Settings</string>
|
||||||
<string name="preferences_general">General</string>
|
<string name="preferences_general">General</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue