#pragma once #include "types.h" #include #include #include #include #include #include class CDImage; class ByteStream; class SettingsInterface; enum class GameListEntryType { Disc, PSExe }; struct GameListDatabaseEntry { std::string code; std::string title; ConsoleRegion region; }; struct GameListEntry { std::string path; std::string code; std::string title; u64 total_size; u64 last_modified_time; ConsoleRegion region; GameListEntryType type; }; class GameList { public: using EntryList = std::vector; GameList(); ~GameList(); static const char* EntryTypeToString(GameListEntryType type); /// Returns true if the filename is a PlayStation executable we can inject. static bool IsExeFileName(const char* path); static std::string GetGameCodeForImage(CDImage* cdi); static std::string GetGameCodeForPath(const char* image_path); static std::optional GetRegionForCode(std::string_view code); static std::optional GetRegionFromSystemArea(CDImage* cdi); static std::optional GetRegionForImage(CDImage* cdi); static std::optional GetRegionForPath(const char* image_path); static std::string_view GetTitleForPath(const char* path); const EntryList& GetEntries() const { return m_entries; } const u32 GetEntryCount() const { return static_cast(m_entries.size()); } const GameListEntry* GetEntryForPath(const char* path) const; const GameListDatabaseEntry* GetDatabaseEntryForCode(const std::string& code) const; void SetCacheFilename(std::string filename) { m_cache_filename = std::move(filename); } void SetDatabaseFilename(std::string filename) { m_database_filename = std::move(filename); } void SetSearchDirectoriesFromSettings(SettingsInterface& si); void AddDirectory(std::string path, bool recursive); void Refresh(bool invalidate_cache, bool invalidate_database); private: enum : u32 { GAME_LIST_CACHE_SIGNATURE = 0x45434C47, GAME_LIST_CACHE_VERSION = 2 }; using DatabaseMap = std::unordered_map; using CacheMap = std::unordered_map; struct DirectoryEntry { std::string path; bool recursive; }; class RedumpDatVisitor; static bool GetExeListEntry(const char* path, GameListEntry* entry); bool GetGameListEntry(const std::string& path, GameListEntry* entry); bool GetGameListEntryFromCache(const std::string& path, GameListEntry* entry); void ScanDirectory(const char* path, bool recursive); void LoadCache(); bool LoadEntriesFromCache(ByteStream* stream); bool OpenCacheForWriting(); bool WriteEntryToCache(const GameListEntry* entry, ByteStream* stream); void CloseCacheFileStream(); void DeleteCacheFile(); void LoadDatabase(); void ClearDatabase(); DatabaseMap m_database; EntryList m_entries; CacheMap m_cache_map; std::unique_ptr m_cache_write_stream; std::vector m_search_directories; std::string m_cache_filename; std::string m_database_filename; bool m_database_load_tried = false; };