android: Add proper homebrew check
This commit is contained in:
		| @@ -223,6 +223,8 @@ object NativeLibrary { | ||||
|  | ||||
|     external fun getCompany(filename: String): String | ||||
|  | ||||
|     external fun isHomebrew(filename: String): Boolean | ||||
|  | ||||
|     external fun setAppDirectory(directory: String) | ||||
|  | ||||
|     external fun initializeGpuDriver( | ||||
|   | ||||
| @@ -127,13 +127,7 @@ class SearchFragment : Fragment() { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             R.id.chip_homebrew -> { | ||||
|                 baseList.filter { | ||||
|                     Log.error("Guh - ${it.path}") | ||||
|                     FileUtil.hasExtension(it.path, "nro") | ||||
|                             || FileUtil.hasExtension(it.path, "nso") | ||||
|                 } | ||||
|             } | ||||
|             R.id.chip_homebrew -> baseList.filter { it.isHomebrew } | ||||
|  | ||||
|             R.id.chip_retail -> baseList.filter { | ||||
|                 FileUtil.hasExtension(it.path, "xci") | ||||
|   | ||||
| @@ -16,7 +16,8 @@ class Game( | ||||
|     val regions: String, | ||||
|     val path: String, | ||||
|     val gameId: String, | ||||
|     val company: String | ||||
|     val company: String, | ||||
|     val isHomebrew: Boolean | ||||
| ) : Parcelable { | ||||
|     val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime" | ||||
|     val keyLastPlayedTime get() = "${gameId}_LastPlayed" | ||||
| @@ -31,6 +32,7 @@ class Game( | ||||
|                 && path == other.path | ||||
|                 && gameId == other.gameId | ||||
|                 && company == other.company | ||||
|                 && isHomebrew == other.isHomebrew | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|   | ||||
| @@ -13,6 +13,8 @@ import androidx.preference.PreferenceManager | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| 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 | ||||
| @@ -20,6 +22,7 @@ import org.yuzu.yuzu_emu.YuzuApplication | ||||
| import org.yuzu.yuzu_emu.utils.GameHelper | ||||
| import java.util.Locale | ||||
|  | ||||
| @OptIn(ExperimentalSerializationApi::class) | ||||
| class GamesViewModel : ViewModel() { | ||||
|     private val _games = MutableLiveData<List<Game>>(emptyList()) | ||||
|     val games: LiveData<List<Game>> get() = _games | ||||
| @@ -49,7 +52,13 @@ class GamesViewModel : ViewModel() { | ||||
|         if (storedGames!!.isNotEmpty()) { | ||||
|             val deserializedGames = mutableSetOf<Game>() | ||||
|             storedGames.forEach { | ||||
|                 val game: Game = Json.decodeFromString(it) | ||||
|                 val game: Game | ||||
|                 try { | ||||
|                     game = Json.decodeFromString(it) | ||||
|                 } catch (e: MissingFieldException) { | ||||
|                     return@forEach | ||||
|                 } | ||||
|  | ||||
|                 val gameExists = | ||||
|                     DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(game.path)) | ||||
|                         ?.exists() | ||||
|   | ||||
| @@ -6,7 +6,6 @@ package org.yuzu.yuzu_emu.utils | ||||
| import android.content.SharedPreferences | ||||
| import android.net.Uri | ||||
| import androidx.preference.PreferenceManager | ||||
| import kotlinx.serialization.decodeFromString | ||||
| import kotlinx.serialization.encodeToString | ||||
| import kotlinx.serialization.json.Json | ||||
| import org.yuzu.yuzu_emu.NativeLibrary | ||||
| @@ -83,7 +82,8 @@ object GameHelper { | ||||
|             NativeLibrary.getRegions(filePath), | ||||
|             filePath, | ||||
|             gameId, | ||||
|             NativeLibrary.getCompany(filePath) | ||||
|             NativeLibrary.getCompany(filePath), | ||||
|             NativeLibrary.isHomebrew(filePath) | ||||
|         ) | ||||
|  | ||||
|         val addedTime = preferences.getLong(newGame.keyAddedToLibraryTime, 0L) | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
|  | ||||
| #include <android/api-level.h> | ||||
| #include <android/native_window_jni.h> | ||||
| #include <core/loader/nro.h> | ||||
|  | ||||
| #include "common/detached_tasks.h" | ||||
| #include "common/dynamic_library.h" | ||||
| @@ -281,6 +282,10 @@ public: | ||||
|         return GetRomMetadata(path).icon; | ||||
|     } | ||||
|  | ||||
|     bool GetIsHomebrew(const std::string& path) { | ||||
|         return GetRomMetadata(path).isHomebrew; | ||||
|     } | ||||
|  | ||||
|     void ResetRomMetadata() { | ||||
|         m_rom_metadata_cache.clear(); | ||||
|     } | ||||
| @@ -348,6 +353,7 @@ private: | ||||
|     struct RomMetadata { | ||||
|         std::string title; | ||||
|         std::vector<u8> icon; | ||||
|         bool isHomebrew; | ||||
|     }; | ||||
|  | ||||
|     RomMetadata GetRomMetadata(const std::string& path) { | ||||
| @@ -360,11 +366,17 @@ private: | ||||
|  | ||||
|     RomMetadata CacheRomMetadata(const std::string& path) { | ||||
|         const auto file = Core::GetGameFileFromPath(m_vfs, path); | ||||
|         const auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); | ||||
|         auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); | ||||
|  | ||||
|         RomMetadata entry; | ||||
|         loader->ReadTitle(entry.title); | ||||
|         loader->ReadIcon(entry.icon); | ||||
|         if (loader->GetFileType() == Loader::FileType::NRO) { | ||||
|             auto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get()); | ||||
|             entry.isHomebrew = loader_nro->IsHomebrew(); | ||||
|         } else { | ||||
|             entry.isHomebrew = false; | ||||
|         } | ||||
|  | ||||
|         m_rom_metadata_cache[path] = entry; | ||||
|  | ||||
| @@ -662,6 +674,12 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany([[maybe_unused]] JNIEnv | ||||
|     return env->NewStringUTF(""); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHomebrew([[maybe_unused]] JNIEnv* env, | ||||
|                                                           [[maybe_unused]] jclass clazz, | ||||
|                                                           [[maybe_unused]] jstring j_filename) { | ||||
|     return EmulationSession::GetInstance().GetIsHomebrew(GetJString(env, j_filename)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation | ||||
|     [[maybe_unused]] (JNIEnv* env, [[maybe_unused]] jclass clazz) { | ||||
|     // Create the default config.ini. | ||||
|   | ||||
| @@ -33,7 +33,8 @@ static_assert(sizeof(NroSegmentHeader) == 0x8, "NroSegmentHeader has incorrect s | ||||
| struct NroHeader { | ||||
|     INSERT_PADDING_BYTES(0x4); | ||||
|     u32_le module_header_offset; | ||||
|     INSERT_PADDING_BYTES(0x8); | ||||
|     u32 magic_ext1; | ||||
|     u32 magic_ext2; | ||||
|     u32_le magic; | ||||
|     INSERT_PADDING_BYTES(0x4); | ||||
|     u32_le file_size; | ||||
| @@ -124,6 +125,16 @@ FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& nro_file) { | ||||
|     return FileType::Error; | ||||
| } | ||||
|  | ||||
| bool AppLoader_NRO::IsHomebrew() { | ||||
|     // Read NSO header | ||||
|     NroHeader nro_header{}; | ||||
|     if (sizeof(NroHeader) != file->ReadObject(&nro_header)) { | ||||
|         return false; | ||||
|     } | ||||
|     return nro_header.magic_ext1 == Common::MakeMagic('H', 'O', 'M', 'E') && | ||||
|            nro_header.magic_ext2 == Common::MakeMagic('B', 'R', 'E', 'W'); | ||||
| } | ||||
|  | ||||
| static constexpr u32 PageAlignSize(u32 size) { | ||||
|     return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); | ||||
| } | ||||
|   | ||||
| @@ -38,6 +38,8 @@ public: | ||||
|      */ | ||||
|     static FileType IdentifyType(const FileSys::VirtualFile& nro_file); | ||||
|  | ||||
|     bool IsHomebrew(); | ||||
|  | ||||
|     FileType GetFileType() const override { | ||||
|         return IdentifyType(file); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user