diff --git a/builds/android/app/src/gamebrowser/org_easyrpg_player_game_browser_GameScanner.cpp b/builds/android/app/src/gamebrowser/org_easyrpg_player_game_browser_GameScanner.cpp index 1cf15c8f6b0..92f0f27bb5b 100644 --- a/builds/android/app/src/gamebrowser/org_easyrpg_player_game_browser_GameScanner.cpp +++ b/builds/android/app/src/gamebrowser/org_easyrpg_player_game_browser_GameScanner.cpp @@ -31,12 +31,15 @@ #include #include - #include "filefinder.h" #include "utils.h" #include "string_view.h" #include "platform/android/android.h" +#include +#include +#include + // via https://stackoverflow.com/q/1821806 static void custom_png_write_func(png_structp png_ptr, png_bytep data, png_size_t length) { std::vector *p = reinterpret_cast*>(png_get_io_ptr(png_ptr)); @@ -216,28 +219,86 @@ Java_org_easyrpg_player_game_1browser_GameScanner_findGames(JNIEnv *env, jclass } } - // Very simple title graphic search: The first image in "Title" is used - auto title_fs = fs.Subtree("Title"); + /// Obtaining of the title image: + // 1. When the title directory contains only one image: Load it + // 2. Attempt to fetch it from the database + // 3. If this fails grab the first from the title folder jbyteArray title_image = nullptr; + + auto load_image = [&](Filesystem_Stream::InputStream& stream) { + if (!stream) { + return; + } + + if (stream.GetName().ends_with(".xyz")) { + title_image = readXyz(env, stream); + } else if (stream.GetName().ends_with(".png") || stream.GetName().ends_with(".bmp")) { + auto vec = Utils::ReadStream(stream); + title_image = env->NewByteArray(vec.size()); + env->SetByteArrayRegion(title_image, 0, vec.size(), reinterpret_cast(vec.data())); + } + }; + + // 1. When the title directory contains only one image: Load it + auto title_fs = fs.Subtree("Title"); if (title_fs) { - for (auto &[name, entry]: *title_fs.ListDirectory()) { - if (entry.type == DirectoryTree::FileType::Regular) { - if (StringView(name).ends_with(".xyz")) { - auto is = title_fs.OpenInputStream(entry.name); - title_image = readXyz(env, is); - } else if (StringView(name).ends_with(".png") || - StringView(name).ends_with(".bmp")) { - auto is = title_fs.OpenInputStream(entry.name); - if (!is) { - // When opening of the image fails it is an unsupported archive format - // Skip this game - continue; + auto& content = *title_fs.ListDirectory(); + if (content.size() == 1 && content[0].second.type == DirectoryTree::FileType::Regular) { + auto is = title_fs.OpenInputStream(content[0].second.name); + if (!is) { + // When opening of the image fails it is in an unsupported archive format + // Skip this game + continue; + } + load_image(is); + } + } + + // 2. Attempt to fetch it from the database + if (!title_image) { + std::string db_file = fs.FindFile("RPG_RT.ldb"); + if (!db_file.empty()) { + // This can fail when the database file is renamed, is not an error condition + auto is = fs.OpenInputStream(db_file); + if (!is) { + // When opening of the db fails it is in an unsupported archive format + // Skip this game + continue; + } else { + auto db = lcf::LDB_Reader::Load(is); + if (!db) { + // Database corrupted? Skip + continue; + } + + if (!db->system.title_name.empty()) { + auto encodings = lcf::ReaderUtil::DetectEncodings(*db); + for (auto &enc: encodings) { + lcf::Encoder encoder(enc); + if (encoder.IsOk()) { + std::string title_name = lcf::ToString(db->system.title_name); + encoder.Encode(title_name); + auto title_is = fs.OpenFile("Title", title_name, FileFinder::IMG_TYPES); + // Title image was found -> Load it + load_image(title_is); + } } + } + } + } + } - auto vec = Utils::ReadStream(is); - title_image = env->NewByteArray(vec.size()); - env->SetByteArrayRegion(title_image, 0, vec.size(), - reinterpret_cast(vec.data())); + // 3. Simply grab the first from the title folder + if (!title_image) { + // No image loaded yet: Grab the first from the title folder + if (title_fs) { + for (auto &[name, entry]: *title_fs.ListDirectory()) { + if (entry.type == DirectoryTree::FileType::Regular) { + auto is = title_fs.OpenInputStream(entry.name); + load_image(is); + if (title_image) { + break; + } } } } diff --git a/src/filefinder.cpp b/src/filefinder.cpp index b0341a45573..ea2ac1500fb 100644 --- a/src/filefinder.cpp +++ b/src/filefinder.cpp @@ -62,14 +62,6 @@ namespace { std::shared_ptr root_fs; FilesystemView game_fs; FilesystemView save_fs; - - constexpr const auto IMG_TYPES = Utils::MakeSvArray(".bmp", ".png", ".xyz"); - constexpr const auto MUSIC_TYPES = Utils::MakeSvArray( - ".opus", ".oga", ".ogg", ".wav", ".mid", ".midi", ".mp3", ".wma"); - constexpr const auto SOUND_TYPES = Utils::MakeSvArray( - ".opus", ".oga", ".ogg", ".wav", ".mp3", ".wma"); - constexpr const auto FONTS_TYPES = Utils::MakeSvArray(".fon", ".fnt", ".bdf", ".ttf", ".ttc", ".otf", ".woff2", ".woff"); - constexpr const auto TEXT_TYPES = Utils::MakeSvArray(".txt", ".csv", ""); // "" = Complete Filename (incl. extension) provided by the user } FilesystemView FileFinder::Game() { diff --git a/src/filefinder.h b/src/filefinder.h index ab0c688767a..9188212df88 100644 --- a/src/filefinder.h +++ b/src/filefinder.h @@ -37,6 +37,14 @@ * insensitive files paths. */ namespace FileFinder { + constexpr const auto IMG_TYPES = Utils::MakeSvArray(".bmp", ".png", ".xyz"); + constexpr const auto MUSIC_TYPES = Utils::MakeSvArray( + ".opus", ".oga", ".ogg", ".wav", ".mid", ".midi", ".mp3", ".wma"); + constexpr const auto SOUND_TYPES = Utils::MakeSvArray( + ".opus", ".oga", ".ogg", ".wav", ".mp3", ".wma"); + constexpr const auto FONTS_TYPES = Utils::MakeSvArray(".fon", ".fnt", ".bdf", ".ttf", ".ttc", ".otf", ".woff2", ".woff"); + constexpr const auto TEXT_TYPES = Utils::MakeSvArray(".txt", ".csv", ""); // "" = Complete Filename (incl. extension) provided by the user + /** * Quits FileFinder. */