diff options
Diffstat (limited to 'src/android/app/src/main/java/org')
9 files changed, 87 insertions, 66 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 115f72710..e2c5b6acd 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu import android.app.Dialog import android.content.DialogInterface +import android.net.Uri import android.os.Bundle import android.text.Html import android.text.method.LinkMovementMethod @@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment import com.google.android.material.dialog.MaterialAlertDialogBuilder import java.lang.ref.WeakReference import org.yuzu.yuzu_emu.activities.EmulationActivity -import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath +import org.yuzu.yuzu_emu.utils.DocumentsTree import org.yuzu.yuzu_emu.utils.FileUtil import org.yuzu.yuzu_emu.utils.Log import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable @@ -68,7 +69,7 @@ object NativeLibrary { @Keep @JvmStatic fun openContentUri(path: String?, openmode: String?): Int { - return if (isNativePath(path!!)) { + return if (DocumentsTree.isNativePath(path!!)) { YuzuApplication.documentsTree!!.openContentUri(path, openmode) } else { FileUtil.openContentUri(path, openmode) @@ -78,7 +79,7 @@ object NativeLibrary { @Keep @JvmStatic fun getSize(path: String?): Long { - return if (isNativePath(path!!)) { + return if (DocumentsTree.isNativePath(path!!)) { YuzuApplication.documentsTree!!.getFileSize(path) } else { FileUtil.getFileSize(path) @@ -88,23 +89,41 @@ object NativeLibrary { @Keep @JvmStatic fun exists(path: String?): Boolean { - return if (isNativePath(path!!)) { + return if (DocumentsTree.isNativePath(path!!)) { YuzuApplication.documentsTree!!.exists(path) } else { - FileUtil.exists(path) + FileUtil.exists(path, suppressLog = true) } } @Keep @JvmStatic fun isDirectory(path: String?): Boolean { - return if (isNativePath(path!!)) { + return if (DocumentsTree.isNativePath(path!!)) { YuzuApplication.documentsTree!!.isDirectory(path) } else { FileUtil.isDirectory(path) } } + @Keep + @JvmStatic + fun getParentDirectory(path: String): String = + if (DocumentsTree.isNativePath(path)) { + YuzuApplication.documentsTree!!.getParentDirectory(path) + } else { + path + } + + @Keep + @JvmStatic + fun getFilename(path: String): String = + if (DocumentsTree.isNativePath(path)) { + YuzuApplication.documentsTree!!.getFilename(path) + } else { + FileUtil.getFilename(Uri.parse(path)) + } + /** * Returns true if pro controller isn't available and handheld is */ @@ -215,32 +234,6 @@ object NativeLibrary { external fun initGameIni(gameID: String?) - /** - * Gets the embedded icon within the given ROM. - * - * @param filename the file path to the ROM. - * @return a byte array containing the JPEG data for the icon. - */ - external fun getIcon(filename: String): ByteArray - - /** - * Gets the embedded title of the given ISO/ROM. - * - * @param filename The file path to the ISO/ROM. - * @return the embedded title of the ISO/ROM. - */ - external fun getTitle(filename: String): String - - external fun getDescription(filename: String): String - - external fun getGameId(filename: String): String - - external fun getRegions(filename: String): String - - external fun getCompany(filename: String): String - - external fun isHomebrew(filename: String): Boolean - external fun setAppDirectory(directory: String) /** @@ -294,11 +287,6 @@ object NativeLibrary { external fun stopEmulation() /** - * Resets the in-memory ROM metadata cache. - */ - external fun resetRomMetadata() - - /** * Returns true if emulation is running (or is paused). */ external fun isRunning(): Boolean diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index f9f88a1d2..0c82cdba8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt @@ -147,7 +147,7 @@ class GameAdapter(private val activity: AppCompatActivity) : private class DiffCallback : DiffUtil.ItemCallback<Game>() { override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean { - return oldItem.gameId == newItem.gameId + return oldItem.programId == newItem.programId } override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt index 6527c64ab..b43978fce 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt @@ -12,15 +12,14 @@ import kotlinx.serialization.Serializable @Serializable class Game( val title: String, - val description: String, - val regions: String, val path: String, - val gameId: String, - val company: String, + val programId: String, + val developer: String, + val version: String, val isHomebrew: Boolean ) : Parcelable { - val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime" - val keyLastPlayedTime get() = "${gameId}_LastPlayed" + val keyAddedToLibraryTime get() = "${programId}_AddedToLibraryTime" + val keyLastPlayedTime get() = "${programId}_LastPlayed" override fun equals(other: Any?): Boolean { if (other !is Game) { @@ -32,11 +31,9 @@ class Game( override fun hashCode(): Int { var result = title.hashCode() - result = 31 * result + description.hashCode() - result = 31 * result + regions.hashCode() result = 31 * result + path.hashCode() - result = 31 * result + gameId.hashCode() - result = 31 * result + company.hashCode() + result = 31 * result + programId.hashCode() + result = 31 * result + developer.hashCode() result = 31 * result + isHomebrew.hashCode() return result } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt index 004b25b04..8512ed17c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt @@ -14,15 +14,13 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.MissingFieldException import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.utils.GameHelper +import org.yuzu.yuzu_emu.utils.GameMetadata -@OptIn(ExperimentalSerializationApi::class) class GamesViewModel : ViewModel() { val games: StateFlow<List<Game>> get() = _games private val _games = MutableStateFlow(emptyList<Game>()) @@ -58,7 +56,8 @@ class GamesViewModel : ViewModel() { val game: Game try { game = Json.decodeFromString(it) - } catch (e: MissingFieldException) { + } catch (e: Exception) { + // We don't care about any errors related to parsing the game cache return@forEach } @@ -113,7 +112,7 @@ class GamesViewModel : ViewModel() { viewModelScope.launch { withContext(Dispatchers.IO) { - NativeLibrary.resetRomMetadata() + GameMetadata.resetMetadata() setGames(GameHelper.getGames()) _isReloading.value = false diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt index eafcf9e42..738275297 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt @@ -42,6 +42,23 @@ class DocumentsTree { return node != null && node.isDirectory } + fun getParentDirectory(filepath: String): String { + val node = resolvePath(filepath)!! + val parentNode = node.parent + if (parentNode != null && parentNode.isDirectory) { + return parentNode.uri!!.toString() + } + return node.uri!!.toString() + } + + fun getFilename(filepath: String): String { + val node = resolvePath(filepath) + if (node != null) { + return node.name!! + } + return filepath + } + private fun resolvePath(filepath: String): DocumentsNode? { val tokens = StringTokenizer(filepath, File.separator, false) var iterator = root diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt index 5ee74a52c..8c3268e9c 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt @@ -144,7 +144,7 @@ object FileUtil { * @param path Native content uri path * @return bool */ - fun exists(path: String?): Boolean { + fun exists(path: String?, suppressLog: Boolean = false): Boolean { var c: Cursor? = null try { val mUri = Uri.parse(path) @@ -152,7 +152,9 @@ object FileUtil { c = context.contentResolver.query(mUri, columns, null, null, null) return c!!.count > 0 } catch (e: Exception) { - Log.info("[FileUtil] Cannot find file from given path, error: " + e.message) + if (!suppressLog) { + Log.info("[FileUtil] Cannot find file from given path, error: " + e.message) + } } finally { closeQuietly(c) } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt index 9001ca9ab..e6aca6b44 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt @@ -71,27 +71,26 @@ object GameHelper { fun getGame(uri: Uri, addedToLibrary: Boolean): Game { val filePath = uri.toString() - var name = NativeLibrary.getTitle(filePath) + var name = GameMetadata.getTitle(filePath) // If the game's title field is empty, use the filename. if (name.isEmpty()) { name = FileUtil.getFilename(uri) } - var gameId = NativeLibrary.getGameId(filePath) + var programId = GameMetadata.getProgramId(filePath) // If the game's ID field is empty, use the filename without extension. - if (gameId.isEmpty()) { - gameId = name.substring(0, name.lastIndexOf(".")) + if (programId.isEmpty()) { + programId = name.substring(0, name.lastIndexOf(".")) } val newGame = Game( name, - NativeLibrary.getDescription(filePath).replace("\n", " "), - NativeLibrary.getRegions(filePath), filePath, - gameId, - NativeLibrary.getCompany(filePath), - NativeLibrary.isHomebrew(filePath) + programId, + GameMetadata.getDeveloper(filePath), + GameMetadata.getVersion(filePath), + GameMetadata.getIsHomebrew(filePath) ) if (addedToLibrary) { diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt index 9fe99fab1..654d62f52 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt @@ -18,7 +18,6 @@ import coil.key.Keyer import coil.memory.MemoryCache import coil.request.ImageRequest import coil.request.Options -import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.model.Game @@ -36,7 +35,7 @@ class GameIconFetcher( } private fun decodeGameIcon(uri: String): Bitmap? { - val data = NativeLibrary.getIcon(uri) + val data = GameMetadata.getIcon(uri) return BitmapFactory.decodeByteArray( data, 0, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt new file mode 100644 index 000000000..0f3542ac6 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.yuzu.yuzu_emu.utils + +object GameMetadata { + external fun getTitle(path: String): String + + external fun getProgramId(path: String): String + + external fun getDeveloper(path: String): String + + external fun getVersion(path: String): String + + external fun getIcon(path: String): ByteArray + + external fun getIsHomebrew(path: String): Boolean + + external fun resetMetadata() +} |