diff --git a/src/frontend-common/game_list.cpp b/src/frontend-common/game_list.cpp index fc1f2328e..4a203439b 100644 --- a/src/frontend-common/game_list.cpp +++ b/src/frontend-common/game_list.cpp @@ -9,6 +9,7 @@ #include "common/string_util.h" #include "core/bios.h" #include "core/host_interface.h" +#include "core/psf_loader.h" #include "core/settings.h" #include "core/system.h" #include @@ -25,7 +26,8 @@ GameList::~GameList() = default; const char* GameList::EntryTypeToString(GameListEntryType type) { - static std::array names = {{"Disc", "PSExe", "Playlist"}}; + static std::array(GameListEntryType::Count)> names = { + {"Disc", "PSExe", "Playlist", "PSF"}}; return names[static_cast(type)]; } @@ -107,6 +109,45 @@ bool GameList::GetExeListEntry(const char* path, GameListEntry* entry) return true; } +bool GameList::GetPsfListEntry(const char* path, GameListEntry* entry) +{ + FILESYSTEM_STAT_DATA ffd; + if (!FileSystem::StatFile(path, &ffd)) + return false; + + PSFLoader::File file; + if (!file.Load(path)) + return false; + + entry->code.clear(); + entry->path = path; + entry->region = file.GetRegion(); + entry->total_size = ffd.Size; + entry->last_modified_time = ffd.ModificationTime.AsUnixTimestamp(); + entry->type = GameListEntryType::PSF; + entry->compatibility_rating = GameListCompatibilityRating::Unknown; + + // Game - Title + std::optional game(file.GetTagString("game")); + if (game.has_value()) + { + entry->title = std::move(game.value()); + entry->title += " - "; + } + else + { + entry->title.clear(); + } + + std::optional title(file.GetTagString("title")); + if (title.has_value()) + entry->title += title.value(); + else + entry->title += GetFileNameFromPath(path); + + return true; +} + bool GameList::GetM3UListEntry(const char* path, GameListEntry* entry) { FILESYSTEM_STAT_DATA ffd; @@ -158,6 +199,8 @@ bool GameList::GetGameListEntry(const std::string& path, GameListEntry* entry) { if (System::IsExeFileName(path.c_str())) return GetExeListEntry(path.c_str(), entry); + if (System::IsPsfFileName(path.c_str())) + return GetPsfListEntry(path.c_str(), entry); if (System::IsM3UFileName(path.c_str())) return GetM3UListEntry(path.c_str(), entry); @@ -325,7 +368,7 @@ bool GameList::LoadEntriesFromCache(ByteStream* stream) if (!ReadString(stream, &path) || !ReadString(stream, &code) || !ReadString(stream, &title) || !ReadU64(stream, &total_size) || !ReadU64(stream, &last_modified_time) || !ReadU8(stream, ®ion) || region >= static_cast(DiscRegion::Count) || !ReadU8(stream, &type) || - type > static_cast(GameListEntryType::Playlist) || !ReadU8(stream, &compatibility_rating) || + type >= static_cast(GameListEntryType::Count) || !ReadU8(stream, &compatibility_rating) || compatibility_rating >= static_cast(GameListCompatibilityRating::Count)) { Log_WarningPrintf("Game list cache entry is corrupted"); diff --git a/src/frontend-common/game_list.h b/src/frontend-common/game_list.h index 9bc7aa929..d7138287a 100644 --- a/src/frontend-common/game_list.h +++ b/src/frontend-common/game_list.h @@ -18,7 +18,9 @@ enum class GameListEntryType { Disc, PSExe, - Playlist + Playlist, + PSF, + Count }; enum class GameListCompatibilityRating @@ -71,6 +73,15 @@ public: GameList(); ~GameList(); + /// Returns true if the filename is a PlayStation executable we can inject. + static bool IsExeFileName(const char* path); + + /// Returns true if the filename is a Portable Sound Format file we can uncompress/load. + static bool IsPsfFileName(const char* path); + + /// Returns true if the filename is a M3U Playlist we can handle. + static bool IsM3UFileName(const char* path); + static const char* EntryTypeToString(GameListEntryType type); static const char* EntryCompatibilityRatingToString(GameListCompatibilityRating rating); @@ -127,6 +138,7 @@ private: GameListEntry* GetMutableEntryForPath(const char* path); static bool GetExeListEntry(const char* path, GameListEntry* entry); + static bool GetPsfListEntry(const char* path, GameListEntry* entry); bool GetM3UListEntry(const char* path, GameListEntry* entry); bool GetGameListEntry(const std::string& path, GameListEntry* entry);