diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96e42ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store + +[Bb]uild \ No newline at end of file diff --git a/CMakeModules/DownloadExternals.cmake b/CMakeModules/DownloadExternals.cmake index 1f2cc91..4a349de 100644 --- a/CMakeModules/DownloadExternals.cmake +++ b/CMakeModules/DownloadExternals.cmake @@ -17,7 +17,7 @@ elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(package_repo "ext-linux-bin/raw/main/") set(package_extension ".tar.xz") elseif (ANDROID) - set(package_repo "ext-android-bin/raw/main/") + set(package_repo "android-binaries/raw/main/") set(package_extension ".tar.xz") else() message(FATAL_ERROR "No package available for this platform") diff --git a/externals/VulkanMemoryAllocator b/externals/VulkanMemoryAllocator index 19b940e..2f382df 160000 --- a/externals/VulkanMemoryAllocator +++ b/externals/VulkanMemoryAllocator @@ -1 +1 @@ -Subproject commit 19b940e864bd3a5afb3c79e3c6788869d01a19eb +Subproject commit 2f382df218d7e8516dee3b3caccb819a62b571a2 diff --git a/externals/libadrenotools b/externals/libadrenotools index deec5f7..5cd3f5c 160000 --- a/externals/libadrenotools +++ b/externals/libadrenotools @@ -1 +1 @@ -Subproject commit deec5f75ee1a8ccbe32c8780b1d17284fc87b0f1 +Subproject commit 5cd3f5c5ceea6d9e9d435ccdd922d9b99e55d10b diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt deleted file mode 100644 index bf6f036..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ShaderProgressViewModel.kt +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.disk_shader_cache - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class ShaderProgressViewModel : ViewModel() { - private val _progress = MutableLiveData(0) - val progress: LiveData get() = _progress - - private val _max = MutableLiveData(0) - val max: LiveData get() = _max - - private val _message = MutableLiveData("") - val message: LiveData get() = _message - - fun setProgress(progress: Int) { - _progress.postValue(progress) - } - - fun setMax(max: Int) { - _max.postValue(max) - } - - fun setMessage(msg: String) { - _message.postValue(msg) - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt deleted file mode 100644 index 8a8e0a6..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/disk_shader_cache/ui/ShaderProgressDialogFragment.kt +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.disk_shader_cache.ui - -import android.app.Dialog -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.ViewModelProvider -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding -import org.yuzu.yuzu_emu.disk_shader_cache.DiskShaderCacheProgress -import org.yuzu.yuzu_emu.disk_shader_cache.ShaderProgressViewModel - -class ShaderProgressDialogFragment : DialogFragment() { - private var _binding: DialogProgressBarBinding? = null - private val binding get() = _binding!! - - private lateinit var alertDialog: AlertDialog - - private lateinit var shaderProgressViewModel: ShaderProgressViewModel - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - _binding = DialogProgressBarBinding.inflate(layoutInflater) - shaderProgressViewModel = - ViewModelProvider(requireActivity())[ShaderProgressViewModel::class.java] - - val title = requireArguments().getString(TITLE) - val message = requireArguments().getString(MESSAGE) - - isCancelable = false - alertDialog = MaterialAlertDialogBuilder(requireActivity()) - .setView(binding.root) - .setTitle(title) - .setMessage(message) - .create() - return alertDialog - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - shaderProgressViewModel.progress.observe(viewLifecycleOwner) { progress -> - binding.progressBar.progress = progress - setUpdateText() - } - shaderProgressViewModel.max.observe(viewLifecycleOwner) { max -> - binding.progressBar.max = max - setUpdateText() - } - shaderProgressViewModel.message.observe(viewLifecycleOwner) { msg -> - alertDialog.setMessage(msg) - } - synchronized(DiskShaderCacheProgress.finishLock) { - DiskShaderCacheProgress.finishLock.notifyAll() - } - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - fun onUpdateProgress(msg: String, progress: Int, max: Int) { - shaderProgressViewModel.setProgress(progress) - shaderProgressViewModel.setMax(max) - shaderProgressViewModel.setMessage(msg) - } - - private fun setUpdateText() { - binding.progressText.text = String.format( - "%d/%d", - shaderProgressViewModel.progress.value, - shaderProgressViewModel.max.value - ) - } - - companion object { - const val TAG = "ProgressDialogFragment" - const val TITLE = "title" - const val MESSAGE = "message" - - fun newInstance(title: String, message: String): ShaderProgressDialogFragment { - val frag = ShaderProgressDialogFragment() - val args = Bundle() - args.putString(TITLE, title) - args.putString(MESSAGE, message) - frag.arguments = args - return frag - } - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt deleted file mode 100644 index 474f598..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingSection.kt +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.model - -/** - * A semantically-related group of Settings objects. These Settings are - * internally stored as a HashMap. - */ -class SettingSection(val name: String) { - val settings = HashMap() - - /** - * Convenience method; inserts a value directly into the backing HashMap. - * - * @param setting The Setting to be inserted. - */ - fun putSetting(setting: AbstractSetting) { - settings[setting.key!!] = setting - } - - /** - * Convenience method; gets a value directly from the backing HashMap. - * - * @param key Used to retrieve the Setting. - * @return A Setting object (you should probably cast this before using) - */ - fun getSetting(key: String): AbstractSetting? { - return settings[key] - } - - fun mergeSection(settingSection: SettingSection) { - for (setting in settingSection.settings.values) { - putSetting(setting) - } - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt deleted file mode 100644 index bd9233d..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/SettingsViewModel.kt +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.model - -import androidx.lifecycle.ViewModel - -class SettingsViewModel : ViewModel() { - val settings = Settings() -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt deleted file mode 100644 index 93e677b..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityPresenter.kt +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -import android.content.Context -import android.os.Bundle -import android.text.TextUtils -import java.io.File -import org.yuzu.yuzu_emu.NativeLibrary -import org.yuzu.yuzu_emu.features.settings.model.Settings -import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile -import org.yuzu.yuzu_emu.utils.DirectoryInitialization -import org.yuzu.yuzu_emu.utils.Log - -class SettingsActivityPresenter(private val activityView: SettingsActivityView) { - val settings: Settings get() = activityView.settings - - private var shouldSave = false - private lateinit var menuTag: String - private lateinit var gameId: String - - fun onCreate(savedInstanceState: Bundle?, menuTag: String, gameId: String) { - this.menuTag = menuTag - this.gameId = gameId - if (savedInstanceState != null) { - shouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE) - } - } - - fun onStart() { - prepareDirectoriesIfNeeded() - } - - private fun loadSettingsUI() { - if (!settings.isLoaded) { - if (!TextUtils.isEmpty(gameId)) { - settings.loadSettings(gameId, activityView) - } else { - settings.loadSettings(activityView) - } - } - activityView.showSettingsFragment(menuTag, false, gameId) - activityView.onSettingsFileLoaded() - } - - private fun prepareDirectoriesIfNeeded() { - val configFile = - File( - "${DirectoryInitialization.userDirectory}/config/" + - "${SettingsFile.FILE_NAME_CONFIG}.ini" - ) - if (!configFile.exists()) { - Log.error( - "${DirectoryInitialization.userDirectory}/config/" + - "${SettingsFile.FILE_NAME_CONFIG}.ini" - ) - Log.error("yuzu config file could not be found!") - } - - if (!DirectoryInitialization.areDirectoriesReady) { - DirectoryInitialization.start(activityView as Context) - } - loadSettingsUI() - } - - fun onStop(finishing: Boolean) { - if (finishing && shouldSave) { - Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...") - settings.saveSettings(activityView) - } - NativeLibrary.reloadSettings() - } - - fun onSettingChanged() { - shouldSave = true - } - - fun onSettingsReset() { - shouldSave = false - } - - fun saveState(outState: Bundle) { - outState.putBoolean(KEY_SHOULD_SAVE, shouldSave) - } - - companion object { - private const val KEY_SHOULD_SAVE = "should_save" - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt deleted file mode 100644 index c186fc3..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivityView.kt +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -import org.yuzu.yuzu_emu.features.settings.model.Settings - -/** - * Abstraction for the Activity that manages SettingsFragments. - */ -interface SettingsActivityView { - /** - * Show a new SettingsFragment. - * - * @param menuTag Identifier for the settings group that should be displayed. - * @param addToStack Whether or not this fragment should replace a previous one. - */ - fun showSettingsFragment(menuTag: String, addToStack: Boolean, gameId: String) - - /** - * Called by a contained Fragment to get access to the Setting HashMap - * loaded from disk, so that each Fragment doesn't need to perform its own - * read operation. - * - * @return A HashMap of Settings. - */ - val settings: Settings - - /** - * Called when a load operation completes. - */ - fun onSettingsFileLoaded() - - /** - * Called when a load operation fails. - */ - fun onSettingsFileNotFound() - - /** - * Display a popup text message on screen. - * - * @param message The contents of the onscreen message. - * @param is_long Whether this should be a long Toast or short one. - */ - fun showToastMessage(message: String, is_long: Boolean) - - /** - * End the activity. - */ - fun finish() - - /** - * Called by a containing Fragment to tell the Activity that a setting was changed; - * unless this has been called, the Activity will not save to disk. - */ - fun onSettingChanged() -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt deleted file mode 100644 index 1ebe35e..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentView.kt +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.features.settings.ui - -import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem - -/** - * Abstraction for a screen showing a list of settings. Instances of - * this type of view will each display a layer of the setting hierarchy. - */ -interface SettingsFragmentView { - /** - * Pass an ArrayList to the View so that it can be displayed on screen. - * - * @param settingsList The result of converting the HashMap to an ArrayList - */ - fun showSettingsList(settingsList: ArrayList) - - /** - * Instructs the Fragment to load the settings screen. - */ - fun loadSettingsList() - - /** - * @return The Fragment's containing activity. - */ - val activityView: SettingsActivityView? - - /** - * Tell the Fragment to tell the containing Activity to show a new - * Fragment containing a submenu of settings. - * - * @param menuKey Identifier for the settings group that should be shown. - */ - fun loadSubMenu(menuKey: String) - - /** - * Tell the Fragment to tell the containing activity to display a toast message. - * - * @param message Text to be shown in the Toast - * @param is_long Whether this should be a long Toast or short one. - */ - fun showToastMessage(message: String?, is_long: Boolean) - - /** - * Have the fragment add a setting to the HashMap. - * - * @param setting The (possibly previously missing) new setting. - */ - fun putSetting(setting: AbstractSetting) - - /** - * Have the fragment tell the containing Activity that a setting was modified. - */ - fun onSettingChanged() -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt deleted file mode 100644 index ee2d447..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ImportExportSavesFragment.kt +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.fragments - -import android.app.Dialog -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.provider.DocumentsContract -import android.widget.Toast -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AppCompatActivity -import androidx.documentfile.provider.DocumentFile -import androidx.fragment.app.DialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import java.io.BufferedOutputStream -import java.io.File -import java.io.FileOutputStream -import java.io.FilenameFilter -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.YuzuApplication -import org.yuzu.yuzu_emu.features.DocumentProvider -import org.yuzu.yuzu_emu.getPublicFilesDir -import org.yuzu.yuzu_emu.utils.FileUtil - -class ImportExportSavesFragment : DialogFragment() { - private val context = YuzuApplication.appContext - private val savesFolder = - "${context.getPublicFilesDir().canonicalPath}/nand/user/save/0000000000000000" - - // Get first subfolder in saves folder (should be the user folder) - private val savesFolderRoot = File(savesFolder).listFiles()?.firstOrNull()?.canonicalPath ?: "" - private var lastZipCreated: File? = null - - private lateinit var startForResultExportSave: ActivityResultLauncher - private lateinit var documentPicker: ActivityResultLauncher> - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val activity = requireActivity() as AppCompatActivity - - val activityResultRegistry = requireActivity().activityResultRegistry - startForResultExportSave = activityResultRegistry.register( - "startForResultExportSaveKey", - ActivityResultContracts.StartActivityForResult() - ) { - File(context.getPublicFilesDir().canonicalPath, "temp").deleteRecursively() - } - documentPicker = activityResultRegistry.register( - "documentPickerKey", - ActivityResultContracts.OpenDocument() - ) { - it?.let { uri -> importSave(uri, activity) } - } - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return if (savesFolderRoot == "") { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.manage_save_data) - .setMessage(R.string.import_export_saves_no_profile) - .setPositiveButton(android.R.string.ok, null) - .show() - } else { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.manage_save_data) - .setMessage(R.string.manage_save_data_description) - .setNegativeButton(R.string.export_saves) { _, _ -> - exportSave() - } - .setPositiveButton(R.string.import_saves) { _, _ -> - documentPicker.launch(arrayOf("application/zip")) - } - .setNeutralButton(android.R.string.cancel, null) - .show() - } - } - - /** - * Zips the save files located in the given folder path and creates a new zip file with the current date and time. - * @return true if the zip file is successfully created, false otherwise. - */ - private fun zipSave(): Boolean { - try { - val tempFolder = File(requireContext().getPublicFilesDir().canonicalPath, "temp") - tempFolder.mkdirs() - val saveFolder = File(savesFolderRoot) - val outputZipFile = File( - tempFolder, - "yuzu saves - ${ - LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")) - }.zip" - ) - outputZipFile.createNewFile() - ZipOutputStream(BufferedOutputStream(FileOutputStream(outputZipFile))).use { zos -> - saveFolder.walkTopDown().forEach { file -> - val zipFileName = - file.absolutePath.removePrefix(savesFolderRoot).removePrefix("/") - if (zipFileName == "") { - return@forEach - } - val entry = ZipEntry("$zipFileName${(if (file.isDirectory) "/" else "")}") - zos.putNextEntry(entry) - if (file.isFile) { - file.inputStream().use { fis -> fis.copyTo(zos) } - } - } - } - lastZipCreated = outputZipFile - } catch (e: Exception) { - return false - } - return true - } - - /** - * Exports the save file located in the given folder path by creating a zip file and sharing it via intent. - */ - private fun exportSave() { - CoroutineScope(Dispatchers.IO).launch { - val wasZipCreated = zipSave() - val lastZipFile = lastZipCreated - if (!wasZipCreated || lastZipFile == null) { - withContext(Dispatchers.Main) { - Toast.makeText(context, "Failed to export save", Toast.LENGTH_LONG).show() - } - return@launch - } - - withContext(Dispatchers.Main) { - val file = DocumentFile.fromSingleUri( - context, - DocumentsContract.buildDocumentUri( - DocumentProvider.AUTHORITY, - "${DocumentProvider.ROOT_ID}/temp/${lastZipFile.name}" - ) - )!! - val intent = Intent(Intent.ACTION_SEND) - .setDataAndType(file.uri, "application/zip") - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .putExtra(Intent.EXTRA_STREAM, file.uri) - startForResultExportSave.launch(Intent.createChooser(intent, "Share save file")) - } - } - } - - /** - * Imports the save files contained in the zip file, and replaces any existing ones with the new save file. - * @param zipUri The Uri of the zip file containing the save file(s) to import. - */ - private fun importSave(zipUri: Uri, activity: AppCompatActivity) { - val inputZip = context.contentResolver.openInputStream(zipUri) - // A zip needs to have at least one subfolder named after a TitleId in order to be considered valid. - var validZip = false - val savesFolder = File(savesFolderRoot) - val cacheSaveDir = File("${context.cacheDir.path}/saves/") - cacheSaveDir.mkdir() - - if (inputZip == null) { - Toast.makeText(context, context.getString(R.string.fatal_error), Toast.LENGTH_LONG) - .show() - return - } - - val filterTitleId = - FilenameFilter { _, dirName -> dirName.matches(Regex("^0100[\\dA-Fa-f]{12}$")) } - - try { - CoroutineScope(Dispatchers.IO).launch { - FileUtil.unzip(inputZip, cacheSaveDir) - cacheSaveDir.list(filterTitleId)?.forEach { savePath -> - File(savesFolder, savePath).deleteRecursively() - File(cacheSaveDir, savePath).copyRecursively(File(savesFolder, savePath), true) - validZip = true - } - - withContext(Dispatchers.Main) { - if (!validZip) { - MessageDialogFragment.newInstance( - requireActivity(), - titleId = R.string.save_file_invalid_zip_structure, - descriptionId = R.string.save_file_invalid_zip_structure_description - ).show(activity.supportFragmentManager, MessageDialogFragment.TAG) - return@withContext - } - Toast.makeText( - context, - context.getString(R.string.save_file_imported_success), - Toast.LENGTH_LONG - ).show() - } - - cacheSaveDir.deleteRecursively() - } - } catch (e: Exception) { - Toast.makeText(context, context.getString(R.string.fatal_error), Toast.LENGTH_LONG) - .show() - } - } - - companion object { - const val TAG = "ImportExportSavesFragment" - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt deleted file mode 100644 index 8847e55..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.fragments - -import android.app.Dialog -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentActivity -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.launch -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding -import org.yuzu.yuzu_emu.model.TaskViewModel - -class IndeterminateProgressDialogFragment : DialogFragment() { - private val taskViewModel: TaskViewModel by activityViewModels() - - private lateinit var binding: DialogProgressBarBinding - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val titleId = requireArguments().getInt(TITLE) - val cancellable = requireArguments().getBoolean(CANCELLABLE) - - binding = DialogProgressBarBinding.inflate(layoutInflater) - binding.progressBar.isIndeterminate = true - val dialog = MaterialAlertDialogBuilder(requireContext()) - .setTitle(titleId) - .setView(binding.root) - - if (cancellable) { - dialog.setNegativeButton(android.R.string.cancel, null) - } - - val alertDialog = dialog.create() - alertDialog.setCanceledOnTouchOutside(false) - - if (!taskViewModel.isRunning.value) { - taskViewModel.runTask() - } - return alertDialog - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - viewLifecycleOwner.lifecycleScope.apply { - launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { - taskViewModel.isComplete.collect { - if (it) { - dismiss() - when (val result = taskViewModel.result.value) { - is String -> Toast.makeText( - requireContext(), - result, - Toast.LENGTH_LONG - ).show() - - is MessageDialogFragment -> result.show( - requireActivity().supportFragmentManager, - MessageDialogFragment.TAG - ) - - else -> { - // Do nothing - } - } - taskViewModel.clear() - } - } - } - } - launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { - taskViewModel.cancelled.collect { - if (it) { - dialog?.setTitle(R.string.cancelling) - } - } - } - } - } - } - - // By default, the ProgressDialog will immediately dismiss itself upon a button being pressed. - // Setting the OnClickListener again after the dialog is shown overrides this behavior. - override fun onResume() { - super.onResume() - val alertDialog = dialog as AlertDialog - val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE) - negativeButton.setOnClickListener { - alertDialog.setTitle(getString(R.string.cancelling)) - taskViewModel.setCancelled(true) - } - } - - companion object { - const val TAG = "IndeterminateProgressDialogFragment" - - private const val TITLE = "Title" - private const val CANCELLABLE = "Cancellable" - - fun newInstance( - activity: FragmentActivity, - titleId: Int, - cancellable: Boolean = false, - task: suspend () -> Any - ): IndeterminateProgressDialogFragment { - val dialog = IndeterminateProgressDialogFragment() - val args = Bundle() - ViewModelProvider(activity)[TaskViewModel::class.java].task = task - args.putInt(TITLE, titleId) - args.putBoolean(CANCELLABLE, cancellable) - dialog.arguments = args - return dialog - } - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt deleted file mode 100644 index b29b627..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/LongMessageDialogFragment.kt +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.fragments - -import android.app.Dialog -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import androidx.fragment.app.DialogFragment -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import org.yuzu.yuzu_emu.R - -class LongMessageDialogFragment : DialogFragment() { - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val titleId = requireArguments().getInt(TITLE) - val description = requireArguments().getString(DESCRIPTION) - val helpLinkId = requireArguments().getInt(HELP_LINK) - - val dialog = MaterialAlertDialogBuilder(requireContext()) - .setPositiveButton(R.string.close, null) - .setTitle(titleId) - .setMessage(description) - - if (helpLinkId != 0) { - dialog.setNeutralButton(R.string.learn_more) { _, _ -> - openLink(getString(helpLinkId)) - } - } - - return dialog.show() - } - - private fun openLink(link: String) { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link)) - startActivity(intent) - } - - companion object { - const val TAG = "LongMessageDialogFragment" - - private const val TITLE = "Title" - private const val DESCRIPTION = "Description" - private const val HELP_LINK = "Link" - - fun newInstance( - titleId: Int, - description: String, - helpLinkId: Int = 0 - ): LongMessageDialogFragment { - val dialog = LongMessageDialogFragment() - val bundle = Bundle() - bundle.apply { - putInt(TITLE, titleId) - putString(DESCRIPTION, description) - putInt(HELP_LINK, helpLinkId) - } - dialog.arguments = bundle - return dialog - } - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsDialogFragment.kt deleted file mode 100644 index 60e029f..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsDialogFragment.kt +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.fragments - -import android.app.Dialog -import android.content.DialogInterface -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.slider.Slider -import kotlinx.coroutines.launch -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.databinding.DialogSliderBinding -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem -import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting -import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting -import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting -import org.yuzu.yuzu_emu.model.SettingsViewModel - -class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener { - private var type = 0 - private var position = 0 - - private var defaultCancelListener = - DialogInterface.OnClickListener { _: DialogInterface?, _: Int -> closeDialog() } - - private val settingsViewModel: SettingsViewModel by activityViewModels() - - private lateinit var sliderBinding: DialogSliderBinding - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - type = requireArguments().getInt(TYPE) - position = requireArguments().getInt(POSITION) - - if (settingsViewModel.clickedItem == null) dismiss() - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return when (type) { - TYPE_RESET_SETTING -> { - MaterialAlertDialogBuilder(requireContext()) - .setMessage(R.string.reset_setting_confirmation) - .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> - settingsViewModel.clickedItem!!.setting.reset() - settingsViewModel.setAdapterItemChanged(position) - } - .setNegativeButton(android.R.string.cancel, null) - .create() - } - - SettingsItem.TYPE_SINGLE_CHOICE -> { - val item = settingsViewModel.clickedItem as SingleChoiceSetting - val value = getSelectionForSingleChoiceValue(item) - MaterialAlertDialogBuilder(requireContext()) - .setTitle(item.nameId) - .setSingleChoiceItems(item.choicesId, value, this) - .create() - } - - SettingsItem.TYPE_SLIDER -> { - sliderBinding = DialogSliderBinding.inflate(layoutInflater) - val item = settingsViewModel.clickedItem as SliderSetting - - settingsViewModel.setSliderTextValue(item.getSelectedValue().toFloat(), item.units) - sliderBinding.slider.apply { - valueFrom = item.min.toFloat() - valueTo = item.max.toFloat() - value = settingsViewModel.sliderProgress.value.toFloat() - addOnChangeListener { _: Slider, value: Float, _: Boolean -> - settingsViewModel.setSliderTextValue(value, item.units) - } - } - - MaterialAlertDialogBuilder(requireContext()) - .setTitle(item.nameId) - .setView(sliderBinding.root) - .setPositiveButton(android.R.string.ok, this) - .setNegativeButton(android.R.string.cancel, defaultCancelListener) - .create() - } - - SettingsItem.TYPE_STRING_SINGLE_CHOICE -> { - val item = settingsViewModel.clickedItem as StringSingleChoiceSetting - MaterialAlertDialogBuilder(requireContext()) - .setTitle(item.nameId) - .setSingleChoiceItems(item.choices, item.selectValueIndex, this) - .create() - } - - else -> super.onCreateDialog(savedInstanceState) - } - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return when (type) { - SettingsItem.TYPE_SLIDER -> sliderBinding.root - else -> super.onCreateView(inflater, container, savedInstanceState) - } - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - when (type) { - SettingsItem.TYPE_SLIDER -> { - viewLifecycleOwner.lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { - settingsViewModel.sliderTextValue.collect { - sliderBinding.textValue.text = it - } - } - repeatOnLifecycle(Lifecycle.State.CREATED) { - settingsViewModel.sliderProgress.collect { - sliderBinding.slider.value = it.toFloat() - } - } - } - } - } - } - - override fun onClick(dialog: DialogInterface, which: Int) { - when (settingsViewModel.clickedItem) { - is SingleChoiceSetting -> { - val scSetting = settingsViewModel.clickedItem as SingleChoiceSetting - val value = getValueForSingleChoiceSelection(scSetting, which) - scSetting.setSelectedValue(value) - } - - is StringSingleChoiceSetting -> { - val scSetting = settingsViewModel.clickedItem as StringSingleChoiceSetting - val value = scSetting.getValueAt(which) - scSetting.setSelectedValue(value) - } - - is SliderSetting -> { - val sliderSetting = settingsViewModel.clickedItem as SliderSetting - sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value) - } - } - closeDialog() - } - - private fun closeDialog() { - settingsViewModel.setAdapterItemChanged(position) - settingsViewModel.clickedItem = null - settingsViewModel.setSliderProgress(-1f) - dismiss() - } - - private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int { - val valuesId = item.valuesId - return if (valuesId > 0) { - val valuesArray = requireContext().resources.getIntArray(valuesId) - valuesArray[which] - } else { - which - } - } - - private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int { - val value = item.getSelectedValue() - val valuesId = item.valuesId - if (valuesId > 0) { - val valuesArray = requireContext().resources.getIntArray(valuesId) - for (index in valuesArray.indices) { - val current = valuesArray[index] - if (current == value) { - return index - } - } - } else { - return value - } - return -1 - } - - companion object { - const val TAG = "SettingsDialogFragment" - - const val TYPE_RESET_SETTING = -1 - - const val TITLE = "Title" - const val TYPE = "Type" - const val POSITION = "Position" - - fun newInstance( - settingsViewModel: SettingsViewModel, - clickedItem: SettingsItem, - type: Int, - position: Int - ): SettingsDialogFragment { - when (type) { - SettingsItem.TYPE_HEADER, - SettingsItem.TYPE_SWITCH, - SettingsItem.TYPE_SUBMENU, - SettingsItem.TYPE_DATETIME_SETTING, - SettingsItem.TYPE_RUNNABLE -> - throw IllegalArgumentException("[SettingsDialogFragment] Incompatible type!") - - SettingsItem.TYPE_SLIDER -> settingsViewModel.setSliderProgress( - (clickedItem as SliderSetting).getSelectedValue().toFloat() - ) - } - settingsViewModel.clickedItem = clickedItem - - val args = Bundle() - args.putInt(TYPE, type) - args.putInt(POSITION, position) - val fragment = SettingsDialogFragment() - fragment.arguments = args - return fragment - } - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt deleted file mode 100644 index a135b80..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SettingsSearchFragment.kt +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.fragments - -import android.content.Context -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.inputmethod.InputMethodManager -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.updatePadding -import androidx.core.widget.doOnTextChanged -import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle -import androidx.recyclerview.widget.LinearLayoutManager -import com.google.android.material.divider.MaterialDividerItemDecoration -import com.google.android.material.transition.MaterialSharedAxis -import info.debatty.java.stringsimilarity.Cosine -import kotlinx.coroutines.launch -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.databinding.FragmentSettingsSearchBinding -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem -import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter -import org.yuzu.yuzu_emu.model.SettingsViewModel -import org.yuzu.yuzu_emu.utils.NativeConfig -import org.yuzu.yuzu_emu.utils.ViewUtils.updateMargins - -class SettingsSearchFragment : Fragment() { - private var _binding: FragmentSettingsSearchBinding? = null - private val binding get() = _binding!! - - private var settingsAdapter: SettingsAdapter? = null - - private val settingsViewModel: SettingsViewModel by activityViewModels() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) - returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) - reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) - exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentSettingsSearchBinding.inflate(layoutInflater) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - if (savedInstanceState != null) { - binding.searchText.setText(savedInstanceState.getString(SEARCH_TEXT)) - } - - settingsAdapter = SettingsAdapter(this, requireContext()) - - val dividerDecoration = MaterialDividerItemDecoration( - requireContext(), - LinearLayoutManager.VERTICAL - ) - dividerDecoration.isLastItemDecorated = false - binding.settingsList.apply { - adapter = settingsAdapter - layoutManager = LinearLayoutManager(requireContext()) - addItemDecoration(dividerDecoration) - } - - focusSearch() - - binding.backButton.setOnClickListener { settingsViewModel.setShouldNavigateBack(true) } - binding.searchBackground.setOnClickListener { focusSearch() } - binding.clearButton.setOnClickListener { binding.searchText.setText("") } - binding.searchText.doOnTextChanged { _, _, _, _ -> - search() - binding.settingsList.smoothScrollToPosition(0) - } - viewLifecycleOwner.lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.CREATED) { - settingsViewModel.shouldReloadSettingsList.collect { - if (it) { - settingsViewModel.setShouldReloadSettingsList(false) - search() - } - } - } - } - - search() - - setInsets() - } - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - outState.putString(SEARCH_TEXT, binding.searchText.text.toString()) - } - - private fun search() { - val searchTerm = binding.searchText.text.toString().lowercase() - binding.clearButton.visibility = - if (searchTerm.isEmpty()) View.INVISIBLE else View.VISIBLE - if (searchTerm.isEmpty()) { - binding.noResultsView.visibility = View.VISIBLE - settingsAdapter?.submitList(emptyList()) - return - } - - val baseList = SettingsItem.settingsItems - val similarityAlgorithm = if (searchTerm.length > 2) Cosine() else Cosine(1) - val sortedList: List = baseList.mapNotNull { item -> - val title = getString(item.value.nameId).lowercase() - val similarity = similarityAlgorithm.similarity(searchTerm, title) - if (similarity > 0.08) { - Pair(similarity, item) - } else { - null - } - }.sortedByDescending { it.first }.mapNotNull { - val item = it.second.value - val pairedSettingKey = item.setting.pairedSettingKey - val optionalSetting: SettingsItem? = if (pairedSettingKey.isNotEmpty()) { - val pairedSettingValue = NativeConfig.getBoolean(pairedSettingKey, false) - if (pairedSettingValue) it.second.value else null - } else { - it.second.value - } - optionalSetting - } - settingsAdapter?.submitList(sortedList) - binding.noResultsView.visibility = - if (sortedList.isEmpty()) View.VISIBLE else View.INVISIBLE - } - - private fun focusSearch() { - binding.searchText.requestFocus() - val imm = requireActivity() - .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager? - imm?.showSoftInput(binding.searchText, InputMethodManager.SHOW_IMPLICIT) - } - - private fun setInsets() = - ViewCompat.setOnApplyWindowInsetsListener( - binding.root - ) { _: View, windowInsets: WindowInsetsCompat -> - val extraListSpacing = resources.getDimensionPixelSize(R.dimen.spacing_med) - val sideMargin = resources.getDimensionPixelSize(R.dimen.spacing_medlarge) - val topMargin = resources.getDimensionPixelSize(R.dimen.spacing_chip) - - val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) - val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout()) - - val leftInsets = barInsets.left + cutoutInsets.left - val rightInsets = barInsets.right + cutoutInsets.right - - binding.settingsList.updatePadding(bottom = barInsets.bottom + extraListSpacing) - binding.frameSearch.updatePadding( - left = leftInsets + sideMargin, - top = barInsets.top + topMargin, - right = rightInsets + sideMargin - ) - binding.noResultsView.updatePadding( - left = leftInsets, - right = rightInsets, - bottom = barInsets.bottom - ) - - binding.settingsList.updateMargins( - left = leftInsets + sideMargin, - right = rightInsets + sideMargin - ) - binding.divider.updateMargins( - left = leftInsets + sideMargin, - right = rightInsets + sideMargin - ) - - windowInsets - } - - companion object { - const val SEARCH_TEXT = "SearchText" - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt deleted file mode 100644 index ed79a8b..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.model - -data class Addon( - var enabled: Boolean, - val title: String, - val version: String -) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt deleted file mode 100644 index 5cb6a5d..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SettingsViewModel.kt +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.model - -import androidx.lifecycle.ViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.YuzuApplication -import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem - -class SettingsViewModel : ViewModel() { - var game: Game? = null - - var clickedItem: SettingsItem? = null - - val shouldRecreate: StateFlow get() = _shouldRecreate - private val _shouldRecreate = MutableStateFlow(false) - - val shouldNavigateBack: StateFlow get() = _shouldNavigateBack - private val _shouldNavigateBack = MutableStateFlow(false) - - val shouldShowResetSettingsDialog: StateFlow get() = _shouldShowResetSettingsDialog - private val _shouldShowResetSettingsDialog = MutableStateFlow(false) - - val shouldReloadSettingsList: StateFlow get() = _shouldReloadSettingsList - private val _shouldReloadSettingsList = MutableStateFlow(false) - - val sliderProgress: StateFlow get() = _sliderProgress - private val _sliderProgress = MutableStateFlow(-1) - - val sliderTextValue: StateFlow get() = _sliderTextValue - private val _sliderTextValue = MutableStateFlow("") - - val adapterItemChanged: StateFlow get() = _adapterItemChanged - private val _adapterItemChanged = MutableStateFlow(-1) - - fun setShouldRecreate(value: Boolean) { - _shouldRecreate.value = value - } - - fun setShouldNavigateBack(value: Boolean) { - _shouldNavigateBack.value = value - } - - fun setShouldShowResetSettingsDialog(value: Boolean) { - _shouldShowResetSettingsDialog.value = value - } - - fun setShouldReloadSettingsList(value: Boolean) { - _shouldReloadSettingsList.value = value - } - - fun setSliderTextValue(value: Float, units: String) { - _sliderProgress.value = value.toInt() - _sliderTextValue.value = String.format( - YuzuApplication.appContext.getString(R.string.value_with_units), - value.toInt().toString(), - units - ) - } - - fun setSliderProgress(value: Float) { - _sliderProgress.value = value.toInt() - } - - fun setAdapterItemChanged(value: Int) { - _adapterItemChanged.value = value - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt deleted file mode 100644 index 9cfda74..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/BiMap.kt +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.utils - -class BiMap { - private val forward: MutableMap = HashMap() - private val backward: MutableMap = HashMap() - - @Synchronized - fun add(key: K, value: V) { - forward[key] = value - backward[value] = key - } - - @Synchronized - fun getForward(key: K): V? { - return forward[key] - } - - @Synchronized - fun getBackward(key: V): K? { - return backward[key] - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt deleted file mode 100644 index eeefcdf..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.utils - -import android.view.InputDevice -import android.view.KeyEvent -import android.view.MotionEvent - -/** - * Some controllers have incorrect mappings. This class has special-case fixes for them. - */ -class ControllerMappingHelper { - /** - * Some controllers report extra button presses that can be ignored. - */ - fun shouldKeyBeIgnored(inputDevice: InputDevice, keyCode: Int): Boolean { - return if (isDualShock4(inputDevice)) { - // The two analog triggers generate analog motion events as well as a keycode. - // We always prefer to use the analog values, so throw away the button press - keyCode == KeyEvent.KEYCODE_BUTTON_L2 || keyCode == KeyEvent.KEYCODE_BUTTON_R2 - } else { - false - } - } - - /** - * Scale an axis to be zero-centered with a proper range. - */ - fun scaleAxis(inputDevice: InputDevice, axis: Int, value: Float): Float { - if (isDualShock4(inputDevice)) { - // Android doesn't have correct mappings for this controller's triggers. It reports them - // as RX & RY, centered at -1.0, and with a range of [-1.0, 1.0] - // Scale them to properly zero-centered with a range of [0.0, 1.0]. - if (axis == MotionEvent.AXIS_RX || axis == MotionEvent.AXIS_RY) { - return (value + 1) / 2.0f - } - } else if (isXboxOneWireless(inputDevice)) { - // Same as the DualShock 4, the mappings are missing. - if (axis == MotionEvent.AXIS_Z || axis == MotionEvent.AXIS_RZ) { - return (value + 1) / 2.0f - } - if (axis == MotionEvent.AXIS_GENERIC_1) { - // This axis is stuck at ~.5. Ignore it. - return 0.0f - } - } else if (isMogaPro2Hid(inputDevice)) { - // This controller has a broken axis that reports a constant value. Ignore it. - if (axis == MotionEvent.AXIS_GENERIC_1) { - return 0.0f - } - } - return value - } - - // Sony DualShock 4 controller - private fun isDualShock4(inputDevice: InputDevice): Boolean { - return inputDevice.vendorId == 0x54c && inputDevice.productId == 0x9cc - } - - // Microsoft Xbox One controller - private fun isXboxOneWireless(inputDevice: InputDevice): Boolean { - return inputDevice.vendorId == 0x45e && inputDevice.productId == 0x2e0 - } - - // Moga Pro 2 HID - private fun isMogaPro2Hid(inputDevice: InputDevice): Boolean { - return inputDevice.vendorId == 0x20d6 && inputDevice.productId == 0x6271 - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt deleted file mode 100644 index 7e8f058..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.utils - -import androidx.preference.PreferenceManager -import org.yuzu.yuzu_emu.YuzuApplication -import org.yuzu.yuzu_emu.features.settings.model.Settings - -object EmulationMenuSettings { - private val preferences = - PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) - - var joystickRelCenter: Boolean - get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER, true) - set(value) { - preferences.edit() - .putBoolean(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER, value) - .apply() - } - var dpadSlide: Boolean - get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE, true) - set(value) { - preferences.edit() - .putBoolean(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE, value) - .apply() - } - var hapticFeedback: Boolean - get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, false) - set(value) { - preferences.edit() - .putBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, value) - .apply() - } - - var showFps: Boolean - get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_SHOW_FPS, false) - set(value) { - preferences.edit() - .putBoolean(Settings.PREF_MENU_SETTINGS_SHOW_FPS, value) - .apply() - } - var showOverlay: Boolean - get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_SHOW_OVERLAY, true) - set(value) { - preferences.edit() - .putBoolean(Settings.PREF_MENU_SETTINGS_SHOW_OVERLAY, value) - .apply() - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ForegroundService.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ForegroundService.kt deleted file mode 100644 index 086d176..0000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ForegroundService.kt +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.yuzu.yuzu_emu.utils - -import android.app.PendingIntent -import android.app.Service -import android.content.Intent -import android.os.IBinder -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import org.yuzu.yuzu_emu.R -import org.yuzu.yuzu_emu.activities.EmulationActivity - -/** - * A service that shows a permanent notification in the background to avoid the app getting - * cleared from memory by the system. - */ -class ForegroundService : Service() { - companion object { - const val EMULATION_RUNNING_NOTIFICATION = 0x1000 - - const val ACTION_STOP = "stop" - } - - private fun showRunningNotification() { - // Intent is used to resume emulation if the notification is clicked - val contentIntent = PendingIntent.getActivity( - this, - 0, - Intent(this, EmulationActivity::class.java), - PendingIntent.FLAG_IMMUTABLE - ) - val builder = - NotificationCompat.Builder(this, getString(R.string.emulation_notification_channel_id)) - .setSmallIcon(R.drawable.ic_stat_notification_logo) - .setContentTitle(getString(R.string.app_name)) - .setContentText(getString(R.string.emulation_notification_running)) - .setPriority(NotificationCompat.PRIORITY_LOW) - .setOngoing(true) - .setVibrate(null) - .setSound(null) - .setContentIntent(contentIntent) - startForeground(EMULATION_RUNNING_NOTIFICATION, builder.build()) - } - - override fun onBind(intent: Intent): IBinder? { - return null - } - - override fun onCreate() { - showRunningNotification() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent == null) { - return START_NOT_STICKY - } - if (intent.action == ACTION_STOP) { - NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION) - stopForeground(STOP_FOREGROUND_REMOVE) - stopSelfResult(startId) - } - return START_STICKY - } - - override fun onDestroy() { - NotificationManagerCompat.from(this).cancel(EMULATION_RUNNING_NOTIFICATION) - } -} diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp deleted file mode 100644 index 7018a52..0000000 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "jni/android_common/android_common.h" - -#include -#include - -#include - -#include "common/string_util.h" -#include "jni/id_cache.h" - -std::string GetJString(JNIEnv* env, jstring jstr) { - if (!jstr) { - return {}; - } - - const jchar* jchars = env->GetStringChars(jstr, nullptr); - const jsize length = env->GetStringLength(jstr); - const std::u16string_view string_view(reinterpret_cast(jchars), length); - const std::string converted_string = Common::UTF16ToUTF8(string_view); - env->ReleaseStringChars(jstr, jchars); - - return converted_string; -} - -jstring ToJString(JNIEnv* env, std::string_view str) { - const std::u16string converted_string = Common::UTF8ToUTF16(str); - return env->NewString(reinterpret_cast(converted_string.data()), - static_cast(converted_string.size())); -} - -jstring ToJString(JNIEnv* env, std::u16string_view str) { - return ToJString(env, Common::UTF16ToUTF8(str)); -} - -double GetJDouble(JNIEnv* env, jobject jdouble) { - return env->GetDoubleField(jdouble, IDCache::GetDoubleValueField()); -} - -jobject ToJDouble(JNIEnv* env, double value) { - return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); -} - -s32 GetJInteger(JNIEnv* env, jobject jinteger) { - return env->GetIntField(jinteger, IDCache::GetIntegerValueField()); -} - -jobject ToJInteger(JNIEnv* env, s32 value) { - return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value); -} - -bool GetJBoolean(JNIEnv* env, jobject jboolean) { - return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField()); -} - -jobject ToJBoolean(JNIEnv* env, bool value) { - return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value); -} diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h deleted file mode 100644 index 29a338c..0000000 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include -#include "common/common_types.h" - -std::string GetJString(JNIEnv* env, jstring jstr); -jstring ToJString(JNIEnv* env, std::string_view str); -jstring ToJString(JNIEnv* env, std::u16string_view str); - -double GetJDouble(JNIEnv* env, jobject jdouble); -jobject ToJDouble(JNIEnv* env, double value); - -s32 GetJInteger(JNIEnv* env, jobject jinteger); -jobject ToJInteger(JNIEnv* env, s32 value); - -bool GetJBoolean(JNIEnv* env, jobject jboolean); -jobject ToJBoolean(JNIEnv* env, bool value); diff --git a/src/android/app/src/main/jni/applets/software_keyboard.cpp b/src/android/app/src/main/jni/applets/software_keyboard.cpp deleted file mode 100644 index 9943483..0000000 --- a/src/android/app/src/main/jni/applets/software_keyboard.cpp +++ /dev/null @@ -1,277 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include - -#include - -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/core.h" -#include "jni/android_common/android_common.h" -#include "jni/applets/software_keyboard.h" -#include "jni/id_cache.h" - -static jclass s_software_keyboard_class; -static jclass s_keyboard_config_class; -static jclass s_keyboard_data_class; -static jmethodID s_swkbd_execute_normal; -static jmethodID s_swkbd_execute_inline; - -namespace SoftwareKeyboard { - -static jobject ToJKeyboardParams(const Core::Frontend::KeyboardInitializeParameters& config) { - JNIEnv* env = IDCache::GetEnvForThread(); - jobject object = env->AllocObject(s_keyboard_config_class); - - env->SetObjectField(object, - env->GetFieldID(s_keyboard_config_class, "ok_text", "Ljava/lang/String;"), - ToJString(env, config.ok_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "header_text", "Ljava/lang/String;"), - ToJString(env, config.header_text)); - env->SetObjectField(object, - env->GetFieldID(s_keyboard_config_class, "sub_text", "Ljava/lang/String;"), - ToJString(env, config.sub_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "guide_text", "Ljava/lang/String;"), - ToJString(env, config.guide_text)); - env->SetObjectField( - object, env->GetFieldID(s_keyboard_config_class, "initial_text", "Ljava/lang/String;"), - ToJString(env, config.initial_text)); - env->SetShortField(object, - env->GetFieldID(s_keyboard_config_class, "left_optional_symbol_key", "S"), - static_cast(config.left_optional_symbol_key)); - env->SetShortField(object, - env->GetFieldID(s_keyboard_config_class, "right_optional_symbol_key", "S"), - static_cast(config.right_optional_symbol_key)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "max_text_length", "I"), - static_cast(config.max_text_length)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "min_text_length", "I"), - static_cast(config.min_text_length)); - env->SetIntField(object, - env->GetFieldID(s_keyboard_config_class, "initial_cursor_position", "I"), - static_cast(config.initial_cursor_position)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "type", "I"), - static_cast(config.type)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "password_mode", "I"), - static_cast(config.password_mode)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "text_draw_type", "I"), - static_cast(config.text_draw_type)); - env->SetIntField(object, env->GetFieldID(s_keyboard_config_class, "key_disable_flags", "I"), - static_cast(config.key_disable_flags.raw)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "use_blur_background", "Z"), - static_cast(config.use_blur_background)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "enable_backspace_button", "Z"), - static_cast(config.enable_backspace_button)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "enable_return_button", "Z"), - static_cast(config.enable_return_button)); - env->SetBooleanField(object, - env->GetFieldID(s_keyboard_config_class, "disable_cancel_button", "Z"), - static_cast(config.disable_cancel_button)); - - return object; -} - -AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobject object) { - JNIEnv* env = IDCache::GetEnvForThread(); - const jstring string = reinterpret_cast(env->GetObjectField( - object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;"))); - return ResultData{GetJString(env, string), - static_cast(env->GetIntField( - object, env->GetFieldID(s_keyboard_data_class, "result", "I")))}; -} - -AndroidKeyboard::~AndroidKeyboard() = default; - -void AndroidKeyboard::InitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { - if (is_inline) { - LOG_WARNING( - Frontend, - "(STUBBED) called, backend requested to initialize the inline software keyboard."); - - submit_inline_callback = std::move(submit_inline_callback_); - } else { - LOG_WARNING( - Frontend, - "(STUBBED) called, backend requested to initialize the normal software keyboard."); - - submit_normal_callback = std::move(submit_normal_callback_); - } - - parameters = std::move(initialize_parameters); - - LOG_INFO(Frontend, - "\nKeyboardInitializeParameters:" - "\nok_text={}" - "\nheader_text={}" - "\nsub_text={}" - "\nguide_text={}" - "\ninitial_text={}" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\ninitial_cursor_position={}" - "\ntype={}" - "\npassword_mode={}" - "\ntext_draw_type={}" - "\nkey_disable_flags={}" - "\nuse_blur_background={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - Common::UTF16ToUTF8(parameters.ok_text), Common::UTF16ToUTF8(parameters.header_text), - Common::UTF16ToUTF8(parameters.sub_text), Common::UTF16ToUTF8(parameters.guide_text), - Common::UTF16ToUTF8(parameters.initial_text), parameters.max_text_length, - parameters.min_text_length, parameters.initial_cursor_position, parameters.type, - parameters.password_mode, parameters.text_draw_type, parameters.key_disable_flags.raw, - parameters.use_blur_background, parameters.enable_backspace_button, - parameters.enable_return_button, parameters.disable_cancel_button); -} - -void AndroidKeyboard::ShowNormalKeyboard() const { - LOG_DEBUG(Frontend, "called, backend requested to show the normal software keyboard."); - - ResultData data{}; - - // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber. - std::thread([&] { - data = ResultData::CreateFromFrontend(IDCache::GetEnvForThread()->CallStaticObjectMethod( - s_software_keyboard_class, s_swkbd_execute_normal, ToJKeyboardParams(parameters))); - }).join(); - - SubmitNormalText(data); -} - -void AndroidKeyboard::ShowTextCheckDialog( - Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const { - LOG_WARNING(Frontend, "(STUBBED) called, backend requested to show the text check dialog."); -} - -void AndroidKeyboard::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to show the inline software keyboard."); - - LOG_INFO(Frontend, - "\nInlineAppearParameters:" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\nkey_top_scale_x={}" - "\nkey_top_scale_y={}" - "\nkey_top_translate_x={}" - "\nkey_top_translate_y={}" - "\ntype={}" - "\nkey_disable_flags={}" - "\nkey_top_as_floating={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - appear_parameters.max_text_length, appear_parameters.min_text_length, - appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, - appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, - appear_parameters.type, appear_parameters.key_disable_flags.raw, - appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, - appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); - - // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber. - m_is_inline_active = true; - std::thread([&] { - IDCache::GetEnvForThread()->CallStaticVoidMethod( - s_software_keyboard_class, s_swkbd_execute_inline, ToJKeyboardParams(parameters)); - }).join(); -} - -void AndroidKeyboard::HideInlineKeyboard() const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to hide the inline software keyboard."); -} - -void AndroidKeyboard::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) const { - LOG_WARNING(Frontend, - "(STUBBED) called, backend requested to change the inline keyboard text."); - - LOG_INFO(Frontend, - "\nInlineTextParameters:" - "\ninput_text={}" - "\ncursor_position={}", - Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); - - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, - text_parameters.input_text, text_parameters.cursor_position); -} - -void AndroidKeyboard::ExitKeyboard() const { - LOG_WARNING(Frontend, "(STUBBED) called, backend requested to exit the software keyboard."); -} - -void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) { - if (!m_is_inline_active) { - return; - } - - m_current_text += submitted_text; - - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, - m_current_text.size()); -} - -void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) { - static constexpr int KEYCODE_BACK = 4; - static constexpr int KEYCODE_ENTER = 66; - static constexpr int KEYCODE_DEL = 67; - - if (!m_is_inline_active) { - return; - } - - switch (key_code) { - case KEYCODE_BACK: - case KEYCODE_ENTER: - m_is_inline_active = false; - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::DecidedEnter, m_current_text, - static_cast(m_current_text.size())); - break; - case KEYCODE_DEL: - m_current_text.pop_back(); - submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, - m_current_text.size()); - break; - } -} - -void AndroidKeyboard::SubmitNormalText(const ResultData& data) const { - submit_normal_callback(data.result, Common::UTF8ToUTF16(data.text), true); -} - -void InitJNI(JNIEnv* env) { - s_software_keyboard_class = reinterpret_cast( - env->NewGlobalRef(env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard"))); - s_keyboard_config_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig"))); - s_keyboard_data_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardData"))); - - s_swkbd_execute_normal = env->GetStaticMethodID( - s_software_keyboard_class, "executeNormal", - "(Lorg/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)Lorg/yuzu/yuzu_emu/" - "applets/keyboard/SoftwareKeyboard$KeyboardData;"); - s_swkbd_execute_inline = env->GetStaticMethodID( - s_software_keyboard_class, "executeInline", - "(Lorg/yuzu/yuzu_emu/applets/keyboard/SoftwareKeyboard$KeyboardConfig;)V"); -} - -void CleanupJNI(JNIEnv* env) { - env->DeleteGlobalRef(s_software_keyboard_class); - env->DeleteGlobalRef(s_keyboard_config_class); - env->DeleteGlobalRef(s_keyboard_data_class); -} - -} // namespace SoftwareKeyboard diff --git a/src/android/app/src/main/jni/applets/software_keyboard.h b/src/android/app/src/main/jni/applets/software_keyboard.h deleted file mode 100644 index 2affc01..0000000 --- a/src/android/app/src/main/jni/applets/software_keyboard.h +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -#include "core/frontend/applets/software_keyboard.h" - -namespace SoftwareKeyboard { - -class AndroidKeyboard final : public Core::Frontend::SoftwareKeyboardApplet { -public: - ~AndroidKeyboard() override; - - void Close() const override { - ExitKeyboard(); - } - - void InitializeKeyboard(bool is_inline, - Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, - SubmitInlineCallback submit_inline_callback_) override; - - void ShowNormalKeyboard() const override; - - void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const override; - - void ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const override; - - void HideInlineKeyboard() const override; - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override; - - void ExitKeyboard() const override; - - void SubmitInlineKeyboardText(std::u16string submitted_text); - - void SubmitInlineKeyboardInput(int key_code); - -private: - struct ResultData { - static ResultData CreateFromFrontend(jobject object); - - std::string text; - Service::AM::Frontend::SwkbdResult result{}; - }; - - void SubmitNormalText(const ResultData& result) const; - - Core::Frontend::KeyboardInitializeParameters parameters{}; - - mutable SubmitNormalCallback submit_normal_callback; - mutable SubmitInlineCallback submit_inline_callback; - -private: - mutable bool m_is_inline_active{}; - std::u16string m_current_text; -}; - -// Should be called in JNI_Load -void InitJNI(JNIEnv* env); - -// Should be called in JNI_Unload -void CleanupJNI(JNIEnv* env); - -} // namespace SoftwareKeyboard - -// Native function calls -extern "C" { -JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_applets_SoftwareKeyboard_ValidateFilters( - JNIEnv* env, jclass clazz, jstring text); - -JNIEXPORT jobject JNICALL Java_org_citra_citra_1emu_applets_SoftwareKeyboard_ValidateInput( - JNIEnv* env, jclass clazz, jstring text); -} diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp deleted file mode 100644 index 81120ab..0000000 --- a/src/android/app/src/main/jni/config.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include - -#include -#include "common/fs/file.h" -#include "common/fs/fs.h" -#include "common/fs/path_util.h" -#include "common/logging/log.h" -#include "common/settings.h" -#include "common/settings_enums.h" -#include "core/hle/service/acc/profile_manager.h" -#include "input_common/main.h" -#include "jni/config.h" -#include "jni/default_ini.h" -#include "uisettings.h" - -namespace FS = Common::FS; - -Config::Config(const std::string& config_name, ConfigType config_type) - : type(config_type), global{config_type == ConfigType::GlobalConfig} { - Initialize(config_name); -} - -Config::~Config() = default; - -bool Config::LoadINI(const std::string& default_contents, bool retry) { - void(FS::CreateParentDir(config_loc)); - config = std::make_unique(FS::PathToUTF8String(config_loc)); - const auto config_loc_str = FS::PathToUTF8String(config_loc); - if (config->ParseError() < 0) { - if (retry) { - LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", - config_loc_str); - - void(FS::CreateParentDir(config_loc)); - void(FS::WriteStringToFile(config_loc, FS::FileType::TextFile, default_contents)); - - config = std::make_unique(config_loc_str); - - return LoadINI(default_contents, false); - } - LOG_ERROR(Config, "Failed."); - return false; - } - LOG_INFO(Config, "Successfully loaded {}", config_loc_str); - return true; -} - -template <> -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - std::string setting_value = config->Get(group, setting.GetLabel(), setting.GetDefault()); - if (setting_value.empty()) { - setting_value = setting.GetDefault(); - } - setting = std::move(setting_value); -} - -template <> -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - setting = config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); -} - -template -void Config::ReadSetting(const std::string& group, Settings::Setting& setting) { - setting = static_cast( - config->GetInteger(group, setting.GetLabel(), static_cast(setting.GetDefault()))); -} - -void Config::ReadValues() { - ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); - ReadSetting("ControlsGeneral", Settings::values.touch_device); - ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); - ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); - ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); - ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); - ReadSetting("ControlsGeneral", Settings::values.motion_enabled); - Settings::values.touchscreen.enabled = - config->GetBoolean("ControlsGeneral", "touch_enabled", true); - Settings::values.touchscreen.rotation_angle = - config->GetInteger("ControlsGeneral", "touch_angle", 0); - Settings::values.touchscreen.diameter_x = - config->GetInteger("ControlsGeneral", "touch_diameter_x", 15); - Settings::values.touchscreen.diameter_y = - config->GetInteger("ControlsGeneral", "touch_diameter_y", 15); - - int num_touch_from_button_maps = - config->GetInteger("ControlsGeneral", "touch_from_button_map", 0); - if (num_touch_from_button_maps > 0) { - for (int i = 0; i < num_touch_from_button_maps; ++i) { - Settings::TouchFromButtonMap map; - map.name = config->Get("ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + - std::string("_name"), - "default"); - const int num_touch_maps = config->GetInteger( - "ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"), - 0); - map.buttons.reserve(num_touch_maps); - - for (int j = 0; j < num_touch_maps; ++j) { - std::string touch_mapping = - config->Get("ControlsGeneral", - std::string("touch_from_button_maps_") + std::to_string(i) + - std::string("_bind_") + std::to_string(j), - ""); - map.buttons.emplace_back(std::move(touch_mapping)); - } - - Settings::values.touch_from_button_maps.emplace_back(std::move(map)); - } - } else { - Settings::values.touch_from_button_maps.emplace_back( - Settings::TouchFromButtonMap{"default", {}}); - num_touch_from_button_maps = 1; - } - Settings::values.touch_from_button_map_index = std::clamp( - Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); - - ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); - - // Data Storage - ReadSetting("Data Storage", Settings::values.use_virtual_sd); - FS::SetYuzuPath(FS::YuzuPath::NANDDir, - config->Get("Data Storage", "nand_directory", - FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); - FS::SetYuzuPath(FS::YuzuPath::SDMCDir, - config->Get("Data Storage", "sdmc_directory", - FS::GetYuzuPathString(FS::YuzuPath::SDMCDir))); - FS::SetYuzuPath(FS::YuzuPath::LoadDir, - config->Get("Data Storage", "load_directory", - FS::GetYuzuPathString(FS::YuzuPath::LoadDir))); - FS::SetYuzuPath(FS::YuzuPath::DumpDir, - config->Get("Data Storage", "dump_directory", - FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); - ReadSetting("Data Storage", Settings::values.gamecard_inserted); - ReadSetting("Data Storage", Settings::values.gamecard_current_game); - ReadSetting("Data Storage", Settings::values.gamecard_path); - - // System - ReadSetting("System", Settings::values.current_user); - Settings::values.current_user = std::clamp(Settings::values.current_user.GetValue(), 0, - Service::Account::MAX_USERS - 1); - - // Disable docked mode by default on Android - Settings::values.use_docked_mode.SetValue(config->GetBoolean("System", "use_docked_mode", false) - ? Settings::ConsoleMode::Docked - : Settings::ConsoleMode::Handheld); - - const auto rng_seed_enabled = config->GetBoolean("System", "rng_seed_enabled", false); - if (rng_seed_enabled) { - Settings::values.rng_seed.SetValue(config->GetInteger("System", "rng_seed", 0)); - } else { - Settings::values.rng_seed.SetValue(0); - } - Settings::values.rng_seed_enabled.SetValue(rng_seed_enabled); - - const auto custom_rtc_enabled = config->GetBoolean("System", "custom_rtc_enabled", false); - if (custom_rtc_enabled) { - Settings::values.custom_rtc = config->GetInteger("System", "custom_rtc", 0); - } else { - Settings::values.custom_rtc = 0; - } - Settings::values.custom_rtc_enabled = custom_rtc_enabled; - - ReadSetting("System", Settings::values.language_index); - ReadSetting("System", Settings::values.region_index); - ReadSetting("System", Settings::values.time_zone_index); - ReadSetting("System", Settings::values.sound_index); - - // Core - ReadSetting("Core", Settings::values.use_multi_core); - ReadSetting("Core", Settings::values.memory_layout_mode); - - // Cpu - ReadSetting("Cpu", Settings::values.cpu_accuracy); - ReadSetting("Cpu", Settings::values.cpu_debug_mode); - ReadSetting("Cpu", Settings::values.cpuopt_page_tables); - ReadSetting("Cpu", Settings::values.cpuopt_block_linking); - ReadSetting("Cpu", Settings::values.cpuopt_return_stack_buffer); - ReadSetting("Cpu", Settings::values.cpuopt_fast_dispatcher); - ReadSetting("Cpu", Settings::values.cpuopt_context_elimination); - ReadSetting("Cpu", Settings::values.cpuopt_const_prop); - ReadSetting("Cpu", Settings::values.cpuopt_misc_ir); - ReadSetting("Cpu", Settings::values.cpuopt_reduce_misalign_checks); - ReadSetting("Cpu", Settings::values.cpuopt_fastmem); - ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); - ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); - ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_inaccurate_nan); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_fastmem_check); - ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_global_monitor); - - // Renderer - ReadSetting("Renderer", Settings::values.renderer_backend); - ReadSetting("Renderer", Settings::values.renderer_debug); - ReadSetting("Renderer", Settings::values.renderer_shader_feedback); - ReadSetting("Renderer", Settings::values.enable_nsight_aftermath); - ReadSetting("Renderer", Settings::values.disable_shader_loop_safety_checks); - ReadSetting("Renderer", Settings::values.vulkan_device); - - ReadSetting("Renderer", Settings::values.resolution_setup); - ReadSetting("Renderer", Settings::values.scaling_filter); - ReadSetting("Renderer", Settings::values.fsr_sharpening_slider); - ReadSetting("Renderer", Settings::values.anti_aliasing); - ReadSetting("Renderer", Settings::values.fullscreen_mode); - ReadSetting("Renderer", Settings::values.aspect_ratio); - ReadSetting("Renderer", Settings::values.max_anisotropy); - ReadSetting("Renderer", Settings::values.use_speed_limit); - ReadSetting("Renderer", Settings::values.speed_limit); - ReadSetting("Renderer", Settings::values.use_disk_shader_cache); - ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); - ReadSetting("Renderer", Settings::values.vsync_mode); - ReadSetting("Renderer", Settings::values.shader_backend); - ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); - ReadSetting("Renderer", Settings::values.nvdec_emulation); - ReadSetting("Renderer", Settings::values.use_fast_gpu_time); - ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); - - ReadSetting("Renderer", Settings::values.bg_red); - ReadSetting("Renderer", Settings::values.bg_green); - ReadSetting("Renderer", Settings::values.bg_blue); - - // Use GPU accuracy normal by default on Android - Settings::values.gpu_accuracy = static_cast(config->GetInteger( - "Renderer", "gpu_accuracy", static_cast(Settings::GpuAccuracy::Normal))); - - // Use GPU default anisotropic filtering on Android - Settings::values.max_anisotropy = - static_cast(config->GetInteger("Renderer", "max_anisotropy", 1)); - - // Disable ASTC compute by default on Android - Settings::values.accelerate_astc.SetValue( - config->GetBoolean("Renderer", "accelerate_astc", false) ? Settings::AstcDecodeMode::Gpu - : Settings::AstcDecodeMode::Cpu); - - // Enable asynchronous presentation by default on Android - Settings::values.async_presentation = - config->GetBoolean("Renderer", "async_presentation", true); - - // Disable force_max_clock by default on Android - Settings::values.renderer_force_max_clock = - config->GetBoolean("Renderer", "force_max_clock", false); - - // Disable use_reactive_flushing by default on Android - Settings::values.use_reactive_flushing = - config->GetBoolean("Renderer", "use_reactive_flushing", false); - - // Audio - ReadSetting("Audio", Settings::values.sink_id); - ReadSetting("Audio", Settings::values.audio_output_device_id); - ReadSetting("Audio", Settings::values.volume); - - // Miscellaneous - // log_filter has a different default here than from common - Settings::values.log_filter = "*:Info"; - ReadSetting("Miscellaneous", Settings::values.use_dev_keys); - - // Debugging - Settings::values.record_frame_times = - config->GetBoolean("Debugging", "record_frame_times", false); - ReadSetting("Debugging", Settings::values.dump_exefs); - ReadSetting("Debugging", Settings::values.dump_nso); - ReadSetting("Debugging", Settings::values.enable_fs_access_log); - ReadSetting("Debugging", Settings::values.reporting_services); - ReadSetting("Debugging", Settings::values.quest_flag); - ReadSetting("Debugging", Settings::values.use_debug_asserts); - ReadSetting("Debugging", Settings::values.use_auto_stub); - ReadSetting("Debugging", Settings::values.disable_macro_jit); - ReadSetting("Debugging", Settings::values.disable_macro_hle); - ReadSetting("Debugging", Settings::values.use_gdbstub); - ReadSetting("Debugging", Settings::values.gdbstub_port); - - const auto title_list = config->Get("AddOns", "title_ids", ""); - std::stringstream ss(title_list); - std::string line; - while (std::getline(ss, line, '|')) { - const auto title_id = std::strtoul(line.c_str(), nullptr, 16); - const auto disabled_list = config->Get("AddOns", "disabled_" + line, ""); - - std::stringstream inner_ss(disabled_list); - std::string inner_line; - std::vector out; - while (std::getline(inner_ss, inner_line, '|')) { - out.push_back(inner_line); - } - - Settings::values.disabled_addons.insert_or_assign(title_id, out); - } - - // Web Service - ReadSetting("WebService", Settings::values.enable_telemetry); - ReadSetting("WebService", Settings::values.web_api_url); - ReadSetting("WebService", Settings::values.yuzu_username); - ReadSetting("WebService", Settings::values.yuzu_token); - - // Network - ReadSetting("Network", Settings::values.network_interface); - - // Android - ReadSetting("Android", AndroidSettings::values.picture_in_picture); - ReadSetting("Android", AndroidSettings::values.screen_layout); -} - -void Config::Initialize(const std::string& config_name) { - const auto fs_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir); - const auto config_file = fmt::format("{}.ini", config_name); - - switch (type) { - case ConfigType::GlobalConfig: - config_loc = FS::PathToUTF8String(fs_config_loc / config_file); - break; - case ConfigType::PerGameConfig: - config_loc = FS::PathToUTF8String(fs_config_loc / "custom" / FS::ToU8String(config_file)); - break; - case ConfigType::InputProfile: - config_loc = FS::PathToUTF8String(fs_config_loc / "input" / config_file); - LoadINI(DefaultINI::android_config_file); - return; - } - LoadINI(DefaultINI::android_config_file); - ReadValues(); -} diff --git a/src/android/app/src/main/jni/config.h b/src/android/app/src/main/jni/config.h deleted file mode 100644 index e1e8f47..0000000 --- a/src/android/app/src/main/jni/config.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include - -#include "common/settings.h" - -class INIReader; - -class Config { - bool LoadINI(const std::string& default_contents = "", bool retry = true); - -public: - enum class ConfigType { - GlobalConfig, - PerGameConfig, - InputProfile, - }; - - explicit Config(const std::string& config_name = "config", - ConfigType config_type = ConfigType::GlobalConfig); - ~Config(); - - void Initialize(const std::string& config_name); - -private: - /** - * Applies a value read from the config to a Setting. - * - * @param group The name of the INI group - * @param setting The yuzu setting to modify - */ - template - void ReadSetting(const std::string& group, Settings::Setting& setting); - - void ReadValues(); - - const ConfigType type; - std::unique_ptr config; - std::string config_loc; - const bool global; -}; diff --git a/src/android/app/src/main/jni/default_ini.h b/src/android/app/src/main/jni/default_ini.h deleted file mode 100644 index d81422a..0000000 --- a/src/android/app/src/main/jni/default_ini.h +++ /dev/null @@ -1,511 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -namespace DefaultINI { - -const char* android_config_file = R"( - -[ControlsP0] -# The input devices and parameters for each Switch native input -# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ... -# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..." -# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values - -# Indicates if this player should be connected at boot -connected= - -# for button input, the following devices are available: -# - "keyboard" (default) for keyboard input. Required parameters: -# - "code": the code of the key to bind -# - "sdl" for joystick input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "button"(optional): the index of the button to bind -# - "hat"(optional): the index of the hat to bind as direction buttons -# - "axis"(optional): the index of the axis to bind -# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right" -# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is -# triggered if the axis value crosses -# - "direction"(only used for axis): "+" means the button is triggered when the axis value -# is greater than the threshold; "-" means the button is triggered when the axis value -# is smaller than the threshold -button_a= -button_b= -button_x= -button_y= -button_lstick= -button_rstick= -button_l= -button_r= -button_zl= -button_zr= -button_plus= -button_minus= -button_dleft= -button_dup= -button_dright= -button_ddown= -button_lstick_left= -button_lstick_up= -button_lstick_right= -button_lstick_down= -button_sl= -button_sr= -button_home= -button_screenshot= - -# for analog input, the following devices are available: -# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: -# - "up", "down", "left", "right": sub-devices for each direction. -# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00" -# - "modifier": sub-devices as a modifier. -# - "modifier_scale": a float number representing the applied modifier scale to the analog input. -# Must be in range of 0.0-1.0. Defaults to 0.5 -# - "sdl" for joystick input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "axis_x": the index of the axis to bind as x-axis (default to 0) -# - "axis_y": the index of the axis to bind as y-axis (default to 1) -lstick= -rstick= - -# for motion input, the following devices are available: -# - "keyboard" (default) for emulating random motion input from buttons. Required parameters: -# - "code": the code of the key to bind -# - "sdl" for motion input using SDL. Required parameters: -# - "guid": SDL identification GUID of the joystick -# - "port": the index of the joystick to bind -# - "motion": the index of the motion sensor to bind -# - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters: -# - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001" -# - "port": the port of the cemu hook server -# - "pad": the index of the joystick -# - "motion": the index of the motion sensor of the joystick to bind -motionleft= -motionright= - -[ControlsGeneral] -# To use the debug_pad, prepend `debug_pad_` before each button setting above. -# i.e. debug_pad_button_a= - -# Enable debug pad inputs to the guest -# 0 (default): Disabled, 1: Enabled -debug_pad_enabled = - -# Whether to enable or disable vibration -# 0: Disabled, 1 (default): Enabled -vibration_enabled= - -# Whether to enable or disable accurate vibrations -# 0 (default): Disabled, 1: Enabled -enable_accurate_vibrations= - -# Enables controller motion inputs -# 0: Disabled, 1 (default): Enabled -motion_enabled = - -# Defines the udp device's touch screen coordinate system for cemuhookudp devices -# - "min_x", "min_y", "max_x", "max_y" -touch_device= - -# for mapping buttons to touch inputs. -#touch_from_button_map=1 -#touch_from_button_maps_0_name=default -#touch_from_button_maps_0_count=2 -#touch_from_button_maps_0_bind_0=foo -#touch_from_button_maps_0_bind_1=bar -# etc. - -# List of Cemuhook UDP servers, delimited by ','. -# Default: 127.0.0.1:26760 -# Example: 127.0.0.1:26760,123.4.5.67:26761 -udp_input_servers = - -# Enable controlling an axis via a mouse input. -# 0 (default): Off, 1: On -mouse_panning = - -# Set mouse sensitivity. -# Default: 1.0 -mouse_panning_sensitivity = - -# Emulate an analog control stick from keyboard inputs. -# 0 (default): Disabled, 1: Enabled -emulate_analog_keyboard = - -# Enable mouse inputs to the guest -# 0 (default): Disabled, 1: Enabled -mouse_enabled = - -# Enable keyboard inputs to the guest -# 0 (default): Disabled, 1: Enabled -keyboard_enabled = - -[Core] -# Whether to use multi-core for CPU emulation -# 0: Disabled, 1 (default): Enabled -use_multi_core = - -# Enable unsafe extended guest system memory layout (8GB DRAM) -# 0 (default): Disabled, 1: Enabled -use_unsafe_extended_memory_layout = - -[Cpu] -# Adjusts various optimizations. -# Auto-select mode enables choice unsafe optimizations. -# Accurate enables only safe optimizations. -# Unsafe allows any unsafe optimizations. -# 0 (default): Auto-select, 1: Accurate, 2: Enable unsafe optimizations -cpu_accuracy = - -# Allow disabling safe optimizations. -# 0 (default): Disabled, 1: Enabled -cpu_debug_mode = - -# Enable inline page tables optimization (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_page_tables = - -# Enable block linking CPU optimization (reduce block dispatcher use during predictable jumps) -# 0: Disabled, 1 (default): Enabled -cpuopt_block_linking = - -# Enable return stack buffer CPU optimization (reduce block dispatcher use during predictable returns) -# 0: Disabled, 1 (default): Enabled -cpuopt_return_stack_buffer = - -# Enable fast dispatcher CPU optimization (use a two-tiered dispatcher architecture) -# 0: Disabled, 1 (default): Enabled -cpuopt_fast_dispatcher = - -# Enable context elimination CPU Optimization (reduce host memory use for guest context) -# 0: Disabled, 1 (default): Enabled -cpuopt_context_elimination = - -# Enable constant propagation CPU optimization (basic IR optimization) -# 0: Disabled, 1 (default): Enabled -cpuopt_const_prop = - -# Enable miscellaneous CPU optimizations (basic IR optimization) -# 0: Disabled, 1 (default): Enabled -cpuopt_misc_ir = - -# Enable reduction of memory misalignment checks (reduce memory fallbacks for misaligned access) -# 0: Disabled, 1 (default): Enabled -cpuopt_reduce_misalign_checks = - -# Enable Host MMU Emulation (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_fastmem = - -# Enable Host MMU Emulation for exclusive memory instructions (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_fastmem_exclusives = - -# Enable fallback on failure of fastmem of exclusive memory instructions (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_recompile_exclusives = - -# Enable optimization to ignore invalid memory accesses (faster guest memory access) -# 0: Disabled, 1 (default): Enabled -cpuopt_ignore_memory_aborts = - -# Enable unfuse FMA (improve performance on CPUs without FMA) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_unfuse_fma = - -# Enable faster FRSQRTE and FRECPE -# Only enabled if cpu_accuracy is set to Unsafe. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_reduce_fp_error = - -# Enable faster ASIMD instructions (32 bits only) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_ignore_standard_fpcr = - -# Enable inaccurate NaN handling -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_inaccurate_nan = - -# Disable address space checks (64 bits only) -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_fastmem_check = - -# Enable faster exclusive instructions -# Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. -# 0: Disabled, 1 (default): Enabled -cpuopt_unsafe_ignore_global_monitor = - -[Renderer] -# Which backend API to use. -# 0: OpenGL (unsupported), 1 (default): Vulkan, 2: Null -backend = - -# Whether to enable asynchronous presentation (Vulkan only) -# 0: Off, 1 (default): On -async_presentation = - -# Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied). -# 0 (default): Disabled, 1: Enabled -force_max_clock = - -# Enable graphics API debugging mode. -# 0 (default): Disabled, 1: Enabled -debug = - -# Enable shader feedback. -# 0 (default): Disabled, 1: Enabled -renderer_shader_feedback = - -# Enable Nsight Aftermath crash dumps -# 0 (default): Disabled, 1: Enabled -nsight_aftermath = - -# Disable shader loop safety checks, executing the shader without loop logic changes -# 0 (default): Disabled, 1: Enabled -disable_shader_loop_safety_checks = - -# Which Vulkan physical device to use (defaults to 0) -vulkan_device = - -# 0: 0.5x (360p/540p) [EXPERIMENTAL] -# 1: 0.75x (540p/810p) [EXPERIMENTAL] -# 2 (default): 1x (720p/1080p) -# 3: 2x (1440p/2160p) -# 4: 3x (2160p/3240p) -# 5: 4x (2880p/4320p) -# 6: 5x (3600p/5400p) -# 7: 6x (4320p/6480p) -resolution_setup = - -# Pixel filter to use when up- or down-sampling rendered frames. -# 0: Nearest Neighbor -# 1 (default): Bilinear -# 2: Bicubic -# 3: Gaussian -# 4: ScaleForce -# 5: AMD FidelityFX™️ Super Resolution [Vulkan Only] -scaling_filter = - -# Anti-Aliasing (AA) -# 0 (default): None, 1: FXAA -anti_aliasing = - -# Whether to use fullscreen or borderless window mode -# 0 (Windows default): Borderless window, 1 (All other default): Exclusive fullscreen -fullscreen_mode = - -# Aspect ratio -# 0: Default (16:9), 1: Force 4:3, 2: Force 21:9, 3: Force 16:10, 4: Stretch to Window -aspect_ratio = - -# Anisotropic filtering -# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x -max_anisotropy = - -# Whether to enable VSync or not. -# OpenGL: Values other than 0 enable VSync -# Vulkan: FIFO is selected if the requested mode is not supported by the driver. -# FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. -# FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. -# Mailbox can have lower latency than FIFO and does not tear but may drop frames. -# Immediate (no synchronization) just presents whatever is available and can exhibit tearing. -# 0: Immediate (Off), 1 (Default): Mailbox (On), 2: FIFO, 3: FIFO Relaxed -use_vsync = - -# Selects the OpenGL shader backend. NV_gpu_program5 is required for GLASM. If NV_gpu_program5 is -# not available and GLASM is selected, GLSL will be used. -# 0: GLSL, 1 (default): GLASM, 2: SPIR-V -shader_backend = - -# Whether to allow asynchronous shader building. -# 0 (default): Off, 1: On -use_asynchronous_shaders = - -# Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory. -# 0 (default): Off, 1: On -use_reactive_flushing = - -# NVDEC emulation. -# 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding -nvdec_emulation = - -# Accelerate ASTC texture decoding. -# 0 (default): Off, 1: On -accelerate_astc = - -# Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value -# 0: Off, 1: On (default) -use_speed_limit = - -# Limits the speed of the game to run no faster than this value as a percentage of target speed -# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) -speed_limit = - -# Whether to use disk based shader cache -# 0: Off, 1 (default): On -use_disk_shader_cache = - -# Which gpu accuracy level to use -# 0 (default): Normal, 1: High, 2: Extreme (Very slow) -gpu_accuracy = - -# Whether to use asynchronous GPU emulation -# 0 : Off (slow), 1 (default): On (fast) -use_asynchronous_gpu_emulation = - -# Inform the guest that GPU operations completed more quickly than they did. -# 0: Off, 1 (default): On -use_fast_gpu_time = - -# Force unmodified buffers to be flushed, which can cost performance. -# 0: Off (default), 1: On -use_pessimistic_flushes = - -# Whether to use garbage collection or not for GPU caches. -# 0 (default): Off, 1: On -use_caches_gc = - -# The clear color for the renderer. What shows up on the sides of the bottom screen. -# Must be in range of 0-255. Defaults to 0 for all. -bg_red = -bg_blue = -bg_green = - -[Audio] -# Which audio output engine to use. -# auto (default): Auto-select -# cubeb: Cubeb audio engine (if available) -# sdl2: SDL2 audio engine (if available) -# null: No audio output -output_engine = - -# Which audio device to use. -# auto (default): Auto-select -output_device = - -# Output volume. -# 100 (default): 100%, 0; mute -volume = - -[Data Storage] -# Whether to create a virtual SD card. -# 1: Yes, 0 (default): No -use_virtual_sd = - -# Whether or not to enable gamecard emulation -# 1: Yes, 0 (default): No -gamecard_inserted = - -# Whether or not the gamecard should be emulated as the current game -# If 'gamecard_inserted' is 0 this setting is irrelevant -# 1: Yes, 0 (default): No -gamecard_current_game = - -# Path to an XCI file to use as the gamecard -# If 'gamecard_inserted' is 0 this setting is irrelevant -# If 'gamecard_current_game' is 1 this setting is irrelevant -gamecard_path = - -[System] -# Whether the system is docked -# 1 (default): Yes, 0: No -use_docked_mode = - -# Sets the seed for the RNG generator built into the switch -# rng_seed will be ignored and randomly generated if rng_seed_enabled is false -rng_seed_enabled = -rng_seed = - -# Sets the current time (in seconds since 12:00 AM Jan 1, 1970) that will be used by the time service -# This will auto-increment, with the time set being the time the game is started -# This override will only occur if custom_rtc_enabled is true, otherwise the current time is used -custom_rtc_enabled = -custom_rtc = - -# Sets the systems language index -# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish, 6: Chinese, -# 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Taiwanese, 12: British English, 13: Canadian French, -# 14: Latin American Spanish, 15: Simplified Chinese, 16: Traditional Chinese, 17: Brazilian Portuguese -language_index = - -# The system region that yuzu will use during emulation -# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan -region_index = - -# The system time zone that yuzu will use during emulation -# 0: Auto-select (default), 1: Default (system archive value), Others: Index for specified time zone -time_zone_index = - -# Sets the sound output mode. -# 0: Mono, 1 (default): Stereo, 2: Surround -sound_index = - -[Miscellaneous] -# A filter which removes logs below a certain logging level. -# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical -log_filter = *:Trace - -# Use developer keys -# 0 (default): Disabled, 1: Enabled -use_dev_keys = - -[Debugging] -# Record frame time data, can be found in the log directory. Boolean value -record_frame_times = -# Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them -dump_exefs=false -# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them -dump_nso=false -# Determines whether or not yuzu will save the filesystem access log. -enable_fs_access_log=false -# Enables verbose reporting services -reporting_services = -# Determines whether or not yuzu will report to the game that the emulated console is in Kiosk Mode -# false: Retail/Normal Mode (default), true: Kiosk Mode -quest_flag = -# Determines whether debug asserts should be enabled, which will throw an exception on asserts. -# false: Disabled (default), true: Enabled -use_debug_asserts = -# Determines whether unimplemented HLE service calls should be automatically stubbed. -# false: Disabled (default), true: Enabled -use_auto_stub = -# Enables/Disables the macro JIT compiler -disable_macro_jit=false -# Determines whether to enable the GDB stub and wait for the debugger to attach before running. -# false: Disabled (default), true: Enabled -use_gdbstub=false -# The port to use for the GDB server, if it is enabled. -gdbstub_port=6543 - -[WebService] -# Whether or not to enable telemetry -# 0: No, 1 (default): Yes -enable_telemetry = -# URL for Web API -web_api_url = https://api.yuzu-emu.org -# Username and token for yuzu Web Service -# See https://profile.yuzu-emu.org/ for more info -yuzu_username = -yuzu_token = - -[Network] -# Name of the network interface device to use with yuzu LAN play. -# e.g. On *nix: 'enp7s0', 'wlp6s0u1u3u3', 'lo' -# e.g. On Windows: 'Ethernet', 'Wi-Fi' -network_interface = - -[AddOns] -# Used to disable add-ons -# List of title IDs of games that will have add-ons disabled (separated by '|'): -title_ids = -# For each title ID, have a key/value pair called `disabled_` equal to the names of the add-ons to disable (sep. by '|') -# e.x. disabled_0100000000010000 = Update|DLC <- disables Updates and DLC on Super Mario Odyssey -)"; -} // namespace DefaultINI diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp deleted file mode 100644 index f30100b..0000000 --- a/src/android/app/src/main/jni/id_cache.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "common/assert.h" -#include "common/fs/fs_android.h" -#include "jni/applets/software_keyboard.h" -#include "jni/id_cache.h" -#include "video_core/rasterizer_interface.h" - -static JavaVM* s_java_vm; -static jclass s_native_library_class; -static jclass s_disk_cache_progress_class; -static jclass s_load_callback_stage_class; -static jclass s_game_dir_class; -static jmethodID s_game_dir_constructor; -static jmethodID s_exit_emulation_activity; -static jmethodID s_disk_cache_load_progress; -static jmethodID s_on_emulation_started; -static jmethodID s_on_emulation_stopped; -static jmethodID s_on_program_changed; - -static jclass s_game_class; -static jmethodID s_game_constructor; -static jfieldID s_game_title_field; -static jfieldID s_game_path_field; -static jfieldID s_game_program_id_field; -static jfieldID s_game_developer_field; -static jfieldID s_game_version_field; -static jfieldID s_game_is_homebrew_field; - -static jclass s_string_class; -static jclass s_pair_class; -static jmethodID s_pair_constructor; -static jfieldID s_pair_first_field; -static jfieldID s_pair_second_field; - -static jclass s_overlay_control_data_class; -static jmethodID s_overlay_control_data_constructor; -static jfieldID s_overlay_control_data_id_field; -static jfieldID s_overlay_control_data_enabled_field; -static jfieldID s_overlay_control_data_landscape_position_field; -static jfieldID s_overlay_control_data_portrait_position_field; -static jfieldID s_overlay_control_data_foldable_position_field; - -static jclass s_patch_class; -static jmethodID s_patch_constructor; -static jfieldID s_patch_enabled_field; -static jfieldID s_patch_name_field; -static jfieldID s_patch_version_field; -static jfieldID s_patch_type_field; -static jfieldID s_patch_program_id_field; -static jfieldID s_patch_title_id_field; - -static jclass s_double_class; -static jmethodID s_double_constructor; -static jfieldID s_double_value_field; - -static jclass s_integer_class; -static jmethodID s_integer_constructor; -static jfieldID s_integer_value_field; - -static jclass s_boolean_class; -static jmethodID s_boolean_constructor; -static jfieldID s_boolean_value_field; - -static constexpr jint JNI_VERSION = JNI_VERSION_1_6; - -namespace IDCache { - -JNIEnv* GetEnvForThread() { - thread_local static struct OwnedEnv { - OwnedEnv() { - status = s_java_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); - if (status == JNI_EDETACHED) - s_java_vm->AttachCurrentThread(&env, nullptr); - } - - ~OwnedEnv() { - if (status == JNI_EDETACHED) - s_java_vm->DetachCurrentThread(); - } - - int status; - JNIEnv* env = nullptr; - } owned; - return owned.env; -} - -jclass GetNativeLibraryClass() { - return s_native_library_class; -} - -jclass GetDiskCacheProgressClass() { - return s_disk_cache_progress_class; -} - -jclass GetDiskCacheLoadCallbackStageClass() { - return s_load_callback_stage_class; -} - -jclass GetGameDirClass() { - return s_game_dir_class; -} - -jmethodID GetGameDirConstructor() { - return s_game_dir_constructor; -} - -jmethodID GetExitEmulationActivity() { - return s_exit_emulation_activity; -} - -jmethodID GetDiskCacheLoadProgress() { - return s_disk_cache_load_progress; -} - -jmethodID GetOnEmulationStarted() { - return s_on_emulation_started; -} - -jmethodID GetOnEmulationStopped() { - return s_on_emulation_stopped; -} - -jmethodID GetOnProgramChanged() { - return s_on_program_changed; -} - -jclass GetGameClass() { - return s_game_class; -} - -jmethodID GetGameConstructor() { - return s_game_constructor; -} - -jfieldID GetGameTitleField() { - return s_game_title_field; -} - -jfieldID GetGamePathField() { - return s_game_path_field; -} - -jfieldID GetGameProgramIdField() { - return s_game_program_id_field; -} - -jfieldID GetGameDeveloperField() { - return s_game_developer_field; -} - -jfieldID GetGameVersionField() { - return s_game_version_field; -} - -jfieldID GetGameIsHomebrewField() { - return s_game_is_homebrew_field; -} - -jclass GetStringClass() { - return s_string_class; -} - -jclass GetPairClass() { - return s_pair_class; -} - -jmethodID GetPairConstructor() { - return s_pair_constructor; -} - -jfieldID GetPairFirstField() { - return s_pair_first_field; -} - -jfieldID GetPairSecondField() { - return s_pair_second_field; -} - -jclass GetOverlayControlDataClass() { - return s_overlay_control_data_class; -} - -jmethodID GetOverlayControlDataConstructor() { - return s_overlay_control_data_constructor; -} - -jfieldID GetOverlayControlDataIdField() { - return s_overlay_control_data_id_field; -} - -jfieldID GetOverlayControlDataEnabledField() { - return s_overlay_control_data_enabled_field; -} - -jfieldID GetOverlayControlDataLandscapePositionField() { - return s_overlay_control_data_landscape_position_field; -} - -jfieldID GetOverlayControlDataPortraitPositionField() { - return s_overlay_control_data_portrait_position_field; -} - -jfieldID GetOverlayControlDataFoldablePositionField() { - return s_overlay_control_data_foldable_position_field; -} - -jclass GetPatchClass() { - return s_patch_class; -} - -jmethodID GetPatchConstructor() { - return s_patch_constructor; -} - -jfieldID GetPatchEnabledField() { - return s_patch_enabled_field; -} - -jfieldID GetPatchNameField() { - return s_patch_name_field; -} - -jfieldID GetPatchVersionField() { - return s_patch_version_field; -} - -jfieldID GetPatchTypeField() { - return s_patch_type_field; -} - -jfieldID GetPatchProgramIdField() { - return s_patch_program_id_field; -} - -jfieldID GetPatchTitleIdField() { - return s_patch_title_id_field; -} - -jclass GetDoubleClass() { - return s_double_class; -} - -jmethodID GetDoubleConstructor() { - return s_double_constructor; -} - -jfieldID GetDoubleValueField() { - return s_double_value_field; -} - -jclass GetIntegerClass() { - return s_integer_class; -} - -jmethodID GetIntegerConstructor() { - return s_integer_constructor; -} - -jfieldID GetIntegerValueField() { - return s_integer_value_field; -} - -jclass GetBooleanClass() { - return s_boolean_class; -} - -jmethodID GetBooleanConstructor() { - return s_boolean_constructor; -} - -jfieldID GetBooleanValueField() { - return s_boolean_value_field; -} - -} // namespace IDCache - -#ifdef __cplusplus -extern "C" { -#endif - -jint JNI_OnLoad(JavaVM* vm, void* reserved) { - s_java_vm = vm; - - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) - return JNI_ERR; - - // Initialize Java classes - const jclass native_library_class = env->FindClass("org/yuzu/yuzu_emu/NativeLibrary"); - s_native_library_class = reinterpret_cast(env->NewGlobalRef(native_library_class)); - s_disk_cache_progress_class = reinterpret_cast(env->NewGlobalRef( - env->FindClass("org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress"))); - s_load_callback_stage_class = reinterpret_cast(env->NewGlobalRef(env->FindClass( - "org/yuzu/yuzu_emu/disk_shader_cache/DiskShaderCacheProgress$LoadCallbackStage"))); - - const jclass game_dir_class = env->FindClass("org/yuzu/yuzu_emu/model/GameDir"); - s_game_dir_class = reinterpret_cast(env->NewGlobalRef(game_dir_class)); - s_game_dir_constructor = env->GetMethodID(game_dir_class, "", "(Ljava/lang/String;Z)V"); - env->DeleteLocalRef(game_dir_class); - - // Initialize methods - s_exit_emulation_activity = - env->GetStaticMethodID(s_native_library_class, "exitEmulationActivity", "(I)V"); - s_disk_cache_load_progress = - env->GetStaticMethodID(s_disk_cache_progress_class, "loadProgress", "(III)V"); - s_on_emulation_started = - env->GetStaticMethodID(s_native_library_class, "onEmulationStarted", "()V"); - s_on_emulation_stopped = - env->GetStaticMethodID(s_native_library_class, "onEmulationStopped", "(I)V"); - s_on_program_changed = - env->GetStaticMethodID(s_native_library_class, "onProgramChanged", "(I)V"); - - const jclass game_class = env->FindClass("org/yuzu/yuzu_emu/model/Game"); - s_game_class = reinterpret_cast(env->NewGlobalRef(game_class)); - s_game_constructor = env->GetMethodID(game_class, "", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" - "String;Ljava/lang/String;Ljava/lang/String;Z)V"); - s_game_title_field = env->GetFieldID(game_class, "title", "Ljava/lang/String;"); - s_game_path_field = env->GetFieldID(game_class, "path", "Ljava/lang/String;"); - s_game_program_id_field = env->GetFieldID(game_class, "programId", "Ljava/lang/String;"); - s_game_developer_field = env->GetFieldID(game_class, "developer", "Ljava/lang/String;"); - s_game_version_field = env->GetFieldID(game_class, "version", "Ljava/lang/String;"); - s_game_is_homebrew_field = env->GetFieldID(game_class, "isHomebrew", "Z"); - env->DeleteLocalRef(game_class); - - const jclass string_class = env->FindClass("java/lang/String"); - s_string_class = reinterpret_cast(env->NewGlobalRef(string_class)); - env->DeleteLocalRef(string_class); - - const jclass pair_class = env->FindClass("kotlin/Pair"); - s_pair_class = reinterpret_cast(env->NewGlobalRef(pair_class)); - s_pair_constructor = - env->GetMethodID(pair_class, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); - s_pair_first_field = env->GetFieldID(pair_class, "first", "Ljava/lang/Object;"); - s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); - env->DeleteLocalRef(pair_class); - - const jclass overlay_control_data_class = - env->FindClass("org/yuzu/yuzu_emu/overlay/model/OverlayControlData"); - s_overlay_control_data_class = - reinterpret_cast(env->NewGlobalRef(overlay_control_data_class)); - s_overlay_control_data_constructor = - env->GetMethodID(overlay_control_data_class, "", - "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;)V"); - s_overlay_control_data_id_field = - env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); - s_overlay_control_data_enabled_field = - env->GetFieldID(overlay_control_data_class, "enabled", "Z"); - s_overlay_control_data_landscape_position_field = - env->GetFieldID(overlay_control_data_class, "landscapePosition", "Lkotlin/Pair;"); - s_overlay_control_data_portrait_position_field = - env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); - s_overlay_control_data_foldable_position_field = - env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); - env->DeleteLocalRef(overlay_control_data_class); - - const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch"); - s_patch_class = reinterpret_cast(env->NewGlobalRef(patch_class)); - s_patch_constructor = env->GetMethodID( - patch_class, "", - "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V"); - s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z"); - s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;"); - s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;"); - s_patch_type_field = env->GetFieldID(patch_class, "type", "I"); - s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;"); - s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;"); - env->DeleteLocalRef(patch_class); - - const jclass double_class = env->FindClass("java/lang/Double"); - s_double_class = reinterpret_cast(env->NewGlobalRef(double_class)); - s_double_constructor = env->GetMethodID(double_class, "", "(D)V"); - s_double_value_field = env->GetFieldID(double_class, "value", "D"); - env->DeleteLocalRef(double_class); - - const jclass int_class = env->FindClass("java/lang/Integer"); - s_integer_class = reinterpret_cast(env->NewGlobalRef(int_class)); - s_integer_constructor = env->GetMethodID(int_class, "", "(I)V"); - s_integer_value_field = env->GetFieldID(int_class, "value", "I"); - env->DeleteLocalRef(int_class); - - const jclass boolean_class = env->FindClass("java/lang/Boolean"); - s_boolean_class = reinterpret_cast(env->NewGlobalRef(boolean_class)); - s_boolean_constructor = env->GetMethodID(boolean_class, "", "(Z)V"); - s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z"); - env->DeleteLocalRef(boolean_class); - - // Initialize Android Storage - Common::FS::Android::RegisterCallbacks(env, s_native_library_class); - - // Initialize applets - SoftwareKeyboard::InitJNI(env); - - return JNI_VERSION; -} - -void JNI_OnUnload(JavaVM* vm, void* reserved) { - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION) != JNI_OK) { - return; - } - - // UnInitialize Android Storage - Common::FS::Android::UnRegisterCallbacks(); - env->DeleteGlobalRef(s_native_library_class); - env->DeleteGlobalRef(s_disk_cache_progress_class); - env->DeleteGlobalRef(s_load_callback_stage_class); - env->DeleteGlobalRef(s_game_dir_class); - env->DeleteGlobalRef(s_game_class); - env->DeleteGlobalRef(s_string_class); - env->DeleteGlobalRef(s_pair_class); - env->DeleteGlobalRef(s_overlay_control_data_class); - env->DeleteGlobalRef(s_patch_class); - env->DeleteGlobalRef(s_double_class); - env->DeleteGlobalRef(s_integer_class); - env->DeleteGlobalRef(s_boolean_class); - - // UnInitialize applets - SoftwareKeyboard::CleanupJNI(env); -} - -#ifdef __cplusplus -} -#endif diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h deleted file mode 100644 index 00e48af..0000000 --- a/src/android/app/src/main/jni/id_cache.h +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once - -#include - -#include "video_core/rasterizer_interface.h" - -namespace IDCache { - -JNIEnv* GetEnvForThread(); -jclass GetNativeLibraryClass(); -jclass GetDiskCacheProgressClass(); -jclass GetDiskCacheLoadCallbackStageClass(); -jclass GetGameDirClass(); -jmethodID GetGameDirConstructor(); -jmethodID GetExitEmulationActivity(); -jmethodID GetDiskCacheLoadProgress(); -jmethodID GetOnEmulationStarted(); -jmethodID GetOnEmulationStopped(); -jmethodID GetOnProgramChanged(); - -jclass GetGameClass(); -jmethodID GetGameConstructor(); -jfieldID GetGameTitleField(); -jfieldID GetGamePathField(); -jfieldID GetGameProgramIdField(); -jfieldID GetGameDeveloperField(); -jfieldID GetGameVersionField(); -jfieldID GetGameIsHomebrewField(); - -jclass GetStringClass(); -jclass GetPairClass(); -jmethodID GetPairConstructor(); -jfieldID GetPairFirstField(); -jfieldID GetPairSecondField(); - -jclass GetOverlayControlDataClass(); -jmethodID GetOverlayControlDataConstructor(); -jfieldID GetOverlayControlDataIdField(); -jfieldID GetOverlayControlDataEnabledField(); -jfieldID GetOverlayControlDataLandscapePositionField(); -jfieldID GetOverlayControlDataPortraitPositionField(); -jfieldID GetOverlayControlDataFoldablePositionField(); - -jclass GetPatchClass(); -jmethodID GetPatchConstructor(); -jfieldID GetPatchEnabledField(); -jfieldID GetPatchNameField(); -jfieldID GetPatchVersionField(); -jfieldID GetPatchTypeField(); -jfieldID GetPatchProgramIdField(); -jfieldID GetPatchTitleIdField(); - -jclass GetDoubleClass(); -jmethodID GetDoubleConstructor(); -jfieldID GetDoubleValueField(); - -jclass GetIntegerClass(); -jmethodID GetIntegerConstructor(); -jfieldID GetIntegerValueField(); - -jclass GetBooleanClass(); -jmethodID GetBooleanConstructor(); -jfieldID GetBooleanValueField(); - -} // namespace IDCache diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 5d484a8..cfb8ebb 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -491,7 +491,7 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* en return false; } -void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(JNIEnv* env, jclass clazz, +void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(JNIEnv* env, jobject clazz, jstring hook_lib_dir, jstring custom_driver_dir, jstring custom_driver_name, @@ -555,32 +555,32 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo( return j_driver_info; } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jclass clazz) { +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadKeys(JNIEnv* env, jobject clazz) { Core::Crypto::KeyManager::Instance().ReloadKeys(); return static_cast(Core::Crypto::KeyManager::Instance().AreKeysLoaded()); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_unpauseEmulation(JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_unpauseEmulation(JNIEnv* env, jobject clazz) { EmulationSession::GetInstance().UnPauseEmulation(); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_pauseEmulation(JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_pauseEmulation(JNIEnv* env, jobject clazz) { EmulationSession::GetInstance().PauseEmulation(); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_stopEmulation(JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_stopEmulation(JNIEnv* env, jobject clazz) { EmulationSession::GetInstance().HaltEmulation(); } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning(JNIEnv* env, jclass clazz) { +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning(JNIEnv* env, jobject clazz) { return static_cast(EmulationSession::GetInstance().IsRunning()); } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isPaused(JNIEnv* env, jclass clazz) { +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isPaused(JNIEnv* env, jobject clazz) { return static_cast(EmulationSession::GetInstance().IsPaused()); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz, +void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jobject clazz, jboolean reload) { // Initialize the emulated system. if (!reload) { @@ -589,7 +589,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass EmulationSession::GetInstance().InitializeSystem(reload); } -jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jclass clazz) { +jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jobject clazz) { jdoubleArray j_stats = env->NewDoubleArray(4); if (EmulationSession::GetInstance().IsRunning()) { @@ -605,7 +605,7 @@ jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jcl return j_stats; } -jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuBackend(JNIEnv* env, jclass clazz) { +jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuBackend(JNIEnv* env, jobject clazz) { if (Settings::IsNceEnabled()) { return Common::Android::ToJString(env, "NCE"); } @@ -641,18 +641,18 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstrin } } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_logDeviceInfo(JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_logDeviceInfo(JNIEnv* env, jobject clazz) { LOG_INFO(Frontend, "yuzu Version: {}-{}", Common::g_scm_branch, Common::g_scm_desc); LOG_INFO(Frontend, "Host OS: Android API level {}", android_get_device_api_level()); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardText(JNIEnv* env, jclass clazz, +void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardText(JNIEnv* env, jobject clazz, jstring j_text) { const std::u16string input = Common::UTF8ToUTF16(Common::Android::GetJString(env, j_text)); EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardText(input); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env, jclass clazz, +void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardInput(JNIEnv* env, jobject clazz, jint j_key_code) { EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardInput(j_key_code); } @@ -677,7 +677,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv* } } -jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, jclass clazz, +jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, jobject clazz, jlong jid) { auto bis_system = EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents(); @@ -694,18 +694,18 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j return Common::Android::ToJString(env, applet_nca->GetFullPath()); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, +void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jobject clazz, jint jappletId) { EmulationSession::GetInstance().SetAppletId(jappletId); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz, +void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jobject clazz, jint jcabinetMode) { EmulationSession::GetInstance().System().GetFrontendAppletHolder().SetCabinetMode( static_cast(jcabinetMode)); } -jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, jclass clazz) { +jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, jobject clazz) { auto bis_system = EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents(); if (!bis_system) { diff --git a/src/android/app/src/main/jni/uisettings.cpp b/src/android/app/src/main/jni/uisettings.cpp deleted file mode 100644 index f2f0bad..0000000 --- a/src/android/app/src/main/jni/uisettings.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "uisettings.h" - -namespace AndroidSettings { - -Values values; - -} // namespace AndroidSettings diff --git a/src/android/app/src/main/jni/uisettings.h b/src/android/app/src/main/jni/uisettings.h deleted file mode 100644 index 494654a..0000000 --- a/src/android/app/src/main/jni/uisettings.h +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/common_types.h" -#include "common/settings_setting.h" - -namespace AndroidSettings { - -struct Values { - Settings::Linkage linkage; - - // Android - Settings::Setting picture_in_picture{linkage, true, "picture_in_picture", - Settings::Category::Android}; - Settings::Setting screen_layout{linkage, - 5, - "screen_layout", - Settings::Category::Android, - Settings::Specialization::Default, - true, - true}; -}; - -extern Values values; - -} // namespace AndroidSettings diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml deleted file mode 100644 index 9f49c13..0000000 --- a/src/android/app/src/main/res/anim-ldrtl/anim_pop_settings_fragment_out.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml deleted file mode 100644 index 82fd719..0000000 --- a/src/android/app/src/main/res/anim-ldrtl/anim_settings_fragment_in.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml deleted file mode 100644 index 5892128..0000000 --- a/src/android/app/src/main/res/anim/anim_pop_settings_fragment_out.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml deleted file mode 100644 index 98e0cf8..0000000 --- a/src/android/app/src/main/res/anim/anim_settings_fragment_in.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - diff --git a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml b/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml deleted file mode 100644 index 77a40a4..0000000 --- a/src/android/app/src/main/res/anim/anim_settings_fragment_out.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml b/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml deleted file mode 100644 index 4612aee..0000000 --- a/src/android/app/src/main/res/animator/menu_slide_in_from_start.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml b/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml deleted file mode 100644 index c004789..0000000 --- a/src/android/app/src/main/res/animator/menu_slide_out_to_start.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/android/app/src/main/res/layout/card_applet_option.xml b/src/android/app/src/main/res/layout/card_applet_option.xml deleted file mode 100644 index 19fbec9..0000000 --- a/src/android/app/src/main/res/layout/card_applet_option.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/android/app/src/main/res/xml/locales_config.xml b/src/android/app/src/main/res/xml/locales_config.xml deleted file mode 100644 index 51b88d9..0000000 --- a/src/android/app/src/main/res/xml/locales_config.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/src/android/build.gradle.kts b/src/android/build.gradle.kts index b77906e..6b47205 100644 --- a/src/android/build.gradle.kts +++ b/src/android/build.gradle.kts @@ -3,8 +3,8 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.1.2" apply false - id("com.android.library") version "8.1.2" apply false + id("com.android.application") version "8.3.0" apply false + id("com.android.library") version "8.3.0" apply false id("org.jetbrains.kotlin.android") version "1.9.20" apply false } diff --git a/src/android/gradle/wrapper/gradle-wrapper.properties b/src/android/gradle/wrapper/gradle-wrapper.properties index 578c71b..42b415f 100644 --- a/src/android/gradle/wrapper/gradle-wrapper.properties +++ b/src/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip