Browse Source

android: Add per-game drivers

nce_cpp
t895 2 years ago
parent
commit
6cf701ae25
  1. 2
      src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt
  2. 14
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt
  3. 18
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriversLoadingDialogFragment.kt
  4. 24
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
  5. 15
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
  6. 17
      src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
  7. 175
      src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt
  8. 10
      src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
  9. 19
      src/android/app/src/main/jni/android_config.cpp
  10. 2
      src/android/app/src/main/jni/android_config.h
  11. 3
      src/android/app/src/main/jni/android_settings.h
  12. 11
      src/android/app/src/main/res/navigation/home_navigation.xml
  13. 2
      src/common/settings.cpp
  14. 1
      src/common/settings_common.h

2
src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/DriverAdapter.kt

@ -42,7 +42,7 @@ class DriverAdapter(private val driverViewModel: DriverViewModel) :
if (driverViewModel.selectedDriver > position) { if (driverViewModel.selectedDriver > position) {
driverViewModel.setSelectedDriverIndex(driverViewModel.selectedDriver - 1) driverViewModel.setSelectedDriverIndex(driverViewModel.selectedDriver - 1)
} }
if (GpuDriverHelper.customDriverData == driverData.second) {
if (GpuDriverHelper.customDriverSettingData == driverData.second) {
driverViewModel.setSelectedDriverIndex(0) driverViewModel.setSelectedDriverIndex(0)
} }
driverViewModel.driversToDelete.add(driverData.first) driverViewModel.driversToDelete.add(driverData.first)

14
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt

@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.fragment.navArgs
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.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -36,6 +37,8 @@ class DriverManagerFragment : Fragment() {
private val homeViewModel: HomeViewModel by activityViewModels() private val homeViewModel: HomeViewModel by activityViewModels()
private val driverViewModel: DriverViewModel by activityViewModels() private val driverViewModel: DriverViewModel by activityViewModels()
private val args by navArgs<DriverManagerFragmentArgs>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
@ -57,7 +60,9 @@ class DriverManagerFragment : Fragment() {
homeViewModel.setNavigationVisibility(visible = false, animated = true) homeViewModel.setNavigationVisibility(visible = false, animated = true)
homeViewModel.setStatusBarShadeVisibility(visible = false) homeViewModel.setStatusBarShadeVisibility(visible = false)
if (!driverViewModel.isInteractionAllowed) {
driverViewModel.onOpenDriverManager(args.game)
if (!driverViewModel.isInteractionAllowed.value) {
DriversLoadingDialogFragment().show( DriversLoadingDialogFragment().show(
childFragmentManager, childFragmentManager,
DriversLoadingDialogFragment.TAG DriversLoadingDialogFragment.TAG
@ -102,10 +107,9 @@ class DriverManagerFragment : Fragment() {
setInsets() setInsets()
} }
// Start installing requested driver
override fun onStop() {
super.onStop()
driverViewModel.onCloseDriverManager()
override fun onDestroy() {
super.onDestroy()
driverViewModel.onCloseDriverManager(args.game)
} }
private fun setInsets() = private fun setInsets() =

18
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriversLoadingDialogFragment.kt

@ -47,25 +47,9 @@ class DriversLoadingDialogFragment : DialogFragment() {
viewLifecycleOwner.lifecycleScope.apply { viewLifecycleOwner.lifecycleScope.apply {
launch { launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
driverViewModel.areDriversLoading.collect { checkForDismiss() }
driverViewModel.isInteractionAllowed.collect { if (it) dismiss() }
} }
} }
launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
driverViewModel.isDriverReady.collect { checkForDismiss() }
}
}
launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
driverViewModel.isDeletingDrivers.collect { checkForDismiss() }
}
}
}
}
private fun checkForDismiss() {
if (driverViewModel.isInteractionAllowed) {
dismiss()
} }
} }

24
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt

@ -352,15 +352,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
launch { launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) { repeatOnLifecycle(Lifecycle.State.RESUMED) {
driverViewModel.isDriverReady.collect {
if (it && !emulationState.isRunning) {
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
}
updateScreenLayout()
emulationState.run(emulationActivity!!.isActivityRecreated)
driverViewModel.isInteractionAllowed.collect {
if (it) {
onEmulationStart()
} }
} }
} }
@ -368,6 +362,18 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
private fun onEmulationStart() {
if (!NativeLibrary.isRunning() && !NativeLibrary.isPaused()) {
if (!DirectoryInitialization.areDirectoriesReady) {
DirectoryInitialization.start()
}
updateScreenLayout()
emulationState.run(emulationActivity!!.isActivityRecreated)
}
}
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
if (_binding == null) { if (_binding == null) {

15
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt

@ -148,6 +148,21 @@ class GamePropertiesFragment : Fragment() {
} }
) )
if (GpuDriverHelper.supportsCustomDriverLoading()) {
add(
SubmenuProperty(
R.string.gpu_driver_manager,
R.string.install_gpu_driver_description,
R.drawable.ic_build,
detailsFlow = driverViewModel.selectedDriverTitle
) {
val action = GamePropertiesFragmentDirections
.actionPerGamePropertiesFragmentToDriverManagerFragment(args.game)
binding.root.findNavController().navigate(action)
}
)
}
if (!args.game.isHomebrew) { if (!args.game.isHomebrew) {
add( add(
SubmenuProperty( SubmenuProperty(

17
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt

@ -68,6 +68,9 @@ class HomeSettingsFragment : Fragment() {
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
homeViewModel.setNavigationVisibility(visible = true, animated = true)
homeViewModel.setStatusBarShadeVisibility(visible = true)
mainActivity = requireActivity() as MainActivity mainActivity = requireActivity() as MainActivity
val optionsList: MutableList<HomeSetting> = mutableListOf<HomeSetting>().apply { val optionsList: MutableList<HomeSetting> = mutableListOf<HomeSetting>().apply {
@ -91,13 +94,14 @@ class HomeSettingsFragment : Fragment() {
R.string.install_gpu_driver_description, R.string.install_gpu_driver_description,
R.drawable.ic_build, R.drawable.ic_build,
{ {
binding.root.findNavController()
.navigate(R.id.action_homeSettingsFragment_to_driverManagerFragment)
val action = HomeSettingsFragmentDirections
.actionHomeSettingsFragmentToDriverManagerFragment(null)
binding.root.findNavController().navigate(action)
}, },
{ GpuDriverHelper.supportsCustomDriverLoading() }, { GpuDriverHelper.supportsCustomDriverLoading() },
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.selectedDriverMetadata
driverViewModel.selectedDriverTitle
) )
) )
add( add(
@ -212,8 +216,11 @@ class HomeSettingsFragment : Fragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
exitTransition = null exitTransition = null
homeViewModel.setNavigationVisibility(visible = true, animated = true)
homeViewModel.setStatusBarShadeVisibility(visible = true)
}
override fun onResume() {
super.onResume()
driverViewModel.updateDriverNameForGame(null)
} }
override fun onDestroyView() { override fun onDestroyView() {

175
src/android/app/src/main/java/org/yuzu/yuzu_emu/model/DriverViewModel.kt

@ -7,81 +7,83 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile
import org.yuzu.yuzu_emu.utils.FileUtil import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.GpuDriverHelper import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.GpuDriverMetadata import org.yuzu.yuzu_emu.utils.GpuDriverMetadata
import org.yuzu.yuzu_emu.utils.NativeConfig
import java.io.BufferedOutputStream import java.io.BufferedOutputStream
import java.io.File import java.io.File
class DriverViewModel : ViewModel() { class DriverViewModel : ViewModel() {
private val _areDriversLoading = MutableStateFlow(false) private val _areDriversLoading = MutableStateFlow(false)
val areDriversLoading: StateFlow<Boolean> get() = _areDriversLoading
private val _isDriverReady = MutableStateFlow(true) private val _isDriverReady = MutableStateFlow(true)
val isDriverReady: StateFlow<Boolean> get() = _isDriverReady
private val _isDeletingDrivers = MutableStateFlow(false) private val _isDeletingDrivers = MutableStateFlow(false)
val isDeletingDrivers: StateFlow<Boolean> get() = _isDeletingDrivers
private val _driverList = MutableStateFlow(mutableListOf<Pair<String, GpuDriverMetadata>>())
val isInteractionAllowed: StateFlow<Boolean> =
combine(
_areDriversLoading,
_isDriverReady,
_isDeletingDrivers
) { loading, ready, deleting ->
!loading && ready && !deleting
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), initialValue = false)
private val _driverList = MutableStateFlow(GpuDriverHelper.getDrivers())
val driverList: StateFlow<MutableList<Pair<String, GpuDriverMetadata>>> get() = _driverList val driverList: StateFlow<MutableList<Pair<String, GpuDriverMetadata>>> get() = _driverList
var previouslySelectedDriver = 0 var previouslySelectedDriver = 0
var selectedDriver = -1 var selectedDriver = -1
private val _selectedDriverMetadata =
MutableStateFlow(
GpuDriverHelper.customDriverData.name
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
)
val selectedDriverMetadata: StateFlow<String> get() = _selectedDriverMetadata
// Used for showing which driver is currently installed within the driver manager card
private val _selectedDriverTitle = MutableStateFlow("")
val selectedDriverTitle: StateFlow<String> get() = _selectedDriverTitle
private val _newDriverInstalled = MutableStateFlow(false) private val _newDriverInstalled = MutableStateFlow(false)
val newDriverInstalled: StateFlow<Boolean> get() = _newDriverInstalled val newDriverInstalled: StateFlow<Boolean> get() = _newDriverInstalled
val driversToDelete = mutableListOf<String>() val driversToDelete = mutableListOf<String>()
val isInteractionAllowed
get() = !areDriversLoading.value && isDriverReady.value && !isDeletingDrivers.value
init { init {
_areDriversLoading.value = true
viewModelScope.launch {
withContext(Dispatchers.IO) {
val drivers = GpuDriverHelper.getDrivers()
val currentDriverMetadata = GpuDriverHelper.customDriverData
for (i in drivers.indices) {
if (drivers[i].second == currentDriverMetadata) {
setSelectedDriverIndex(i)
break
}
}
// If a user had installed a driver before the manager was implemented, this zips
// the installed driver to UserData/gpu_drivers/CustomDriver.zip so that it can
// be indexed and exported as expected.
if (selectedDriver == -1) {
val driverToSave =
File(GpuDriverHelper.driverStoragePath, "CustomDriver.zip")
driverToSave.createNewFile()
FileUtil.zipFromInternalStorage(
File(GpuDriverHelper.driverInstallationPath!!),
GpuDriverHelper.driverInstallationPath!!,
BufferedOutputStream(driverToSave.outputStream())
)
drivers.add(Pair(driverToSave.path, currentDriverMetadata))
setSelectedDriverIndex(drivers.size - 1)
}
val currentDriverMetadata = GpuDriverHelper.installedCustomDriverData
findSelectedDriver(currentDriverMetadata)
// If a user had installed a driver before the manager was implemented, this zips
// the installed driver to UserData/gpu_drivers/CustomDriver.zip so that it can
// be indexed and exported as expected.
if (selectedDriver == -1) {
val driverToSave =
File(GpuDriverHelper.driverStoragePath, "CustomDriver.zip")
driverToSave.createNewFile()
FileUtil.zipFromInternalStorage(
File(GpuDriverHelper.driverInstallationPath!!),
GpuDriverHelper.driverInstallationPath!!,
BufferedOutputStream(driverToSave.outputStream())
)
_driverList.value.add(Pair(driverToSave.path, currentDriverMetadata))
setSelectedDriverIndex(_driverList.value.size - 1)
}
_driverList.value = drivers
_areDriversLoading.value = false
}
// If a user had installed a driver before the config was reworked to be multiplatform,
// we have save the path of the previously selected driver to the new setting.
if (StringSetting.DRIVER_PATH.getString(true).isEmpty() && selectedDriver > 0 &&
StringSetting.DRIVER_PATH.global
) {
StringSetting.DRIVER_PATH.setString(_driverList.value[selectedDriver].first)
NativeConfig.saveGlobalConfig()
} else {
findSelectedDriver(GpuDriverHelper.customDriverSettingData)
} }
updateDriverNameForGame(null)
} }
fun setSelectedDriverIndex(value: Int) { fun setSelectedDriverIndex(value: Int) {
@ -98,9 +100,9 @@ class DriverViewModel : ViewModel() {
fun addDriver(driverData: Pair<String, GpuDriverMetadata>) { fun addDriver(driverData: Pair<String, GpuDriverMetadata>) {
val driverIndex = _driverList.value.indexOfFirst { it == driverData } val driverIndex = _driverList.value.indexOfFirst { it == driverData }
if (driverIndex == -1) { if (driverIndex == -1) {
setSelectedDriverIndex(_driverList.value.size)
_driverList.value.add(driverData) _driverList.value.add(driverData)
_selectedDriverMetadata.value = driverData.second.name
setSelectedDriverIndex(_driverList.value.size - 1)
_selectedDriverTitle.value = driverData.second.name
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver) ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
} else { } else {
setSelectedDriverIndex(driverIndex) setSelectedDriverIndex(driverIndex)
@ -111,8 +113,31 @@ class DriverViewModel : ViewModel() {
_driverList.value.remove(driverData) _driverList.value.remove(driverData)
} }
fun onCloseDriverManager() {
fun onOpenDriverManager(game: Game?) {
if (game != null) {
SettingsFile.loadCustomConfig(game)
}
val driverPath = StringSetting.DRIVER_PATH.getString()
if (driverPath.isEmpty()) {
setSelectedDriverIndex(0)
} else {
findSelectedDriver(GpuDriverHelper.getMetadataFromZip(File(driverPath)))
}
}
fun onCloseDriverManager(game: Game?) {
_isDeletingDrivers.value = true _isDeletingDrivers.value = true
StringSetting.DRIVER_PATH.setString(driverList.value[selectedDriver].first)
updateDriverNameForGame(game)
if (game == null) {
NativeConfig.saveGlobalConfig()
} else {
NativeConfig.savePerGameConfig()
NativeConfig.unloadPerGameConfig()
NativeConfig.reloadGlobalConfig()
}
viewModelScope.launch { viewModelScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
driversToDelete.forEach { driversToDelete.forEach {
@ -125,23 +150,29 @@ class DriverViewModel : ViewModel() {
_isDeletingDrivers.value = false _isDeletingDrivers.value = false
} }
} }
}
// It is the Emulation Fragment's responsibility to load per-game settings so that this function
// knows what driver to load.
fun onLaunchGame() {
_isDriverReady.value = false
if (GpuDriverHelper.customDriverData == driverList.value[selectedDriver].second) {
val selectedDriverFile = File(StringSetting.DRIVER_PATH.getString())
val selectedDriverMetadata = GpuDriverHelper.customDriverSettingData
if (GpuDriverHelper.installedCustomDriverData == selectedDriverMetadata) {
return return
} }
_isDriverReady.value = false
viewModelScope.launch { viewModelScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
if (selectedDriver == 0) {
if (selectedDriverMetadata.name == null) {
GpuDriverHelper.installDefaultDriver() GpuDriverHelper.installDefaultDriver()
setDriverReady() setDriverReady()
return@withContext return@withContext
} }
val driverToInstall = File(driverList.value[selectedDriver].first)
if (driverToInstall.exists()) {
GpuDriverHelper.installCustomDriver(driverToInstall)
if (selectedDriverFile.exists()) {
GpuDriverHelper.installCustomDriver(selectedDriverFile)
} else { } else {
GpuDriverHelper.installDefaultDriver() GpuDriverHelper.installDefaultDriver()
} }
@ -150,9 +181,43 @@ class DriverViewModel : ViewModel() {
} }
} }
private fun findSelectedDriver(currentDriverMetadata: GpuDriverMetadata) {
if (driverList.value.size == 1) {
setSelectedDriverIndex(0)
return
}
driverList.value.forEachIndexed { i: Int, driver: Pair<String, GpuDriverMetadata> ->
if (driver.second == currentDriverMetadata) {
setSelectedDriverIndex(i)
return
}
}
}
fun updateDriverNameForGame(game: Game?) {
if (!GpuDriverHelper.supportsCustomDriverLoading()) {
return
}
if (game == null || NativeConfig.isPerGameConfigLoaded()) {
updateName()
} else {
SettingsFile.loadCustomConfig(game)
updateName()
NativeConfig.unloadPerGameConfig()
NativeConfig.reloadGlobalConfig()
}
}
private fun updateName() {
_selectedDriverTitle.value = GpuDriverHelper.customDriverSettingData.name
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
}
private fun setDriverReady() { private fun setDriverReady() {
_isDriverReady.value = true _isDriverReady.value = true
_selectedDriverMetadata.value = GpuDriverHelper.customDriverData.name
_selectedDriverTitle.value = GpuDriverHelper.customDriverSettingData.name
?: YuzuApplication.appContext.getString(R.string.system_gpu_driver) ?: YuzuApplication.appContext.getString(R.string.system_gpu_driver)
} }
} }

10
src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt

@ -10,6 +10,8 @@ import java.io.File
import java.io.IOException import java.io.IOException
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import java.io.FileNotFoundException
import java.util.zip.ZipException import java.util.zip.ZipException
import java.util.zip.ZipFile import java.util.zip.ZipFile
@ -44,7 +46,7 @@ object GpuDriverHelper {
NativeLibrary.initializeGpuDriver( NativeLibrary.initializeGpuDriver(
hookLibPath, hookLibPath,
driverInstallationPath, driverInstallationPath,
customDriverData.libraryName,
installedCustomDriverData.libraryName,
fileRedirectionPath fileRedirectionPath
) )
} }
@ -190,6 +192,7 @@ object GpuDriverHelper {
} }
} }
} catch (_: ZipException) { } catch (_: ZipException) {
} catch (_: FileNotFoundException) {
} }
return GpuDriverMetadata() return GpuDriverMetadata()
} }
@ -197,9 +200,12 @@ object GpuDriverHelper {
external fun supportsCustomDriverLoading(): Boolean external fun supportsCustomDriverLoading(): Boolean
// Parse the custom driver metadata to retrieve the name. // Parse the custom driver metadata to retrieve the name.
val customDriverData: GpuDriverMetadata
val installedCustomDriverData: GpuDriverMetadata
get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME)) get() = GpuDriverMetadata(File(driverInstallationPath + META_JSON_FILENAME))
val customDriverSettingData: GpuDriverMetadata
get() = getMetadataFromZip(File(StringSetting.DRIVER_PATH.getString()))
fun initializeDirectories() { fun initializeDirectories() {
// Ensure the file redirection directory exists. // Ensure the file redirection directory exists.
val fileRedirectionDir = File(fileRedirectionPath!!) val fileRedirectionDir = File(fileRedirectionPath!!)

19
src/android/app/src/main/jni/android_config.cpp

@ -36,6 +36,7 @@ void AndroidConfig::ReadAndroidValues() {
ReadAndroidUIValues(); ReadAndroidUIValues();
ReadUIValues(); ReadUIValues();
} }
ReadDriverValues();
} }
void AndroidConfig::ReadAndroidUIValues() { void AndroidConfig::ReadAndroidUIValues() {
@ -57,6 +58,7 @@ void AndroidConfig::ReadUIValues() {
void AndroidConfig::ReadPathValues() { void AndroidConfig::ReadPathValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::Paths)); BeginGroup(Settings::TranslateCategory(Settings::Category::Paths));
AndroidSettings::values.game_dirs.clear();
const int gamedirs_size = BeginArray(std::string("gamedirs")); const int gamedirs_size = BeginArray(std::string("gamedirs"));
for (int i = 0; i < gamedirs_size; ++i) { for (int i = 0; i < gamedirs_size; ++i) {
SetArrayIndex(i); SetArrayIndex(i);
@ -71,11 +73,20 @@ void AndroidConfig::ReadPathValues() {
EndGroup(); EndGroup();
} }
void AndroidConfig::ReadDriverValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::GpuDriver));
ReadCategory(Settings::Category::GpuDriver);
EndGroup();
}
void AndroidConfig::SaveAndroidValues() { void AndroidConfig::SaveAndroidValues() {
if (global) { if (global) {
SaveAndroidUIValues(); SaveAndroidUIValues();
SaveUIValues(); SaveUIValues();
} }
SaveDriverValues();
WriteToIni(); WriteToIni();
} }
@ -111,6 +122,14 @@ void AndroidConfig::SavePathValues() {
EndGroup(); EndGroup();
} }
void AndroidConfig::SaveDriverValues() {
BeginGroup(Settings::TranslateCategory(Settings::Category::GpuDriver));
WriteCategory(Settings::Category::GpuDriver);
EndGroup();
}
std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) { std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) {
auto& map = Settings::values.linkage.by_category; auto& map = Settings::values.linkage.by_category;
if (map.contains(category)) { if (map.contains(category)) {

2
src/android/app/src/main/jni/android_config.h

@ -17,6 +17,7 @@ public:
protected: protected:
void ReadAndroidValues(); void ReadAndroidValues();
void ReadAndroidUIValues(); void ReadAndroidUIValues();
void ReadDriverValues();
void ReadHidbusValues() override {} void ReadHidbusValues() override {}
void ReadDebugControlValues() override {} void ReadDebugControlValues() override {}
void ReadPathValues() override; void ReadPathValues() override;
@ -28,6 +29,7 @@ protected:
void SaveAndroidValues(); void SaveAndroidValues();
void SaveAndroidUIValues(); void SaveAndroidUIValues();
void SaveDriverValues();
void SaveHidbusValues() override {} void SaveHidbusValues() override {}
void SaveDebugControlValues() override {} void SaveDebugControlValues() override {}
void SavePathValues() override; void SavePathValues() override;

3
src/android/app/src/main/jni/android_settings.h

@ -30,6 +30,9 @@ struct Values {
Settings::Specialization::Default, Settings::Specialization::Default,
true, true,
true}; true};
Settings::SwitchableSetting<std::string, false> driver_path{linkage, "", "driver_path",
Settings::Category::GpuDriver};
}; };
extern Values values; extern Values values;

11
src/android/app/src/main/res/navigation/home_navigation.xml

@ -111,7 +111,13 @@
<fragment <fragment
android:id="@+id/driverManagerFragment" android:id="@+id/driverManagerFragment"
android:name="org.yuzu.yuzu_emu.fragments.DriverManagerFragment" android:name="org.yuzu.yuzu_emu.fragments.DriverManagerFragment"
android:label="DriverManagerFragment" />
android:label="DriverManagerFragment" >
<argument
android:name="game"
app:argType="org.yuzu.yuzu_emu.model.Game"
app:nullable="true"
android:defaultValue="@null" />
</fragment>
<fragment <fragment
android:id="@+id/appletLauncherFragment" android:id="@+id/appletLauncherFragment"
android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment" android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment"
@ -141,6 +147,9 @@
<action <action
android:id="@+id/action_perGamePropertiesFragment_to_addonsFragment" android:id="@+id/action_perGamePropertiesFragment_to_addonsFragment"
app:destination="@id/addonsFragment" /> app:destination="@id/addonsFragment" />
<action
android:id="@+id/action_perGamePropertiesFragment_to_driverManagerFragment"
app:destination="@id/driverManagerFragment" />
</fragment> </fragment>
<action <action
android:id="@+id/action_global_perGamePropertiesFragment" android:id="@+id/action_global_perGamePropertiesFragment"

2
src/common/settings.cpp

@ -211,6 +211,8 @@ const char* TranslateCategory(Category category) {
case Category::Debugging: case Category::Debugging:
case Category::DebuggingGraphics: case Category::DebuggingGraphics:
return "Debugging"; return "Debugging";
case Category::GpuDriver:
return "GpuDriver";
case Category::Miscellaneous: case Category::Miscellaneous:
return "Miscellaneous"; return "Miscellaneous";
case Category::Network: case Category::Network:

1
src/common/settings_common.h

@ -26,6 +26,7 @@ enum class Category : u32 {
DataStorage, DataStorage,
Debugging, Debugging,
DebuggingGraphics, DebuggingGraphics,
GpuDriver,
Miscellaneous, Miscellaneous,
Network, Network,
WebService, WebService,

Loading…
Cancel
Save