From ac222ceba2b39a4efa4f2f217de93206ee8aa3f6 Mon Sep 17 00:00:00 2001 From: t895 Date: Sun, 10 Dec 2023 20:57:51 -0500 Subject: android: Add game dir entries to FilesystemProvider Allows us to correctly parse update metadata --- .../main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | 12 +++++++ .../java/org/yuzu/yuzu_emu/utils/GameHelper.kt | 22 ++++++++++-- .../java/org/yuzu/yuzu_emu/utils/GameMetadata.kt | 4 ++- src/android/app/src/main/jni/game_metadata.cpp | 39 +++++++++++++++++++--- src/android/app/src/main/jni/native.cpp | 11 +++++- src/android/app/src/main/jni/native.h | 1 + 6 files changed, 80 insertions(+), 9 deletions(-) (limited to 'src/android') 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 95b98798d..010c44951 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 @@ -547,6 +547,18 @@ object NativeLibrary { */ external fun getSavePath(programId: String): String + /** + * Adds a file to the manual filesystem provider in our EmulationSession instance + * @param path Path to the file we're adding. Can be a string representation of a [Uri] or + * a normal path + */ + external fun addFileToFilesystemProvider(path: String) + + /** + * Clears all files added to the manual filesystem provider in our EmulationSession instance + */ + external fun clearFilesystemProvider() + /** * Button type for use in onTouchEvent */ 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 55010dc59..579b600f1 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 @@ -36,6 +36,12 @@ object GameHelper { // Ensure keys are loaded so that ROM metadata can be decrypted. NativeLibrary.reloadKeys() + // Reset metadata so we don't use stale information + GameMetadata.resetMetadata() + + // Remove previous filesystem provider information so we can get up to date version info + NativeLibrary.clearFilesystemProvider() + val badDirs = mutableListOf() gameDirs.forEachIndexed { index: Int, gameDir: GameDir -> val gameDirUri = Uri.parse(gameDir.uriString) @@ -92,14 +98,24 @@ object GameHelper { ) } else { if (Game.extensions.contains(FileUtil.getExtension(it.uri))) { - games.add(getGame(it.uri, true)) + val game = getGame(it.uri, true) + if (game != null) { + games.add(game) + } } } } } - fun getGame(uri: Uri, addedToLibrary: Boolean): Game { + fun getGame(uri: Uri, addedToLibrary: Boolean): Game? { val filePath = uri.toString() + if (!GameMetadata.getIsValid(filePath)) { + return null + } + + // Needed to update installed content information + NativeLibrary.addFileToFilesystemProvider(filePath) + var name = GameMetadata.getTitle(filePath) // If the game's title field is empty, use the filename. @@ -118,7 +134,7 @@ object GameHelper { filePath, programId, GameMetadata.getDeveloper(filePath), - GameMetadata.getVersion(filePath), + GameMetadata.getVersion(filePath, false), GameMetadata.getIsHomebrew(filePath) ) 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 index 0f3542ac6..8e412482a 100644 --- 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 @@ -4,13 +4,15 @@ package org.yuzu.yuzu_emu.utils object GameMetadata { + external fun getIsValid(path: String): Boolean + 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 getVersion(path: String, reload: Boolean): String external fun getIcon(path: String): ByteArray diff --git a/src/android/app/src/main/jni/game_metadata.cpp b/src/android/app/src/main/jni/game_metadata.cpp index 24d9df702..78f604c70 100644 --- a/src/android/app/src/main/jni/game_metadata.cpp +++ b/src/android/app/src/main/jni/game_metadata.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include #include @@ -61,7 +62,11 @@ RomMetadata CacheRomMetadata(const std::string& path) { return entry; } -RomMetadata GetRomMetadata(const std::string& path) { +RomMetadata GetRomMetadata(const std::string& path, bool reload = false) { + if (reload) { + return CacheRomMetadata(path); + } + if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) { return search->second; } @@ -71,6 +76,32 @@ RomMetadata GetRomMetadata(const std::string& path) { extern "C" { +jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, + jstring jpath) { + const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile( + GetJString(env, jpath), FileSys::Mode::Read); + if (!file) { + return false; + } + + auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file); + if (!loader) { + return false; + } + + const auto file_type = loader->GetFileType(); + if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) { + return false; + } + + u64 program_id = 0; + Loader::ResultStatus res = loader->ReadProgramId(program_id); + if (res != Loader::ResultStatus::Success) { + return false; + } + return true; +} + jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj, jstring jpath) { return ToJString(env, GetRomMetadata(GetJString(env, jpath)).title); @@ -87,8 +118,8 @@ jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, job } jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj, - jstring jpath) { - return ToJString(env, GetRomMetadata(GetJString(env, jpath)).version); + jstring jpath, jboolean jreload) { + return ToJString(env, GetRomMetadata(GetJString(env, jpath), jreload).version); } jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj, @@ -106,7 +137,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, j } void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) { - return m_rom_metadata_cache.clear(); + m_rom_metadata_cache.clear(); } } // extern "C" diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index ce570b811..0c1db7d46 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -80,7 +80,7 @@ Core::System& EmulationSession::System() { return m_system; } -FileSys::ManualContentProvider* EmulationSession::ContentProvider() { +FileSys::ManualContentProvider* EmulationSession::GetContentProvider() { return m_manual_provider.get(); } @@ -880,4 +880,13 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j return ToJString(env, user_save_data_path); } +void Java_org_yuzu_yuzu_1emu_NativeLibrary_addFileToFilesystemProvider(JNIEnv* env, jobject jobj, + jstring jpath) { + EmulationSession::GetInstance().ConfigureFilesystemProvider(GetJString(env, jpath)); +} + +void Java_org_yuzu_yuzu_1emu_NativeLibrary_clearFilesystemProvider(JNIEnv* env, jobject jobj) { + EmulationSession::GetInstance().GetContentProvider()->ClearAllEntries(); +} + } // extern "C" diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 96c22d52b..4a8049578 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -21,6 +21,7 @@ public: static EmulationSession& GetInstance(); const Core::System& System() const; Core::System& System(); + FileSys::ManualContentProvider* GetContentProvider(); const EmuWindow_Android& Window() const; EmuWindow_Android& Window(); -- cgit v1.2.3