[frontend] refactor: extract common firmware & key functions #38

Merged
crueter merged 4 commits from feature/firmware-loader into master 2025-07-13 03:39:21 +02:00
39 changed files with 1146 additions and 1078 deletions

View file

@ -15,6 +15,7 @@ import android.view.Surface
import android.view.View
import android.widget.TextView
import androidx.annotation.Keep
import androidx.core.net.toUri
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import net.swiftzer.semver.SemVer
import java.lang.ref.WeakReference
@ -27,6 +28,7 @@ import org.yuzu.yuzu_emu.model.InstallResult
import org.yuzu.yuzu_emu.model.Patch
import org.yuzu.yuzu_emu.model.GameVerificationResult
import org.yuzu.yuzu_emu.network.NetPlayManager
import java.io.File
/**
* Class which contains methods that interact
@ -102,6 +104,21 @@ object NativeLibrary {
FileUtil.getFilename(Uri.parse(path))
}
@Keep
@JvmStatic
fun copyFileToStorage(source: String, destdir: String): Boolean {
return FileUtil.copyUriToInternalStorage(
source.toUri(),
destdir
) != null
}
@Keep
@JvmStatic
fun getFileExtension(source: String): String {
return FileUtil.getExtension(source.toUri())
}
external fun setAppDirectory(directory: String)
/**
@ -415,18 +432,29 @@ object NativeLibrary {
*/
external fun firmwareVersion(): String
fun isFirmwareSupported(): Boolean {
var version: SemVer
/**
* Verifies installed firmware.
*
* @return The result code.
*/
external fun verifyFirmware(): Int
try {
version = SemVer.parse(firmwareVersion())
} catch (_: Exception) {
return false
}
val max = SemVer(19, 0, 1)
/**
* Check if a game requires firmware to be playable.
*
* @param programId The game's Program ID.
* @return Whether or not the game requires firmware to be playable.
*/
external fun gameRequiresFirmware(programId: String): Boolean
return version <= max
}
/**
* Installs keys from the specified path.
*
* @param path The path to install keys from.
* @param ext What extension the keys should have.
* @return The result code.
*/
external fun installKeys(path: String, ext: String): Int
/**
* Checks the PatchManager for any addons that are available

View file

@ -3,11 +3,16 @@
package org.yuzu.yuzu_emu.adapters
import android.content.DialogInterface
import android.net.Uri
import android.text.Html
import android.text.method.LinkMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.pm.ShortcutInfoCompat
@ -33,6 +38,10 @@ import org.yuzu.yuzu_emu.utils.GameIconUtils
import org.yuzu.yuzu_emu.utils.ViewUtils.marquee
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
import androidx.recyclerview.widget.RecyclerView
import androidx.core.net.toUri
import androidx.core.content.edit
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.yuzu.yuzu_emu.NativeLibrary
class GameAdapter(private val activity: AppCompatActivity) :
AbstractDiffAdapter<Game, GameAdapter.GameViewHolder>(exact = false) {
@ -171,8 +180,9 @@ class GameAdapter(private val activity: AppCompatActivity) :
fun onClick(game: Game) {
val gameExists = DocumentFile.fromSingleUri(
YuzuApplication.appContext,
Uri.parse(game.path)
game.path.toUri()
)?.exists() == true
if (!gameExists) {
Toast.makeText(
YuzuApplication.appContext,
@ -184,29 +194,49 @@ class GameAdapter(private val activity: AppCompatActivity) :
return
}
val preferences =
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
preferences.edit()
.putLong(
game.keyLastPlayedTime,
System.currentTimeMillis()
)
.apply()
activity.lifecycleScope.launch {
withContext(Dispatchers.IO) {
val shortcut =
ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
.setShortLabel(game.title)
.setIcon(GameIconUtils.getShortcutIcon(activity, game))
.setIntent(game.launchIntent)
.build()
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
val launch: () -> Unit = {
val preferences =
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
preferences.edit {
putLong(
game.keyLastPlayedTime,
System.currentTimeMillis()
)
}
activity.lifecycleScope.launch {
withContext(Dispatchers.IO) {
val shortcut =
ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
.setShortLabel(game.title)
.setIcon(GameIconUtils.getShortcutIcon(activity, game))
.setIntent(game.launchIntent)
.build()
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
}
}
val action = HomeNavigationDirections.actionGlobalEmulationActivity(game, true)
binding.root.findNavController().navigate(action)
}
val action = HomeNavigationDirections.actionGlobalEmulationActivity(game, true)
binding.root.findNavController().navigate(action)
if (NativeLibrary.gameRequiresFirmware(game.programId) && !NativeLibrary.isFirmwareAvailable()) {
MaterialAlertDialogBuilder(activity)
.setTitle(R.string.loader_requires_firmware)
.setMessage(
Html.fromHtml(
activity.getString(R.string.loader_requires_firmware_description),
Html.FROM_HTML_MODE_LEGACY
)
)
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
launch()
}
.setNegativeButton(android.R.string.cancel) { _,_ -> }
.show()
} else {
launch()
}
}
fun onLongClick(game: Game): Boolean {

View file

@ -264,8 +264,6 @@ class DriverFetcherFragment : Fragment() {
}
releases.add(release)
println(release.publishTime)
}
}

View file

@ -137,7 +137,7 @@ class HomeSettingsFragment : Fragment() {
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_appletLauncherFragment)
},
{ NativeLibrary.isFirmwareAvailable() && NativeLibrary.isFirmwareSupported() },
{ NativeLibrary.isFirmwareAvailable() },
R.string.applets_error_firmware,
R.string.applets_error_description
)

View file

@ -352,7 +352,7 @@ class SetupFragment : Fragment() {
val getProdKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
mainActivity.processKey(result)
mainActivity.processKey(result, "keys")
if (NativeLibrary.areKeysPresent()) {
keyCallback.onStepCompleted()
}

View file

@ -47,9 +47,6 @@ import info.debatty.java.stringsimilarity.Jaccard
import info.debatty.java.stringsimilarity.JaroWinkler
import java.util.Locale
import androidx.core.content.edit
import androidx.core.view.updateLayoutParams
import org.yuzu.yuzu_emu.features.settings.model.Settings
import android.view.ViewParent
import androidx.core.view.doOnNextLayout
class GamesFragment : Fragment() {
@ -151,7 +148,7 @@ class GamesFragment : Fragment() {
)
}
gamesViewModel.games.collect(viewLifecycleOwner) {
if (it.size > 0) {
if (it.isNotEmpty()) {
setAdapter(it)
}
}
@ -361,7 +358,7 @@ class GamesFragment : Fragment() {
popup.setOnMenuItemClickListener { item ->
currentFilter = item.itemId
preferences.edit().putInt(PREF_SORT_TYPE, currentFilter).apply()
preferences.edit { putInt(PREF_SORT_TYPE, currentFilter) }
filterAndSearch()
true
}

View file

@ -6,6 +6,8 @@ package org.yuzu.yuzu_emu.ui.main
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.ParcelFileDescriptor
import android.provider.OpenableColumns
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager
@ -47,6 +49,7 @@ import java.io.BufferedOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import androidx.core.content.edit
import androidx.core.net.toFile
class MainActivity : AppCompatActivity(), ThemeProvider {
private lateinit var binding: ActivityMainBinding
@ -70,10 +73,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
val granted = permissions.entries.all { it.value }
if (granted) {
// Permissions were granted.
Toast.makeText(this, R.string.bluetooth_permissions_granted, Toast.LENGTH_SHORT).show()
Toast.makeText(this, R.string.bluetooth_permissions_granted, Toast.LENGTH_SHORT)
.show()
} else {
// Permissions were denied.
Toast.makeText(this, R.string.bluetooth_permissions_denied, Toast.LENGTH_LONG).show()
Toast.makeText(this, R.string.bluetooth_permissions_denied, Toast.LENGTH_LONG)
.show()
}
}
@ -94,7 +99,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition { !DirectoryInitialization.areDirectoriesReady }
@ -105,13 +110,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
NativeLibrary.initMultiplayer()
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
checkAndRequestBluetoothPermissions()
if (savedInstanceState != null) {
checkedDecryption = savedInstanceState.getBoolean(CHECKED_DECRYPTION)
checkedFirmware = savedInstanceState.getBoolean(CHECKED_FIRMWARE)
@ -146,22 +151,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
binding.statusBarShade.setBackgroundColor(
ThemeHelper.getColorWithOpacity(
MaterialColors.getColor(
binding.root,
com.google.android.material.R.attr.colorSurface
),
ThemeHelper.SYSTEM_BAR_ALPHA
binding.root, com.google.android.material.R.attr.colorSurface
), ThemeHelper.SYSTEM_BAR_ALPHA
)
)
if (InsetsHelper.getSystemGestureType(applicationContext) !=
InsetsHelper.GESTURE_NAVIGATION
) {
if (InsetsHelper.getSystemGestureType(applicationContext) != InsetsHelper.GESTURE_NAVIGATION) {
binding.navigationBarShade.setBackgroundColor(
ThemeHelper.getColorWithOpacity(
MaterialColors.getColor(
binding.root,
com.google.android.material.R.attr.colorSurface
),
ThemeHelper.SYSTEM_BAR_ALPHA
binding.root, com.google.android.material.R.attr.colorSurface
), ThemeHelper.SYSTEM_BAR_ALPHA
)
)
}
@ -172,9 +171,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
homeViewModel.statusBarShadeVisible.collect(this) { showStatusBarShade(it) }
homeViewModel.contentToInstall.collect(
this,
resetState = { homeViewModel.setContentToInstall(null) }
) {
this, resetState = { homeViewModel.setContentToInstall(null) }) {
if (it != null) {
installContent(it)
}
@ -183,7 +180,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (it) checkKeys()
}
homeViewModel.checkFirmware.collect(this, resetState = { homeViewModel.setCheckFirmware(false) }) {
homeViewModel.checkFirmware.collect(
this, resetState = { homeViewModel.setCheckFirmware(false) }) {
if (it) checkFirmware()
}
@ -203,12 +201,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
negativeButtonTitleId = R.string.close,
showNegativeButton = true,
positiveAction = {
PreferenceManager.getDefaultSharedPreferences(applicationContext)
.edit() {
putBoolean(Settings.PREF_SHOULD_SHOW_PRE_ALPHA_WARNING, false)
}
}
).show(supportFragmentManager, MessageDialogFragment.TAG)
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit() {
putBoolean(Settings.PREF_SHOULD_SHOW_PRE_ALPHA_WARNING, false)
}
}).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
@ -228,15 +224,18 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
private fun checkFirmware() {
if (!NativeLibrary.isFirmwareAvailable() || !NativeLibrary.isFirmwareSupported()) {
MessageDialogFragment.newInstance(
titleId = R.string.firmware_missing,
descriptionId = R.string.firmware_missing_description,
helpLinkId = R.string.firmware_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
val resultCode: Int = NativeLibrary.verifyFirmware()
if (resultCode == 0) return;
val resultString: String =
resources.getStringArray(R.array.verifyFirmwareResults)[resultCode]
MessageDialogFragment.newInstance(
titleId = R.string.firmware_invalid,
descriptionString = resultString,
helpLinkId = R.string.firmware_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
@ -283,23 +282,22 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
super.onResume()
}
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(
binding.root
) { _: View, windowInsets: WindowInsetsCompat ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val mlpStatusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
mlpStatusShade.height = insets.top
binding.statusBarShade.layoutParams = mlpStatusShade
private fun setInsets() = ViewCompat.setOnApplyWindowInsetsListener(
binding.root
) { _: View, windowInsets: WindowInsetsCompat ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val mlpStatusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
mlpStatusShade.height = insets.top
binding.statusBarShade.layoutParams = mlpStatusShade
// The only situation where we care to have a nav bar shade is when it's at the bottom
// of the screen where scrolling list elements can go behind it.
val mlpNavShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
mlpNavShade.height = insets.bottom
binding.navigationBarShade.layoutParams = mlpNavShade
// The only situation where we care to have a nav bar shade is when it's at the bottom
// of the screen where scrolling list elements can go behind it.
val mlpNavShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
mlpNavShade.height = insets.bottom
binding.navigationBarShade.layoutParams = mlpNavShade
windowInsets
}
windowInsets
}
override fun setTheme(resId: Int) {
super.setTheme(resId)
@ -315,17 +313,14 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
fun processGamesDir(result: Uri, calledFromGameFragment: Boolean = false) {
contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
result, Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val uriString = result.toString()
val folder = gamesViewModel.folders.value.firstOrNull { it.uriString == uriString }
if (folder != null) {
Toast.makeText(
applicationContext,
R.string.folder_already_added,
Toast.LENGTH_SHORT
applicationContext, R.string.folder_already_added, Toast.LENGTH_SHORT
).show()
return
}
@ -334,72 +329,50 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
.show(supportFragmentManager, AddGameFolderDialogFragment.TAG)
}
val getProdKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
processKey(result)
}
val getProdKey = registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
processKey(result, "keys")
}
fun processKey(result: Uri): Boolean {
if (FileUtil.getExtension(result) != "keys") {
MessageDialogFragment.newInstance(
this,
titleId = R.string.reading_keys_failure,
descriptionId = R.string.install_prod_keys_failure_extension_description
).show(supportFragmentManager, MessageDialogFragment.TAG)
return false
}
contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
if (FileUtil.copyUriToInternalStorage(
result,
dstPath,
"prod.keys"
) != null
) {
if (NativeLibrary.reloadKeys()) {
Toast.makeText(
applicationContext,
R.string.install_keys_success,
Toast.LENGTH_SHORT
).show()
homeViewModel.setCheckKeys(true)
val firstTimeSetup = PreferenceManager.getDefaultSharedPreferences(applicationContext)
.getBoolean(Settings.PREF_FIRST_APP_LAUNCH, true)
if (!firstTimeSetup) {
homeViewModel.setCheckFirmware(true)
}
gamesViewModel.reloadGames(true)
return true
} else {
MessageDialogFragment.newInstance(
this,
titleId = R.string.invalid_keys_error,
descriptionId = R.string.install_keys_failure_description,
helpLinkId = R.string.dumping_keys_quickstart_link
).show(supportFragmentManager, MessageDialogFragment.TAG)
return false
}
}
return false
}
val getFirmware =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {
return@registerForActivityResult
}
val getAmiiboKey = registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
processKey(result, "bin")
}
}
fun processKey(result: Uri, extension: String = "keys") {
contentResolver.takePersistableUriPermission(
result, Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val resultCode: Int = NativeLibrary.installKeys(result.toString(), extension);
if (resultCode == 0) {
Toast.makeText(
applicationContext, R.string.keys_install_success, Toast.LENGTH_SHORT
).show()
gamesViewModel.reloadGames(true)
return
}
val resultString: String =
resources.getStringArray(R.array.installKeysResults)[resultCode]
MessageDialogFragment.newInstance(
titleId = R.string.keys_failed,
descriptionString = resultString,
helpLinkId = R.string.keys_missing_help
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
val getFirmware = registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
processFirmware(result)
}
}
fun processFirmware(result: Uri, onComplete: (() -> Unit)? = null) {
val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
@ -409,15 +382,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
val cacheFirmwareDir = File("${cacheDir.path}/registered/")
ProgressDialogFragment.newInstance(
this,
R.string.firmware_installing
this, R.string.firmware_installing
) { progressCallback, _ ->
var messageToShow: Any
try {
FileUtil.unzipToInternalStorage(
result.toString(),
cacheFirmwareDir,
progressCallback
result.toString(), cacheFirmwareDir, progressCallback
)
val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
@ -448,10 +418,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
fun uninstallFirmware() {
val firmwarePath = File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
val firmwarePath =
File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
ProgressDialogFragment.newInstance(
this,
R.string.firmware_uninstalling
this, R.string.firmware_uninstalling
) { progressCallback, _ ->
var messageToShow: Any
try {
@ -473,49 +443,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
messageToShow
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
}
val getAmiiboKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result == null) {
return@registerForActivityResult
}
if (FileUtil.getExtension(result) != "bin") {
MessageDialogFragment.newInstance(
this,
titleId = R.string.reading_keys_failure,
descriptionId = R.string.install_amiibo_keys_failure_extension_description
).show(supportFragmentManager, MessageDialogFragment.TAG)
return@registerForActivityResult
}
contentResolver.takePersistableUriPermission(
result,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
if (FileUtil.copyUriToInternalStorage(
result,
dstPath,
"key_retail.bin"
) != null
) {
if (NativeLibrary.reloadKeys()) {
Toast.makeText(
applicationContext,
R.string.install_keys_success,
Toast.LENGTH_SHORT
).show()
} else {
MessageDialogFragment.newInstance(
this,
titleId = R.string.invalid_keys_error,
descriptionId = R.string.install_keys_failure_description,
helpLinkId = R.string.dumping_keys_quickstart_link
).show(supportFragmentManager, MessageDialogFragment.TAG)
}
}
}
val installGameUpdate = registerForActivityResult(
ActivityResultContracts.OpenMultipleDocuments()
@ -530,15 +457,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
ProgressDialogFragment.newInstance(
this@MainActivity,
R.string.verifying_content,
false
this@MainActivity, R.string.verifying_content, false
) { _, _ ->
var updatesMatchProgram = true
for (document in documents) {
val valid = NativeLibrary.doesUpdateMatchProgram(
addonViewModel.game!!.programId,
document.toString()
addonViewModel.game!!.programId, document.toString()
)
if (!valid) {
updatesMatchProgram = false
@ -554,16 +478,14 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
titleId = R.string.content_install_notice,
descriptionId = R.string.content_install_notice_description,
positiveAction = { homeViewModel.setContentToInstall(documents) },
negativeAction = {}
)
negativeAction = {})
}
}.show(supportFragmentManager, ProgressDialogFragment.TAG)
}
private fun installContent(documents: List<Uri>) {
ProgressDialogFragment.newInstance(
this@MainActivity,
R.string.installing_game_content
this@MainActivity, R.string.installing_game_content
) { progressCallback, messageCallback ->
var installSuccess = 0
var installOverwrite = 0
@ -571,14 +493,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
var error = 0
documents.forEach {
messageCallback.invoke(FileUtil.getFilename(it))
when (
InstallResult.from(
NativeLibrary.installFileToNand(
it.toString(),
progressCallback
)
when (InstallResult.from(
NativeLibrary.installFileToNand(
it.toString(), progressCallback
)
) {
)) {
InstallResult.Success -> {
installSuccess += 1
}
@ -599,13 +518,12 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
addonViewModel.refreshAddons()
val separator = System.getProperty("line.separator") ?: "\n"
val separator = System.lineSeparator() ?: "\n"
val installResult = StringBuilder()
if (installSuccess > 0) {
installResult.append(
getString(
R.string.install_game_content_success_install,
installSuccess
R.string.install_game_content_success_install, installSuccess
)
)
installResult.append(separator)
@ -613,8 +531,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
if (installOverwrite > 0) {
installResult.append(
getString(
R.string.install_game_content_success_overwrite,
installOverwrite
R.string.install_game_content_success_overwrite, installOverwrite
)
)
installResult.append(separator)
@ -624,8 +541,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
installResult.append(separator)
installResult.append(
getString(
R.string.install_game_content_failed_count,
errorTotal
R.string.install_game_content_failed_count, errorTotal
)
)
installResult.append(separator)
@ -666,9 +582,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
ProgressDialogFragment.newInstance(
this,
R.string.exporting_user_data,
true
this, R.string.exporting_user_data, true
) { progressCallback, _ ->
val zipResult = FileUtil.zipFromInternalStorage(
File(DirectoryInitialization.userDirectory!!),
@ -692,8 +606,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
}
ProgressDialogFragment.newInstance(
this,
R.string.importing_user_data
this, R.string.importing_user_data
) { progressCallback, _ ->
val checkStream =
ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result)))

View file

@ -60,6 +60,7 @@
#include "core/hle/service/set/system_settings_server.h"
#include "core/loader/loader.h"
#include "frontend_common/config.h"
#include "frontend_common/firmware_manager.h"
#include "hid_core/frontend/emulated_controller.h"
#include "hid_core/hid_core.h"
#include "hid_core/hid_types.h"
@ -283,6 +284,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
: Service::AM::LaunchType::ApplicationInitiated,
.program_index = static_cast<s32>(program_index),
};
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
if (m_load_result != Core::SystemResultStatus::Success) {
return m_load_result;
@ -764,35 +766,19 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass cl
}
bool isFirmwarePresent() {
auto bis_system =
EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
return false;
}
// Query an applet to see if it's available
auto applet_nca =
bis_system->GetEntry(0x010000000000100Dull, FileSys::ContentRecordType::Program);
if (!applet_nca) {
return false;
}
return true;
return FirmwareManager::CheckFirmwarePresence(EmulationSession::GetInstance().System());
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, jclass clazz) {
return isFirmwarePresent();
}
// TODO(crueter): This check is nonfunctional...
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_firmwareVersion(JNIEnv* env, jclass clazz) {
Service::Set::FirmwareVersionFormat firmware_data{};
const auto result = Service::Set::GetFirmwareVersionImpl(
firmware_data, EmulationSession::GetInstance().System(),
Service::Set::GetFirmwareVersionType::Version2);
const auto pair = FirmwareManager::GetFirmwareVersion(EmulationSession::GetInstance().System());
const auto firmware_data = pair.first;
const auto result = pair.second;
if (result.IsError() || !isFirmwarePresent()) {
LOG_INFO(Frontend, "Installed firmware: No firmware available");
return Common::Android::ToJString(env, "N/A");
}
@ -804,6 +790,23 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_firmwareVersion(JNIEnv* env, jclas
return Common::Android::ToJString(env, display_version);
}
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyFirmware(JNIEnv* env, jclass clazz) {
return static_cast<int>(FirmwareManager::VerifyFirmware(EmulationSession::GetInstance().System()));
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_gameRequiresFirmware(JNIEnv* env, jclass clazz, jstring jprogramId) {
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
return FirmwareManager::GameRequiresFirmware(program_id);
}
jint Java_org_yuzu_yuzu_1emu_NativeLibrary_installKeys(JNIEnv* env, jclass clazz, jstring jpath, jstring jext) {
const auto path = Common::Android::GetJString(env, jpath);
const auto ext = Common::Android::GetJString(env, jext);
return static_cast<int>(FirmwareManager::InstallKeys(path, ext));
}
jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
jstring jpath,
jstring jprogramId) {

View file

@ -349,13 +349,7 @@
<string name="warning_cancel">إلغاء</string>
<string name="install_amiibo_keys">تثبيت مفاتيح أميبو</string>
<string name="install_amiibo_keys_description">مطلوب لاستخدام أميبو في اللعبة</string>
<string name="invalid_keys_file">تم تحديد ملف مفاتيح غير صالح</string>
<string name="install_keys_success">تم تثبيت المفاتيح بنجاح</string>
<string name="reading_keys_failure">خطأ في قراءة مفاتيح التشفير</string>
<string name="install_prod_keys_failure_extension_description">وحاول مرة أخر keys تحقق من أن ملف المفاتيح له امتداد</string>
<string name="install_amiibo_keys_failure_extension_description">وحاول مرة أخر bin تحقق من أن ملف المفاتيح له امتداد</string>
<string name="invalid_keys_error">مفاتيح التشفير غير صالحة</string>
<string name="install_keys_failure_description">الملف المحدد غير صحيح أو تالف. يرجى إعادة المفاتيح الخاصة بك</string>
<string name="gpu_driver_manager">GPU مدير برنامج تشغيل</string>
<string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string>
<string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة للحصول على أداء أو دقة أفضل</string>
@ -422,8 +416,6 @@
<string name="verify_installed_content_description">فحص المحتوى المثبت بحثًا عن تلف</string>
<string name="keys_missing">مفاتيح التشفير مفقودة</string>
<string name="keys_missing_description">لا يمكن فك تشفير البرنامج الثابت والألعاب</string>
<string name="firmware_missing">البرنامج الثابت مفقود أو جديد جدًا</string>
<string name="firmware_missing_description">بعض الألعاب قد لا تعمل بشكل صحيح. يتطلب إيدن البرنامج الثابت 19.0.1 أو أقل.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -344,13 +344,7 @@
<string name="warning_cancel">ڕەتکردنەوە</string>
<string name="install_amiibo_keys">دامەزراندنی کلیلی Amiibo</string>
<string name="install_amiibo_keys_description">پێویستە بۆ بەکارهێنانی Amiibo لە یاریدا</string>
<string name="invalid_keys_file">فایلی کلیلێکی نادروست هەڵبژێردرا</string>
<string name="install_keys_success">کلیلەکان بە سەرکەوتوویی دامەزران</string>
<string name="reading_keys_failure">هەڵە لە خوێندنەوەی کۆدکردنی کلیل</string>
<string name="install_prod_keys_failure_extension_description">دڵنیابەوە کە فایلی کلیلەکانت درێژکراوەی .keys ی هەیە و دووبارە هەوڵبدەرەوە.</string>
<string name="install_amiibo_keys_failure_extension_description">دڵنیابە کە فایلی کلیلەکانت درێژکراوەی .bin ی هەیە و دووبارە هەوڵبدەرەوە.</string>
<string name="invalid_keys_error">کلیلی کۆدکردنی نادروستە</string>
<string name="install_keys_failure_description">فایلە هەڵبژێردراوەکە هەڵەیە یان تێکچووە. تکایە دووبارە کلیلەکانت دەربێنەوە.</string>
<string name="install_gpu_driver">دامەزراندنی وەگەڕخەری GPU</string>
<string name="install_gpu_driver_description">دامەزراندنی وەگەڕخەری بەدیل بۆ ئەوەی بە ئەگەرێکی زۆرەوە کارایی باشتر یان وردبینی هەبێت</string>
<string name="advanced_settings">ڕێکخستنە پێشکەوتووەکان</string>
@ -416,8 +410,6 @@
<string name="verify_installed_content_description">هەموو ناوەڕۆکی دامەزراو پشکنین دەکات بۆ تێکچوون</string>
<string name="keys_missing">کلیلە کۆدکراوەکان دیار نییە</string>
<string name="keys_missing_description">پتەوواڵا و یارییە تاکەکەسییەکان ناتوانرێت کۆد بکرێنەوە</string>
<string name="firmware_missing">فریموێر بوونی نییە یان زۆر نوێە</string>
<string name="firmware_missing_description">هەندێ یاری لەوانەیە باش کار نەکەن. ئێدەن پێویستی بە فریموێری ١٩.٠.١ یان کەمترە.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -333,10 +333,6 @@
<string name="warning_cancel">Zrušit</string>
<string name="install_amiibo_keys">Instalovat Amiibo klíče</string>
<string name="install_amiibo_keys_description">Povinné použití Amiibo ve hře</string>
<string name="invalid_keys_file">Vybrané klíče jsou neplatné</string>
<string name="install_keys_success">Klíče úspěšně nainstalovány</string>
<string name="reading_keys_failure">Chyba při čtení šifrovacích klíčů</string>
<string name="invalid_keys_error">Neplatné šifrovací klíče</string>
<string name="gpu_driver_manager">Správce ovladače GPU</string>
<string name="install_gpu_driver">Instalovat GPU ovladač</string>
<string name="advanced_settings">Pokročilé nastavení</string>
@ -380,8 +376,6 @@
<string name="verify_installed_content_description">Kontrola poškození obsahu</string>
<string name="keys_missing">Chybí šifrovací klíče</string>
<string name="keys_missing_description">Firmware a retail hry nelze dešifrovat</string>
<string name="firmware_missing">Firmware chybí nebo je příliš nový</string>
<string name="firmware_missing_description">Některé hry nemusí fungovat správně. Eden vyžaduje firmware 19.0.1 nebo nižší.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">Abbrechen</string>
<string name="install_amiibo_keys">Amiibo-Schlüssel installieren</string>
<string name="install_amiibo_keys_description">Benötigt um Amiibos im Spiel zu verwenden</string>
<string name="invalid_keys_file">Ungültige Schlüsseldatei ausgewählt</string>
<string name="install_keys_success">Schlüssel erfolgreich installiert</string>
<string name="reading_keys_failure">Fehler beim Lesen der Schlüssel</string>
<string name="install_prod_keys_failure_extension_description">Überprüfen Sie, ob Ihre Schlüsseldatei die Erweiterung \".keys\" hat, und versuchen Sie es erneut.</string>
<string name="install_amiibo_keys_failure_extension_description">Überprüfen Sie, ob Ihre Schlüsseldatei die Erweiterung \".bin\" hat, und versuchen Sie es erneut.</string>
<string name="invalid_keys_error">Ungültige Schlüssel</string>
<string name="install_keys_failure_description">Die ausgewählte Datei ist falsch oder beschädigt. Bitte kopieren Sie Ihre Schlüssel erneut.</string>
<string name="gpu_driver_manager">GPU-Treiber Verwaltung</string>
<string name="install_gpu_driver">GPU-Treiber installieren</string>
<string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
@ -415,8 +409,6 @@ Wirklich fortfahren?</string>
<string name="verify_installed_content_description">Überprüft installierte Inhalte auf Fehler</string>
<string name="keys_missing">Schlüssel fehlen</string>
<string name="keys_missing_description">Firmware und Spiele können nicht entschlüsselt werden</string>
<string name="firmware_missing">Firmware fehlt oder ist zu neu</string>
<string name="firmware_missing_description">Einige Spiele funktionieren möglicherweise nicht richtig. Eden erfordert Firmware 19.0.1 oder älter.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">Cancelar</string>
<string name="install_amiibo_keys">Instalar claves de Amiibo</string>
<string name="install_amiibo_keys_description">Necesario para usar Amiibos en el juego</string>
<string name="invalid_keys_file">Archivo de claves seleccionado no válido</string>
<string name="install_keys_success">Claves instaladas correctamente</string>
<string name="reading_keys_failure">Error al leer las claves de cifrado</string>
<string name="install_prod_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .keys y pruebe otra vez.</string>
<string name="install_amiibo_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .bin y pruebe otra vez.</string>
<string name="invalid_keys_error">Claves de cifrado no válidas</string>
<string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string>
<string name="gpu_driver_manager">Explorador de drivers de GPU</string>
<string name="install_gpu_driver">Instalar driver de GPU</string>
<string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string>
@ -428,8 +422,6 @@
<string name="verify_installed_content_description">Comprueba todo el contenido instalado por si hubiese alguno corrupto</string>
<string name="keys_missing">Faltan las claves de encriptación</string>
<string name="keys_missing_description">El firmware y los juegos no se pueden desencriptar</string>
<string name="firmware_missing">Falta el firmware o es demasiado nuevo</string>
<string name="firmware_missing_description">Algunos juegos pueden no funcionar correctamente. Eden requiere firmware 19.0.1 o inferior.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">لغو</string>
<string name="install_amiibo_keys">کلیدهای Amiibo را نصب کنید</string>
<string name="install_amiibo_keys_description">برای استفاده از Amiibo در بازی لازم است</string>
<string name="invalid_keys_file">فایل کلیدهای نامعتبر انتخاب شد</string>
<string name="install_keys_success">کلیدها با موفقیت نصب شدند</string>
<string name="reading_keys_failure">خطا در خواندن کلیدهای رمزگذاری</string>
<string name="install_prod_keys_failure_extension_description">بررسی کنید که فایل کلیدهای شما دارای پسوند keys. باشد و دوباره امتحان کنید.</string>
<string name="install_amiibo_keys_failure_extension_description">بررسی کنید که فایل کلیدهای شما دارای پسوند bin. باشد و دوباره امتحان کنید.</string>
<string name="invalid_keys_error">کلیدهای رمزگذاری نامعتبر</string>
<string name="install_keys_failure_description">فایل انتخابی نادرست یا خراب است. لطفا کلیدهای خود را دوباره استخراج کنید.</string>
<string name="gpu_driver_manager">مدیریت درایور پردازنده گرافیکی</string>
<string name="install_gpu_driver">نصب درایور پردازنده گرافیکی</string>
<string name="install_gpu_driver_description">درایورهای جایگزین را برای عملکرد یا دقت بهتر نصب کنید</string>
@ -426,8 +420,6 @@
<string name="verify_installed_content_description">تمام محتوای نصب شده را از نظر خرابی بررسی می‌کند</string>
<string name="keys_missing">کلیدهای رمزگذاری وجود ندارند</string>
<string name="keys_missing_description">ثابت‌افزار و بازی‌های فروشگاهی قابل رمزگشایی نیستند</string>
<string name="firmware_missing">فریمور وجود ندارد یا خیلی جدید است</string>
<string name="firmware_missing_description">برخی بازی‌ها ممکن است به درستی کار نکنند. ایدن به فریمور نسخه 19.0.1 یا پایین‌تر نیاز دارد.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">Annuler</string>
<string name="install_amiibo_keys">Installer les clés Amiibo</string>
<string name="install_amiibo_keys_description">Nécessaire pour utiliser les Amiibo en jeu</string>
<string name="invalid_keys_file">Fichier de clés sélectionné invalide</string>
<string name="install_keys_success">Clés installées avec succès</string>
<string name="reading_keys_failure">Erreur lors de la lecture des clés de chiffrement</string>
<string name="install_prod_keys_failure_extension_description">Vérifiez que votre fichier de clés a une extension .keys et réessayez.</string>
<string name="install_amiibo_keys_failure_extension_description">Vérifiez que votre fichier de clés a une extension .bin et réessayez.</string>
<string name="invalid_keys_error">Clés de chiffrement invalides</string>
<string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string>
<string name="gpu_driver_manager">Gestionnaire de pilotes du GPU</string>
<string name="install_gpu_driver">Installer le pilote du GPU</string>
<string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string>
@ -428,8 +422,6 @@
<string name="verify_installed_content_description">Vérifie l\'intégrité des contenus installés</string>
<string name="keys_missing">Les clés de chiffrement sont manquantes.</string>
<string name="keys_missing_description">Le firmware et les jeux commerciaux ne peuvent pas être déchiffrés</string>
<string name="firmware_missing">Firmware manquant ou trop récent</string>
<string name="firmware_missing_description">Certains jeux peuvent ne pas fonctionner correctement. Eden nécessite le firmware 19.0.1 ou antérieur.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -348,13 +348,7 @@
<string name="warning_cancel">ביטול</string>
<string name="install_amiibo_keys">התקן מפתחות Amiibo</string>
<string name="install_amiibo_keys_description">נחוץ כדי להשתמש ב Amiibo במשחק</string>
<string name="invalid_keys_file">קובץ מפתחות לא חוקי נבחר</string>
<string name="install_keys_success">מפתחות הותקנו בהצלחה</string>
<string name="reading_keys_failure">שגיאה בקריאת מפתחות ההצפנה</string>
<string name="install_prod_keys_failure_extension_description">ודא שלקובץ המפתחות שלך יש סיומת של key. ונסה/י שוב.</string>
<string name="install_amiibo_keys_failure_extension_description">ודא/י שלקובץ המפתחות שלך יש סיומת של bin. ונסה/י שוב.</string>
<string name="invalid_keys_error">מפתחות הצפנה לא חוקיים</string>
<string name="install_keys_failure_description">קבוץ שנבחר מושחת או לא נכון. בבקשה הוצא מחדש את המפתחות שלך.</string>
<string name="gpu_driver_manager">מנהל הדרייברים של המעבד הגרפי</string>
<string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string>
<string name="install_gpu_driver_description">התקן דרייברים אחרים בשביל סיכוי לביצועים או דיוק גבוההים יותר</string>
@ -427,8 +421,6 @@
<string name="verify_installed_content_description">בודק תוכן מותקן לשגיאות</string>
<string name="keys_missing">מפתחות הצפנה חסרים</string>
<string name="keys_missing_description">לא ניתן לפענח firmware ומשחקים</string>
<string name="firmware_missing">קושחה חסרה או חדשה מדי</string>
<string name="firmware_missing_description">חלק מהמשחקים עשויים לא לפעול כראוי. Eden דורש קושחה בגרסה 19.0.1 או נמוכה יותר.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">Mégse</string>
<string name="install_amiibo_keys">Amiibo kulcsok telepítése</string>
<string name="install_amiibo_keys_description">Amiibo használata szükséges a játékhoz</string>
<string name="invalid_keys_file">Érvénytelen titkosítófájlok kiválasztva</string>
<string name="install_keys_success">Kulcsok sikeresen telepítve</string>
<string name="reading_keys_failure">Hiba történt a titkosítókulcsok olvasása során</string>
<string name="install_prod_keys_failure_extension_description">Győződj meg róla, hogy a titkosító fájlod .keys kiterjesztéssel rendelkezik, majd próbáld újra.</string>
<string name="install_amiibo_keys_failure_extension_description">Győződj meg róla, hogy a titkosító fájlod .bin kiterjesztéssel rendelkezik, majd próbáld újra.</string>
<string name="invalid_keys_error">Érvénytelen titkosítókulcsok</string>
<string name="install_keys_failure_description">A kiválasztott fájl helytelen, vagy sérült. Állíts össze egy új kulcsot.</string>
<string name="gpu_driver_manager">GPU illesztőprogram-kezelő</string>
<string name="install_gpu_driver">GPU illesztőprogram telepítése</string>
<string name="install_gpu_driver_description">Alternatív illesztőprogramok telepítése az esetlegesen elérhető teljesítmény és pontosság érdekében</string>
@ -424,8 +418,6 @@
<string name="verify_installed_content_description">A telepített tartalom épségét ellenőrzi</string>
<string name="keys_missing">Hiányzó titkosítókulcsok</string>
<string name="keys_missing_description">A Firmware és a kiskereskedelmi (retail) játékok nem dekódolhatók</string>
<string name="firmware_missing">Hiányzó vagy túl új firmware</string>
<string name="firmware_missing_description">Néhány játék nem fog megfelelően működni. Az Eden 19.0.1 vagy régebbi firmware-t igényel.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">Batalkan</string>
<string name="install_amiibo_keys">Install Amiibo keys</string>
<string name="install_amiibo_keys_description">Diperlukan untuk menggunakan Amiibo di dalam game</string>
<string name="invalid_keys_file">Keys yang dipilih invalid</string>
<string name="install_keys_success">Keys berhasil diinstal</string>
<string name="reading_keys_failure">Error saat mengecek enkripsi keys</string>
<string name="install_prod_keys_failure_extension_description">Pastikan file keys anda memiliki format .keys dan coba lagi.</string>
<string name="install_amiibo_keys_failure_extension_description">Pastikan file keys anda memiliki format .bin dan coba lagi.</string>
<string name="invalid_keys_error">Keys enkripsi tidak valid</string>
<string name="install_keys_failure_description">File yang dipilih salah atau rusak. Silakan masukkan kembali kunci Anda.</string>
<string name="gpu_driver_manager">Manajer driver GPU</string>
<string name="install_gpu_driver">Install driver GPU</string>
<string name="install_gpu_driver_description">Instal driver lain untuk kinerja atau akurasi yang berpotensi lebih baik</string>
@ -424,8 +418,6 @@
<string name="verify_installed_content_description">Memeriksa semua konten yang terinstal dari kerusakan</string>
<string name="keys_missing">Kunci enkripsi hilang</string>
<string name="keys_missing_description">Firmware dan game retail tidak dapat didekripsi</string>
<string name="firmware_missing">Firmware hilang atau terlalu baru</string>
<string name="firmware_missing_description">Beberapa game mungkin tidak berfungsi dengan baik. Eden memerlukan firmware 19.0.1 atau lebih rendah.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -348,13 +348,7 @@
<string name="warning_cancel">Annulla</string>
<string name="install_amiibo_keys">Installa le chiavi degli Amiibo</string>
<string name="install_amiibo_keys_description">Necessario per usare gli Amiibo in gioco</string>
<string name="invalid_keys_file">Selezionate chiavi non valide</string>
<string name="install_keys_success">Chiavi installate correttamente</string>
<string name="reading_keys_failure">Errore durante la lettura delle chiavi di crittografia</string>
<string name="install_prod_keys_failure_extension_description">Controlla che le tue chiavi abbiano l\'estensione .keys e prova di nuovo.</string>
<string name="install_amiibo_keys_failure_extension_description">Controlla che le tue chiavi abbiano l\'estensione .bin e prova di nuovo</string>
<string name="invalid_keys_error">Chiavi di crittografia non valide</string>
<string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string>
<string name="gpu_driver_manager">Gestore driver GPU</string>
<string name="install_gpu_driver">Installa i driver GPU</string>
<string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string>
@ -427,8 +421,6 @@
<string name="verify_installed_content_description">Verifica l\'integrità di tutti i contenuti installati.</string>
<string name="keys_missing">Chiavi di crittografia mancanti</string>
<string name="keys_missing_description">Impossibile decifrare firmware e giochi retail</string>
<string name="firmware_missing">Firmware mancante o troppo recente</string>
<string name="firmware_missing_description">Alcuni giochi potrebbero non funzionare correttamente. Eden richiede il firmware 19.0.1 o precedente.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">キャンセル</string>
<string name="install_amiibo_keys">Amiibo</string>
<string name="install_amiibo_keys_description">ゲーム内での Amiibo の使用に必要です</string>
<string name="invalid_keys_file">無効なキーファイルです</string>
<string name="install_keys_success">正常にインストールされました</string>
<string name="reading_keys_failure">暗号化キーの読み込み失敗</string>
<string name="install_prod_keys_failure_extension_description">キーの拡張子が.keysであることを確認し、再度お試しください。</string>
<string name="install_amiibo_keys_failure_extension_description">キーの拡張子が.binであることを確認し、再度お試しください。</string>
<string name="invalid_keys_error">暗号化キーが無効</string>
<string name="install_keys_failure_description">ファイルが間違っているか破損しています。キーを再ダンプしてください。</string>
<string name="gpu_driver_manager">GPUドライバーの管理</string>
<string name="install_gpu_driver">GPUドライバー</string>
<string name="install_gpu_driver_description">代替ドライバーをインストールしてパフォーマンスや精度を向上させます</string>
@ -417,8 +411,6 @@
<string name="verify_installed_content_description">すべてのインストール済みコンテンツの整合性を確認</string>
<string name="keys_missing">暗号化キーが不足</string>
<string name="keys_missing_description">ファームウェアと製品版ゲームを復号化できません</string>
<string name="firmware_missing">ファームウェアがないか、バージョンが新しすぎます</string>
<string name="firmware_missing_description">一部のゲームが正常に動作しない可能性があります。Edenは19.0.1以下のファームウェアが必要です。</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">취소</string>
<string name="install_amiibo_keys">amiibo 키 설치</string>
<string name="install_amiibo_keys_description">게임에서 amiibo 사용 시 필요</string>
<string name="invalid_keys_file">잘못된 키 파일이 선택됨</string>
<string name="install_keys_success">키 값을 설치했습니다.</string>
<string name="reading_keys_failure">암호화 키 읽기 오류</string>
<string name="install_prod_keys_failure_extension_description">키 파일의 확장자가 .keys인지 확인하고 다시 시도하세요.</string>
<string name="install_amiibo_keys_failure_extension_description">키 파일의 확장자가 .bin인지 확인하고 다시 시도하세요.</string>
<string name="invalid_keys_error">암호화 키가 올바르지 않음</string>
<string name="install_keys_failure_description">선택한 파일이 잘못되었거나 손상되었습니다. 키를 다시 덤프하세요.</string>
<string name="gpu_driver_manager">GPU 드라이버 관리자</string>
<string name="install_gpu_driver">GPU 드라이버 설치</string>
<string name="install_gpu_driver_description">잠재적인 성능 또는 정확도 개선을 위해 대체 드라이버 설치</string>
@ -423,8 +417,6 @@
<string name="verify_installed_content_description">전체 설치된 콘텐츠의 손상을 확인합니다.</string>
<string name="keys_missing">암호화 키를 찾을 수 없음</string>
<string name="keys_missing_description">펌웨어 및 패키지 게임을 해독할 수 없음</string>
<string name="firmware_missing">펌웨어가 없거나 버전이 너무 높습니다</string>
<string name="firmware_missing_description">일부 게임이 제대로 작동하지 않을 수 있습니다. Eden은 19.0.1 이하 버전의 펌웨어가 필요합니다.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -344,13 +344,7 @@
<string name="warning_cancel">Avbryt</string>
<string name="install_amiibo_keys">Installer Amiibo-nøkler</string>
<string name="install_amiibo_keys_description">Kreves for å bruke Amiibo i spillet</string>
<string name="invalid_keys_file">Ugyldig nøkkelfil valgt</string>
<string name="install_keys_success">Nøkler vellykket installert</string>
<string name="reading_keys_failure">Feil ved lesing av krypteringsnøkler</string>
<string name="install_prod_keys_failure_extension_description">Kontroller at nøkkelfilen har filtypen .keys, og prøv igjen.</string>
<string name="install_amiibo_keys_failure_extension_description">Kontroller at nøkkelfilen har filtypen .bin, og prøv igjen.</string>
<string name="invalid_keys_error">Ugyldige krypteringsnøkler</string>
<string name="install_keys_failure_description">Den valgte filen er feil eller ødelagt. Vennligst dump nøklene på nytt.</string>
<string name="install_gpu_driver">Installer GPU-driver</string>
<string name="install_gpu_driver_description">Installer alternative drivere for potensielt bedre ytelse eller nøyaktighet.</string>
<string name="advanced_settings">Avanserte innstillinger</string>
@ -416,8 +410,6 @@
<string name="verify_installed_content_description">Sjekk for korrupsjon</string>
<string name="keys_missing">Nøkler mangler</string>
<string name="keys_missing_description">Kan ikke dekryptere firmware/spill</string>
<string name="firmware_missing">Firmware mangler eller er for ny</string>
<string name="firmware_missing_description">Noen spill fungerer kanskje ikke skikkelig. Eden krever firmware 19.0.1 eller lavere.</string>
<!-- Applet-lanseringsstrenger -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -344,13 +344,7 @@
<string name="warning_cancel">Anuluj</string>
<string name="install_amiibo_keys">Zainstaluj klucze Amiibo</string>
<string name="install_amiibo_keys_description">Wymagane aby korzystać z Amiibo w grze</string>
<string name="invalid_keys_file">Wybrano niepoprawne klucze</string>
<string name="install_keys_success">Klucze zainstalowane pomyślnie</string>
<string name="reading_keys_failure">Błąd podczas odczytu kluczy</string>
<string name="install_prod_keys_failure_extension_description">Upewnij się że twoje klucze mają rozszerzenie .keys i spróbuj ponownie.</string>
<string name="install_amiibo_keys_failure_extension_description">Upewnij się że twoje klucze mają rozszerzenie .bin i spróbuj ponownie.</string>
<string name="invalid_keys_error">Niepoprawne klucze</string>
<string name="install_keys_failure_description">Wybrany plik jest niepoprawny lub uszkodzony. Zrzuć ponownie swoje klucze.</string>
<string name="install_gpu_driver">Zainstaluj sterownik GPU</string>
<string name="install_gpu_driver_description">Użyj alternatywnych sterowników aby potencjalnie zwiększyć wydajność i naprawić błędy</string>
<string name="advanced_settings">Ustawienia zaawansowane</string>
@ -416,8 +410,6 @@
<string name="verify_installed_content_description">Sprawdza integralność zainstalowanych plików.</string>
<string name="keys_missing">Brak kluczy</string>
<string name="keys_missing_description">Firmware i gry nie mogą być odszyfrowane.</string>
<string name="firmware_missing">Brak firmware lub zbyt nowa wersja</string>
<string name="firmware_missing_description">Niektóre gry mogą nie działać poprawnie. Eden wymaga firmware w wersji 19.0.1 lub starszej.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">Cancelar</string>
<string name="install_amiibo_keys">Instalar chaves Amiibo</string>
<string name="install_amiibo_keys_description">Necessárias para usar Amiibos em um jogo</string>
<string name="invalid_keys_file">Arquivo de chaves selecionado inválido</string>
<string name="install_keys_success">Chaves instaladas com sucesso</string>
<string name="reading_keys_failure">Erro ao ler chaves de encriptação</string>
<string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .keys e tente novamente.</string>
<string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .bin e tente novamente.</string>
<string name="invalid_keys_error">Chaves de encriptação inválidas</string>
<string name="install_keys_failure_description">O arquivo selecionado está incorreto ou corrompido. Por favor extraia suas chaves novamente.</string>
<string name="gpu_driver_manager">Gerenciador de driver de GPU</string>
<string name="install_gpu_driver">Instalar driver para GPU</string>
<string name="install_gpu_driver_description">Instale drivers alternativos para desempenho ou precisão potencialmente melhores</string>
@ -428,8 +422,6 @@
<string name="verify_installed_content_description">Verifica todo o conteúdo instalado em busca de dados corrompidos</string>
<string name="keys_missing">Faltando chaves de encriptação</string>
<string name="keys_missing_description">O firmware e jogos comerciais não poderão ser decriptados</string>
<string name="firmware_missing">Firmware ausente ou muito recente</string>
<string name="firmware_missing_description">Alguns jogos podem não funcionar corretamente. O Eden requer firmware 19.0.1 ou inferior.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -347,13 +347,7 @@
<string name="warning_cancel">Cancelar</string>
<string name="install_amiibo_keys">Instala chaves Amiibo</string>
<string name="install_amiibo_keys_description">Necessário para usares Amiibo no jogo</string>
<string name="invalid_keys_file">Ficheiro de chaves inválido</string>
<string name="install_keys_success">Chaves instaladas com sucesso</string>
<string name="reading_keys_failure">Erro ao ler chaves de encriptação</string>
<string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .keys e tente novamente.</string>
<string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .bin e tente novamente.</string>
<string name="invalid_keys_error">Chaves de encriptação inválidas</string>
<string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string>
<string name="gpu_driver_manager">Gerenciador de driver de GPU</string>
<string name="install_gpu_driver">Instala driver para GPU</string>
<string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string>
@ -428,8 +422,6 @@
<string name="verify_installed_content_description">Verifica todo o conteúdo instalado em busca de dados corrompidos</string>
<string name="keys_missing">Faltando chaves de encriptação</string>
<string name="keys_missing_description">O firmware e jogos comerciais não poderão ser decriptados</string>
<string name="firmware_missing">Firmware em falta ou demasiado recente</string>
<string name="firmware_missing_description">Alguns jogos podem não funcionar corretamente. O Eden requer firmware versão 19.0.1 ou inferior.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">Отмена</string>
<string name="install_amiibo_keys">Установить ключи Amiibo</string>
<string name="install_amiibo_keys_description">Необходимо для использования Amiibo в играх</string>
<string name="invalid_keys_file">Выбран неверный файл ключей</string>
<string name="install_keys_success">Ключи успешно установлены</string>
<string name="reading_keys_failure">Ошибка при чтении ключей шифрования</string>
<string name="install_prod_keys_failure_extension_description">Убедитесь, что файл ключей имеет расширение .keys, и повторите попытку.</string>
<string name="install_amiibo_keys_failure_extension_description">Убедитесь, что файл ключей имеет расширение .bin, и повторите попытку.</string>
<string name="invalid_keys_error">Неверные ключи шифрования</string>
<string name="install_keys_failure_description">Выбранный файл неверен или поврежден. Пожалуйста, пере-дампите ваши ключи.</string>
<string name="gpu_driver_manager">Менеджер драйверов ГП</string>
<string name="install_gpu_driver">Установить драйвер ГП</string>
<string name="install_gpu_driver_description">Установите альтернативные драйверы для потенциально лучшей производительности и/или точности</string>
@ -430,8 +424,6 @@
<string name="verify_installed_content_description">Проверяет весь установленный контент на наличие повреждений</string>
<string name="keys_missing">Отсутствуют ключи шифрования</string>
<string name="keys_missing_description">Прошивка и розничные игры не могут быть расшифрованы</string>
<string name="firmware_missing">Прошивка отсутствует или слишком новая</string>
<string name="firmware_missing_description">Некоторые игры могут работать некорректно. Eden требует прошивку версии 19.0.1 или ниже.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -298,13 +298,7 @@
<string name="warning_cancel">Отказати</string>
<string name="install_amiibo_keys">Инсталирајте Амиибо Кеис</string>
<string name="install_amiibo_keys_description">Потребно је користити Амиибо у игри</string>
<string name="invalid_keys_file">Изабрана је неважећа датотека тастера</string>
<string name="install_keys_success">Кључеви су успешно инсталирани</string>
<string name="reading_keys_failure">Грешка приликом чишћења кључева за шифровање</string>
<string name="install_prod_keys_failure_extension_description">Проверите да датотека кључева има. Екеис Ектенсион и покушајте поново.</string>
<string name="install_amiibo_keys_failure_extension_description">Проверите да датотека кључева има .бин екстензију и покушајте поново.</string>
<string name="invalid_keys_error">Неважеће кључеве за шифровање</string>
<string name="install_keys_failure_description">Изабрана датотека је нетачна или оштећена. Молим вас да вам умањите кључеве.</string>
<string name="gpu_driver_fetcher">ГПУ возач фетцхер</string>
<string name="gpu_driver_manager">ГПУ управљач возача</string>
<string name="install_gpu_driver">Инсталирајте ГПУ драјвер</string>
@ -380,8 +374,6 @@
<string name="keys_missing">Шифра о шифрирањима недостају</string>
<string name="keys_missing_description">Фирмваре и малопродајне игре не могу се дешифровати</string>
<string name="firmware_missing">Фирмвер недостаје или је превише нов</string>
<string name="firmware_missing_description">Неке игре можда неће радити исправно. Eden захтева фирмвер верзије 19.0.1 или старији.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Клаунцх</string>

View file

@ -344,12 +344,6 @@
<string name="warning_cancel">Відміна</string>
<string name="install_amiibo_keys">Встановити ключі Amiibo</string>
<string name="install_amiibo_keys_description">Необхідно для використання Amiibo в іграх</string>
<string name="invalid_keys_file">Вибрано неправильний файл ключів</string>
<string name="install_keys_success">Ключі успішно встановлено</string>
<string name="reading_keys_failure">Помилка під час зчитування ключів шифрування</string>
<string name="install_prod_keys_failure_extension_description">Переконайтеся, що файл ключів має розширення .keys, і повторіть спробу.</string>
<string name="invalid_keys_error">Невірні ключі шифрування</string>
<string name="install_keys_failure_description">Обраний файл невірний або пошкоджений. Будь ласка, зробіть повторний дамп ваших ключів.</string>
<string name="install_gpu_driver">Встановити драйвер GPU</string>
<string name="install_gpu_driver_description">Встановіть альтернативні драйвери для потенційно кращої продуктивності та/або точності</string>
<string name="advanced_settings">Розширені налаштування</string>
@ -415,8 +409,6 @@
<string name="verify_installed_content_description">Перевіряє встановлений вміст на наявність помилок.</string>
<string name="keys_missing">Відсутні ключі</string>
<string name="keys_missing_description">Прошивку та роздрібні ігри не вдасться розшифрувати.</string>
<string name="firmware_missing">Прошивка відсутня або занадто нова</string>
<string name="firmware_missing_description">Деякі ігри можуть працювати неправильно. Eden вимагає прошивку версії 19.0.1 або нижче.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -344,13 +344,7 @@
<string name="warning_cancel">Huỷ</string>
<string name="install_amiibo_keys">Cài đặt Amiibo</string>
<string name="install_amiibo_keys_description">Cần thiết để dùng Amiibo trong trò chơi</string>
<string name="invalid_keys_file">Chìa khóa không hợp lệ</string>
<string name="install_keys_success">Cài đặt chìa khóa thành công</string>
<string name="reading_keys_failure">Lỗi đọc keys mã hóa</string>
<string name="install_prod_keys_failure_extension_description">Xác minh rằng tệp keys của bạn có đuôi .keys và thử lại.</string>
<string name="install_amiibo_keys_failure_extension_description">Xác minh rằng tệp keys của bạn có đuôi .bin và thử lại.</string>
<string name="invalid_keys_error">Keys mã hoá không hợp lệ</string>
<string name="install_keys_failure_description">Chọn file sai hoặc bị hỏng. Hãy xuất chìa khóa khác</string>
<string name="install_gpu_driver">Cài đặt driver GPU</string>
<string name="install_gpu_driver_description">Cài đặt driver thay thế để có thể có hiệu suất tốt và chính xác hơn</string>
<string name="advanced_settings">Cài đặt nâng cao</string>
@ -416,8 +410,6 @@
<string name="verify_installed_content_description">Kiểm tra lỗi nội dung đã cài</string>
<string name="keys_missing">Thiếu keys mã hóa</string>
<string name="keys_missing_description">Không thể giải mã firmware và game</string>
<string name="firmware_missing">Thiếu firmware hoặc phiên bản quá mới</string>
<string name="firmware_missing_description">Một số trò chơi có thể không hoạt động bình thường. Eden yêu cầu firmware phiên bản 19.0.1 hoặc thấp hơn.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -346,13 +346,7 @@
<string name="warning_cancel">取消</string>
<string name="install_amiibo_keys">安装 Amiibo 密钥文件</string>
<string name="install_amiibo_keys_description">在遊戏中使用 Amiibo 时必需</string>
<string name="invalid_keys_file">选择的密钥文件无效</string>
<string name="install_keys_success">密钥文件已成功安装</string>
<string name="reading_keys_failure">读取加密密钥时出错</string>
<string name="install_prod_keys_failure_extension_description">请确保您的密钥文件扩展名为 .keys 并重试。</string>
<string name="install_amiibo_keys_failure_extension_description">请确保您的密钥文件扩展名为 .bin 并重试。</string>
<string name="invalid_keys_error">无效的加密密钥</string>
<string name="install_keys_failure_description">选择的密钥文件不正确或已损坏。请重新转储密钥文件。</string>
<string name="gpu_driver_manager">GPU 驱动管理器</string>
<string name="install_gpu_driver">安装 GPU 驱动</string>
<string name="install_gpu_driver_description">安装替代的驱动程序以获得更好的性能和精度</string>
@ -423,8 +417,6 @@
<string name="verify_installed_content_description">检查所有安装的内容是否有损坏</string>
<string name="keys_missing">密钥缺失</string>
<string name="keys_missing_description">无法解密固件和商业游戏</string>
<string name="firmware_missing">固件缺失或版本过新</string>
<string name="firmware_missing_description">某些游戏可能无法正常运行。Eden需要19.0.1或更低版本的固件。</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -350,13 +350,7 @@
<string name="warning_cancel">取消</string>
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
<string name="install_amiibo_keys_description">需要在遊戲中使用 Amiibo</string>
<string name="invalid_keys_file">無效的金鑰檔案已選取</string>
<string name="install_keys_success">金鑰已成功安裝</string>
<string name="reading_keys_failure">讀取加密金鑰時發生錯誤</string>
<string name="install_prod_keys_failure_extension_description">驗證您的金鑰檔案是否具有 .keys 副檔名並再試一次。</string>
<string name="install_amiibo_keys_failure_extension_description">驗證您的金鑰檔案是否具有 .bin 副檔名並再試一次。</string>
<string name="invalid_keys_error">無效的加密金鑰</string>
<string name="install_keys_failure_description">選取的檔案不正確或已損毀,請重新傾印您的金鑰。</string>
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
<string name="install_gpu_driver">安裝 GPU 驅動程式</string>
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
@ -427,8 +421,6 @@
<string name="verify_installed_content_description">检查所有安装的内容是否有损坏</string>
<string name="keys_missing">密钥缺失</string>
<string name="keys_missing_description">无法解密固件和商业游戏</string>
<string name="firmware_missing">韌體缺失或版本過新</string>
<string name="firmware_missing_description">某些遊戲可能無法正常運作。Eden需要19.0.1或更低版本的韌體。</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>

View file

@ -496,4 +496,18 @@
<item>3</item>
</integer-array>
<string-array name="verifyFirmwareResults">
<item>""</item>
<item>@string/error_firmware_missing</item>
<item>@string/error_firmware_corrupted</item>
<item>@string/error_firmware_too_new</item>
</string-array>
<string-array name="installKeysResults">
<item>""</item>
<item>""</item>
<item>@string/error_keys_copy_failed</item>
<item>@string/error_keys_invalid_filename</item>
<item>@string/error_keys_failed_init</item>
</string-array>
</resources>

View file

@ -304,14 +304,8 @@
<string name="warning_cancel">Cancel</string>
<string name="install_amiibo_keys">Install Amiibo keys</string>
<string name="install_amiibo_keys_description">Required to use Amiibo in game</string>
<string name="invalid_keys_file">Invalid keys file selected</string>
<string name="install_keys_success">Keys successfully installed</string>
<string name="reading_keys_failure">Error reading encryption keys</string>
<string name="install_prod_keys_failure_extension_description">Verify your keys file has a .keys extension and try again.</string>
<string name="install_amiibo_keys_failure_extension_description">Verify your keys file has a .bin extension and try again.</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="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="install_gpu_driver">Install GPU driver</string>
@ -390,10 +384,18 @@
<string name="keys_missing_description">Firmware and retail games cannot be decrypted</string>
<string name="keys_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
<string name="firmware_missing">Firmware is missing or too new</string>
<string name="firmware_missing_description">Some games may not function properly. Eden requires firmware 19.0.1 or below.</string>
<string name="firmware_invalid">Firmware Invalid</string>
<string name="error_firmware_missing">Firmware is required to run certain games and use the Home Menu. Eden only works with firmware 19.0.1 and earlier.</string>
<string name="error_firmware_corrupted">Firmware reported as present, but was unable to be read. Check for decryption keys and redump firmware if necessary.</string>
<string name="error_firmware_too_new">Firmware is too new or could not be read. Eden only works with firmware 19.0.1 and earlier.</string>
<string name="firmware_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware</string>
<string name="keys_failed">Failed to Install Keys</string>
<string name="keys_install_success">Keys successfully installed</string>
<string name="error_keys_copy_failed">One or more keys failed to copy.</string>
<string name="error_keys_invalid_filename">Verify your keys file has a .keys extension and try again.</string>
<string name="error_keys_failed_init">Keys failed to initialize. Check that your dumping tools are up to date and re-dump keys.</string>
<!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string>
<string name="qlaunch_description">Launch applications from the system home screen</string>
@ -754,13 +756,16 @@
<!-- ROM loading errors -->
<string name="loader_error_encrypted">Your ROM is encrypted</string>
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-mirror.github.io/help/quickstart/#dumping-physical-titles-game-cards">game cartidges</a> or <a href="https://yuzu-mirror.github.io/help/quickstart/#dumping-digital-titles-eshop">installed titles</a>.]]></string>
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-mirror.github.io/help/quickstart/#dumping-physical-titles-game-cards">game cartridges</a> or <a href="https://yuzu-mirror.github.io/help/quickstart/#dumping-digital-titles-eshop">installed titles</a>.]]></string>
<string name="loader_error_encrypted_keys_description"><![CDATA[Please ensure your <a href="https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys">prod.keys</a> file is installed so that games can be decrypted.]]></string>
<string name="loader_error_video_core">An error occurred initializing the video core</string>
<string name="loader_error_video_core_description">This is usually caused by an incompatible GPU driver. Installing a custom GPU driver may resolve this problem.</string>
<string name="loader_error_invalid_format">Unable to load ROM</string>
<string name="loader_error_file_not_found">ROM file does not exist</string>
<string name="loader_requires_firmware">Game Requires Firmware</string>
<string name="loader_requires_firmware_description"><![CDATA[The game you are trying to launch requires firmware to boot or to get past the opening menu. Please <a href="https://yuzu-mirror.github.io/help/quickstart"> dump and install firmware</a>, or press "OK" to launch anyways.]]></string>
<!-- Emulation Menu -->
<string name="emulation_exit">Exit emulation</string>
<string name="emulation_done">Done</string>

File diff suppressed because it is too large Load diff

View file

@ -39,6 +39,9 @@ jclass GetDiskCacheLoadCallbackStageClass();
jclass GetGameDirClass();
jmethodID GetGameDirConstructor();
jmethodID GetDiskCacheLoadProgress();
jmethodID GetCopyToStorage();
jmethodID GetFileExists();
jmethodID GetFileExtension();
jmethodID GetExitEmulationActivity();
jmethodID GetOnEmulationStarted();

View file

@ -5,6 +5,8 @@ add_library(frontend_common STATIC
config.cpp
config.h
content_manager.h
firmware_manager.h
firmware_manager.cpp
)
create_target_directory_groups(frontend_common)

View file

@ -0,0 +1,139 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "firmware_manager.h"
#include <filesystem>
#include <common/fs/fs_paths.h>
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/logging/backend.h"
#include "core/crypto/key_manager.h"
#include "frontend_common/content_manager.h"
#ifdef ANDROID
#include <jni.h>
#include <common/android/id_cache.h>
#include <common/android/android_common.h>
#endif
FirmwareManager::KeyInstallResult
FirmwareManager::InstallKeys(std::string location, std::string extension) {
LOG_INFO(Frontend, "Installing key files from {}", location);
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
#ifdef ANDROID
JNIEnv *env = Common::Android::GetEnvForThread();
jstring jsrc = Common::Android::ToJString(env, location);
jclass native = Common::Android::GetNativeLibraryClass();
jmethodID getExtension = Common::Android::GetFileExtension();
jstring jext = static_cast<jstring>(env->CallStaticObjectMethod(
native,
getExtension,
jsrc
));
std::string ext = Common::Android::GetJString(env, jext);
if (ext != extension) {
return ErrorWrongFilename;
}
jmethodID copyToStorage = Common::Android::GetCopyToStorage();
jstring jdest = Common::Android::ToJString(env, keys_dir.string());
jboolean copyResult = env->CallStaticBooleanMethod(
native,
copyToStorage,
jsrc,
jdest
);
if (!copyResult) {
return ErrorFailedCopy;
}
#else
if (!location.ends_with(extension)) {
return ErrorWrongFilename;
}
bool prod_keys_found = false;
const std::filesystem::path prod_key_path = location;
const std::filesystem::path key_source_path = prod_key_path.parent_path();
if (!Common::FS::IsDir(key_source_path)) {
return InvalidDir;
}
std::vector<std::filesystem::path> source_key_files;
if (Common::FS::Exists(prod_key_path)) {
prod_keys_found = true;
source_key_files.emplace_back(prod_key_path);
}
if (Common::FS::Exists(key_source_path / "title.keys")) {
source_key_files.emplace_back(key_source_path / "title.keys");
}
if (Common::FS::Exists(key_source_path / "key_retail.bin")) {
source_key_files.emplace_back(key_source_path / "key_retail.bin");
}
if (source_key_files.empty() || !prod_keys_found) {
return ErrorWrongFilename;
}
for (const auto &key_file : source_key_files) {
std::filesystem::path destination_key_file = keys_dir / key_file.filename();
if (!std::filesystem::copy_file(key_file,
destination_key_file,
std::filesystem::copy_options::overwrite_existing)) {
LOG_ERROR(Frontend,
"Failed to copy file {} to {}",
key_file.string(),
destination_key_file.string());
return ErrorFailedCopy;
}
}
#endif
// Reinitialize the key manager
Core::Crypto::KeyManager::Instance().ReloadKeys();
if (ContentManager::AreKeysPresent()) {
return Success;
}
// Let the frontend handle everything else
return ErrorFailedInit;
}
FirmwareManager::FirmwareCheckResult FirmwareManager::VerifyFirmware(Core::System &system) {
if (!CheckFirmwarePresence(system)) {
return ErrorFirmwareMissing;
} else {
const auto pair = GetFirmwareVersion(system);
const auto firmware_data = pair.first;
const auto result = pair.second;
if (result.IsError()) {
LOG_INFO(Frontend, "Unable to read firmware");
return ErrorFirmwareCorrupted;
}
// TODO: update this whenever newer firmware is properly supported
if (firmware_data.major > 19) {
return ErrorFirmwareTooNew;
}
}
return FirmwareGood;
}

File diff suppressed because one or more lines are too long

View file

@ -10,6 +10,7 @@
#include "core/hle/service/am/applet_manager.h"
#include "core/loader/nca.h"
#include "core/tools/renderdoc.h"
#include "frontend_common/firmware_manager.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
@ -211,7 +212,7 @@ enum class CalloutFlag : uint32_t {
* Some games perform worse or straight-up don't work with updates,
* so this tracks which games are bad in this regard.
*/
static const QList<u64> bad_update_games{
constexpr std::array<u64, 1> bad_update_games{
0x0100F2C0115B6000 // Tears of the Kingdom
};
@ -1884,46 +1885,61 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
QSettings settings;
QStringList currentIgnored = settings.value("ignoredBadUpdates", {}).toStringList();
for (const u64 id : bad_update_games) {
const bool ignored = currentIgnored.contains(QString::number(id));
if (std::find(bad_update_games.begin(), bad_update_games.end(), params.program_id) != bad_update_games.end()
&& !currentIgnored.contains(QString::number(params.program_id))) {
QMessageBox *msg = new QMessageBox(this);
msg->setWindowTitle(tr("Game Updates Warning"));
msg->setIcon(QMessageBox::Warning);
msg->setText(tr("The game you are trying to launch is known to have performance or booting "
"issues when updates are applied. Please try increasing the memory layout to "
"6GB or 8GB if any issues occur.<br><br>Press \"OK\" to continue launching, or "
"\"Cancel\" to cancel the launch."));
if (params.program_id == id && !ignored) {
QMessageBox *msg = new QMessageBox(this);
msg->setWindowTitle(tr("Game Updates Warning"));
msg->setIcon(QMessageBox::Warning);
msg->setText(tr("The game you are trying to launch is known to have performance or booting "
"issues when updates are applied. Please try increasing the memory layout to "
"6GB or 8GB if any issues occur.<br><br>Press \"OK\" to continue launching, or "
"\"Cancel\" to cancel the launch."));
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
// TODO: TMP: Recommends more memory for TotK.
QCheckBox *dontShowAgain = new QCheckBox(msg);
dontShowAgain->setText(tr("Don't show again for this game"));
msg->setCheckBox(dontShowAgain);
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
int result = msg->exec();
QCheckBox *dontShowAgain = new QCheckBox(msg);
dontShowAgain->setText(tr("Don't show again for this game"));
msg->setCheckBox(dontShowAgain);
// wtf
QMessageBox::ButtonRole role = msg->buttonRole(msg->button((QMessageBox::StandardButton) result));
int result = msg->exec();
// wtf
QMessageBox::ButtonRole role = msg->buttonRole(msg->button((QMessageBox::StandardButton) result));
switch (role) {
case QMessageBox::RejectRole:
return false;
case QMessageBox::AcceptRole:
default:
if (dontShowAgain->isChecked()) {
currentIgnored << QString::number(params.program_id);
settings.setValue("ignoredBadUpdates", currentIgnored);
settings.sync();
}
break;
switch (role) {
case QMessageBox::RejectRole:
return false;
case QMessageBox::AcceptRole:
default:
if (dontShowAgain->isChecked()) {
currentIgnored << QString::number(params.program_id);
settings.setValue("ignoredBadUpdates", currentIgnored);
settings.sync();
}
break;
}
}
if (FirmwareManager::GameRequiresFirmware(params.program_id) && !FirmwareManager::CheckFirmwarePresence(*system)) {
QMessageBox *msg = new QMessageBox(this);
msg->setWindowTitle(tr("Game Requires Firmware"));
msg->setIcon(QMessageBox::Warning);
msg->setText(tr("The game you are trying to launch requires firmware to boot or to get past the "
"opening menu. Please <a href='https://yuzu-mirror.github.io/help/quickstart'>"
"dump and install firmware</a>, or press \"OK\" to launch anyways."));
msg->setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
int exec_result = msg->exec();
QMessageBox::ButtonRole role = msg->buttonRole(msg->button((QMessageBox::StandardButton) exec_result));
switch (role) {
case QMessageBox::RejectRole:
return false;
case QMessageBox::AcceptRole:
default:
break;
}
}
@ -1940,7 +1956,7 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
UISettings::values.callout_flags = UISettings::values.callout_flags.GetValue() |
static_cast<u32>(CalloutFlag::DRDDeprecation);
QMessageBox::warning(
this, tr("Warning Outdated Game Format"),
this, tr("Warning: Outdated Game Format"),
tr("You are using the deconstructed ROM directory format for this game, which is an "
"outdated format that has been superseded by others such as NCA, NAX, XCI, or "
"NSP. Deconstructed ROM directories lack icons, metadata, and update "
@ -1963,7 +1979,7 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
"This is usually caused by outdated GPU drivers, including integrated ones. "
"Please see the log for more details. "
"For more information on accessing the log, please see the following page: "
"<a href='https://eden-emulator.github.io/help/reference/log-files/'>"
"<a href='https://yuzu-mirror.github.io/help/reference/log-files/'>"
"How to Upload the Log File</a>. "));
break;
default:
@ -4293,8 +4309,8 @@ void GMainWindow::OnInstallFirmware() {
progress.close();
QMessageBox::warning(
this, tr("Firmware install failed"),
tr("Firmware installation cancelled, firmware may be in bad state, "
"restart eden or re-install firmware."));
tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. "
"Restart Eden or re-install firmware."));
return;
}
}
@ -4339,72 +4355,27 @@ void GMainWindow::OnInstallDecryptionKeys() {
}
const QString key_source_location = QFileDialog::getOpenFileName(
this, tr("Select Dumped Keys Location"), {}, QStringLiteral("prod.keys (prod.keys)"), {},
this, tr("Select Dumped Keys Location"), {}, QStringLiteral("Decryption Keys (*.keys)"), {},
QFileDialog::ReadOnly);
if (key_source_location.isEmpty()) {
return;
}
// Verify that it contains prod.keys, title.keys and optionally, key_retail.bin
LOG_INFO(Frontend, "Installing key files from {}", key_source_location.toStdString());
FirmwareManager::KeyInstallResult result = FirmwareManager::InstallKeys(key_source_location.toStdString(), "keys");
const std::filesystem::path prod_key_path = key_source_location.toStdString();
const std::filesystem::path key_source_path = prod_key_path.parent_path();
if (!Common::FS::IsDir(key_source_path)) {
return;
}
bool prod_keys_found = false;
std::vector<std::filesystem::path> source_key_files;
if (Common::FS::Exists(prod_key_path)) {
prod_keys_found = true;
source_key_files.emplace_back(prod_key_path);
}
if (Common::FS::Exists(key_source_path / "title.keys")) {
source_key_files.emplace_back(key_source_path / "title.keys");
}
if (Common::FS::Exists(key_source_path / "key_retail.bin")) {
source_key_files.emplace_back(key_source_path / "key_retail.bin");
}
// There should be at least prod.keys.
if (source_key_files.empty() || !prod_keys_found) {
QMessageBox::warning(this, tr("Decryption Keys install failed"),
tr("prod.keys is a required decryption key file."));
return;
}
const auto yuzu_keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
for (auto key_file : source_key_files) {
std::filesystem::path destination_key_file = yuzu_keys_dir / key_file.filename();
if (!std::filesystem::copy_file(key_file, destination_key_file,
std::filesystem::copy_options::overwrite_existing)) {
LOG_ERROR(Frontend, "Failed to copy file {} to {}", key_file.string(),
destination_key_file.string());
QMessageBox::critical(this, tr("Decryption Keys install failed"),
tr("One or more keys failed to copy."));
return;
}
}
// Reinitialize the key manager, re-read the vfs (for update/dlc files),
// and re-populate the game list in the UI if the user has already added
// game folders.
Core::Crypto::KeyManager::Instance().ReloadKeys();
system->GetFileSystemController().CreateFactories(*vfs);
game_list->PopulateAsync(UISettings::values.game_dirs);
if (ContentManager::AreKeysPresent()) {
switch (result) {
case FirmwareManager::KeyInstallResult::Success:
QMessageBox::information(this, tr("Decryption Keys install succeeded"),
tr("Decryption Keys were successfully installed"));
} else {
break;
default:
QMessageBox::critical(
this, tr("Decryption Keys install failed"),
tr("Decryption Keys failed to initialize. Check that your dumping tools are "
"up to date and re-dump keys."));
tr(FirmwareManager::GetKeyInstallResultString(result)));
break;
}
OnCheckFirmwareDecryption();
@ -5074,52 +5045,27 @@ void GMainWindow::OnCheckFirmwareDecryption() {
void GMainWindow::OnCheckFirmware()
{
if (!CheckFirmwarePresence()) {
auto result = FirmwareManager::VerifyFirmware(*system.get());
switch (result) {
case FirmwareManager::FirmwareGood:
break;
default:
QMessageBox::warning(
this, tr("Firmware Missing"),
tr("Firmware missing. Firmware is required to run certain games and use the Home Menu.\n"
"Eden only works with firmware 19.0.1 and earlier."));
} else {
Service::Set::FirmwareVersionFormat firmware_data{};
const auto result = Service::Set::GetFirmwareVersionImpl(
firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
if (result.IsError()) {
LOG_INFO(Frontend, "Unable to read firmware");
QMessageBox::warning(
this, tr("Firmware Corrupted"),
tr("Firmware reported as present, but was unable to be read. Check for decryption keys and redump firmware if necessary."));
return;
}
if (firmware_data.major > 19) {
QMessageBox::warning(
this, tr("Firmware Too New"),
tr("Firmware is too new. Eden only works with firmware 19.0.1 and earlier."));
}
this, tr("Firmware Read Error"),
tr(FirmwareManager::GetFirmwareCheckString(result)));
break;
}
}
bool GMainWindow::CheckFirmwarePresence() {
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
return false;
}
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
if (!mii_applet_nca) {
return false;
}
return true;
return FirmwareManager::CheckFirmwarePresence(*system.get());
}
void GMainWindow::SetFirmwareVersion() {
Service::Set::FirmwareVersionFormat firmware_data{};
const auto result = Service::Set::GetFirmwareVersionImpl(
firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
const auto pair = FirmwareManager::GetFirmwareVersion(*system.get());
const auto firmware_data = pair.first;
const auto result = pair.second;
if (result.IsError() || !CheckFirmwarePresence()) {
LOG_INFO(Frontend, "Installed firmware: No firmware available");