2019-11-29 13:46:04 +00:00
|
|
|
#pragma once
|
2020-09-01 02:29:22 +00:00
|
|
|
#include "core/types.h"
|
2020-08-20 11:30:11 +00:00
|
|
|
#include "game_settings.h"
|
2020-01-10 03:31:12 +00:00
|
|
|
#include <memory>
|
2019-11-29 13:46:04 +00:00
|
|
|
#include <optional>
|
|
|
|
#include <string>
|
|
|
|
#include <string_view>
|
|
|
|
#include <unordered_map>
|
2019-11-30 15:27:01 +00:00
|
|
|
#include <vector>
|
2019-11-29 13:46:04 +00:00
|
|
|
|
|
|
|
class CDImage;
|
2020-01-08 03:37:43 +00:00
|
|
|
class ByteStream;
|
2020-03-12 05:32:19 +00:00
|
|
|
class ProgressCallback;
|
2019-11-29 13:46:04 +00:00
|
|
|
|
2019-12-31 06:17:17 +00:00
|
|
|
class SettingsInterface;
|
|
|
|
|
2020-01-24 04:50:44 +00:00
|
|
|
enum class GameListEntryType
|
2019-11-29 13:46:04 +00:00
|
|
|
{
|
2020-01-24 04:50:44 +00:00
|
|
|
Disc,
|
2020-08-15 09:54:33 +00:00
|
|
|
PSExe,
|
2021-01-24 04:06:52 +00:00
|
|
|
Playlist,
|
|
|
|
PSF,
|
|
|
|
Count
|
2020-01-24 04:50:44 +00:00
|
|
|
};
|
2019-12-04 11:12:50 +00:00
|
|
|
|
2020-05-16 10:01:19 +00:00
|
|
|
enum class GameListCompatibilityRating
|
|
|
|
{
|
|
|
|
Unknown = 0,
|
|
|
|
DoesntBoot = 1,
|
|
|
|
CrashesInIntro = 2,
|
|
|
|
CrashesInGame = 3,
|
|
|
|
GraphicalAudioIssues = 4,
|
|
|
|
NoIssues = 5,
|
|
|
|
Count,
|
|
|
|
};
|
|
|
|
|
2020-01-24 04:50:46 +00:00
|
|
|
struct GameListDatabaseEntry
|
|
|
|
{
|
|
|
|
std::string code;
|
|
|
|
std::string title;
|
2020-03-12 03:51:29 +00:00
|
|
|
DiscRegion region;
|
2020-01-24 04:50:46 +00:00
|
|
|
};
|
|
|
|
|
2020-01-24 04:50:44 +00:00
|
|
|
struct GameListEntry
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
std::string code;
|
|
|
|
std::string title;
|
|
|
|
u64 total_size;
|
|
|
|
u64 last_modified_time;
|
2020-03-12 03:51:29 +00:00
|
|
|
DiscRegion region;
|
2020-01-24 04:50:44 +00:00
|
|
|
GameListEntryType type;
|
2020-05-16 10:01:19 +00:00
|
|
|
GameListCompatibilityRating compatibility_rating;
|
2020-08-20 11:30:11 +00:00
|
|
|
GameSettings::Entry settings;
|
2020-05-16 10:01:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct GameListCompatibilityEntry
|
|
|
|
{
|
|
|
|
std::string code;
|
|
|
|
std::string title;
|
|
|
|
std::string version_tested;
|
|
|
|
std::string upscaling_issues;
|
|
|
|
std::string comments;
|
|
|
|
DiscRegion region;
|
|
|
|
GameListCompatibilityRating compatibility_rating;
|
2020-01-24 04:50:44 +00:00
|
|
|
};
|
2019-11-30 13:55:05 +00:00
|
|
|
|
2020-01-24 04:50:44 +00:00
|
|
|
class GameList
|
|
|
|
{
|
|
|
|
public:
|
2019-11-30 13:55:05 +00:00
|
|
|
using EntryList = std::vector<GameListEntry>;
|
|
|
|
|
2021-01-30 05:40:41 +00:00
|
|
|
struct DirectoryEntry
|
|
|
|
{
|
|
|
|
std::string path;
|
|
|
|
bool recursive;
|
|
|
|
};
|
|
|
|
|
2019-11-29 13:46:04 +00:00
|
|
|
GameList();
|
|
|
|
~GameList();
|
|
|
|
|
2021-01-24 04:06:52 +00:00
|
|
|
/// 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);
|
|
|
|
|
2020-01-24 04:50:44 +00:00
|
|
|
static const char* EntryTypeToString(GameListEntryType type);
|
2020-07-06 14:59:28 +00:00
|
|
|
static const char* EntryCompatibilityRatingToString(GameListCompatibilityRating rating);
|
2019-12-04 11:54:14 +00:00
|
|
|
|
2020-05-16 10:01:19 +00:00
|
|
|
/// Returns a string representation of a compatibility level.
|
|
|
|
static const char* GetGameListCompatibilityRatingString(GameListCompatibilityRating rating);
|
|
|
|
|
2019-11-30 13:55:05 +00:00
|
|
|
const EntryList& GetEntries() const { return m_entries; }
|
2019-11-30 15:27:01 +00:00
|
|
|
const u32 GetEntryCount() const { return static_cast<u32>(m_entries.size()); }
|
2021-01-30 05:40:41 +00:00
|
|
|
const std::vector<DirectoryEntry>& GetSearchDirectories() const { return m_search_directories; }
|
|
|
|
const u32 GetSearchDirectoryCount() const { return static_cast<u32>(m_search_directories.size()); }
|
2019-11-30 13:55:05 +00:00
|
|
|
|
2020-01-24 04:50:44 +00:00
|
|
|
const GameListEntry* GetEntryForPath(const char* path) const;
|
2020-01-24 04:50:46 +00:00
|
|
|
const GameListDatabaseEntry* GetDatabaseEntryForCode(const std::string& code) const;
|
2020-05-16 10:01:19 +00:00
|
|
|
const GameListCompatibilityEntry* GetCompatibilityEntryForCode(const std::string& code) const;
|
2020-01-24 04:50:44 +00:00
|
|
|
|
2020-01-24 04:51:09 +00:00
|
|
|
void SetCacheFilename(std::string filename) { m_cache_filename = std::move(filename); }
|
2020-11-27 14:42:09 +00:00
|
|
|
void SetUserDatabaseFilename(std::string filename) { m_user_database_filename = std::move(filename); }
|
2021-01-30 05:40:41 +00:00
|
|
|
void SetUserCompatibilityListFilename(std::string filename)
|
|
|
|
{
|
|
|
|
m_user_compatibility_list_filename = std::move(filename);
|
|
|
|
}
|
2020-08-20 11:30:11 +00:00
|
|
|
void SetUserGameSettingsFilename(std::string filename) { m_user_game_settings_filename = std::move(filename); }
|
2020-01-24 04:51:09 +00:00
|
|
|
void SetSearchDirectoriesFromSettings(SettingsInterface& si);
|
2020-01-24 04:51:12 +00:00
|
|
|
|
2019-12-31 06:17:17 +00:00
|
|
|
void AddDirectory(std::string path, bool recursive);
|
2020-03-12 05:32:19 +00:00
|
|
|
void Refresh(bool invalidate_cache, bool invalidate_database, ProgressCallback* progress = nullptr);
|
2019-11-30 13:55:05 +00:00
|
|
|
|
2020-05-16 10:01:19 +00:00
|
|
|
void UpdateCompatibilityEntry(GameListCompatibilityEntry new_entry, bool save_to_list = true);
|
|
|
|
|
2020-05-16 10:24:25 +00:00
|
|
|
static std::string ExportCompatibilityEntry(const GameListCompatibilityEntry* entry);
|
|
|
|
|
2020-08-20 11:30:11 +00:00
|
|
|
const GameSettings::Entry* GetGameSettings(const std::string& filename, const std::string& game_code);
|
|
|
|
void UpdateGameSettings(const std::string& filename, const std::string& game_code, const std::string& game_title,
|
2020-11-27 07:58:06 +00:00
|
|
|
const GameSettings::Entry& new_entry, bool save_to_list = true);
|
2020-08-20 11:30:11 +00:00
|
|
|
|
2020-11-27 13:56:09 +00:00
|
|
|
std::string GetCoverImagePathForEntry(const GameListEntry* entry) const;
|
|
|
|
std::string GetNewCoverImagePathForEntry(const GameListEntry* entry, const char* new_filename) const;
|
2020-09-23 13:43:32 +00:00
|
|
|
|
2019-11-29 13:46:04 +00:00
|
|
|
private:
|
2020-01-08 03:37:43 +00:00
|
|
|
enum : u32
|
|
|
|
{
|
|
|
|
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
|
2021-01-25 17:12:19 +00:00
|
|
|
GAME_LIST_CACHE_VERSION = 22
|
2020-01-08 03:37:43 +00:00
|
|
|
};
|
|
|
|
|
2020-01-24 04:50:46 +00:00
|
|
|
using DatabaseMap = std::unordered_map<std::string, GameListDatabaseEntry>;
|
2020-01-24 04:50:44 +00:00
|
|
|
using CacheMap = std::unordered_map<std::string, GameListEntry>;
|
2020-05-16 10:01:19 +00:00
|
|
|
using CompatibilityMap = std::unordered_map<std::string, GameListCompatibilityEntry>;
|
2020-01-24 04:50:44 +00:00
|
|
|
|
|
|
|
class RedumpDatVisitor;
|
2020-05-16 10:01:19 +00:00
|
|
|
class CompatibilityListVisitor;
|
2020-01-24 04:50:44 +00:00
|
|
|
|
2020-08-20 11:30:11 +00:00
|
|
|
GameListEntry* GetMutableEntryForPath(const char* path);
|
|
|
|
|
2019-12-04 11:12:50 +00:00
|
|
|
static bool GetExeListEntry(const char* path, GameListEntry* entry);
|
2021-01-24 04:06:52 +00:00
|
|
|
static bool GetPsfListEntry(const char* path, GameListEntry* entry);
|
2020-08-15 09:54:33 +00:00
|
|
|
bool GetM3UListEntry(const char* path, GameListEntry* entry);
|
2019-11-29 13:46:04 +00:00
|
|
|
|
2020-01-08 03:37:43 +00:00
|
|
|
bool GetGameListEntry(const std::string& path, GameListEntry* entry);
|
|
|
|
bool GetGameListEntryFromCache(const std::string& path, GameListEntry* entry);
|
2020-03-12 05:32:19 +00:00
|
|
|
void ScanDirectory(const char* path, bool recursive, ProgressCallback* progress);
|
2019-11-29 13:46:04 +00:00
|
|
|
|
2020-01-08 03:37:43 +00:00
|
|
|
void LoadCache();
|
|
|
|
bool LoadEntriesFromCache(ByteStream* stream);
|
|
|
|
bool OpenCacheForWriting();
|
|
|
|
bool WriteEntryToCache(const GameListEntry* entry, ByteStream* stream);
|
2020-04-25 05:23:36 +00:00
|
|
|
void FlushCacheFileStream();
|
2020-01-08 03:37:43 +00:00
|
|
|
void CloseCacheFileStream();
|
2020-05-16 10:01:19 +00:00
|
|
|
void RewriteCacheFile();
|
2020-01-08 03:37:43 +00:00
|
|
|
void DeleteCacheFile();
|
|
|
|
|
|
|
|
void LoadDatabase();
|
|
|
|
void ClearDatabase();
|
|
|
|
|
2020-05-16 10:01:19 +00:00
|
|
|
void LoadCompatibilityList();
|
2020-11-27 07:58:06 +00:00
|
|
|
bool LoadCompatibilityListFromXML(const std::string& xml);
|
2020-05-16 10:01:19 +00:00
|
|
|
bool SaveCompatibilityDatabaseForEntry(const GameListCompatibilityEntry* entry);
|
|
|
|
|
2020-08-20 11:30:11 +00:00
|
|
|
void LoadGameSettings();
|
|
|
|
|
2019-11-30 13:55:05 +00:00
|
|
|
DatabaseMap m_database;
|
|
|
|
EntryList m_entries;
|
2020-01-08 03:37:43 +00:00
|
|
|
CacheMap m_cache_map;
|
2020-05-16 10:01:19 +00:00
|
|
|
CompatibilityMap m_compatibility_list;
|
2020-08-20 11:30:11 +00:00
|
|
|
GameSettings::Database m_game_settings;
|
2020-01-10 03:31:12 +00:00
|
|
|
std::unique_ptr<ByteStream> m_cache_write_stream;
|
2019-12-31 06:17:17 +00:00
|
|
|
|
|
|
|
std::vector<DirectoryEntry> m_search_directories;
|
2020-01-08 03:37:43 +00:00
|
|
|
std::string m_cache_filename;
|
2020-11-27 14:42:09 +00:00
|
|
|
std::string m_user_database_filename;
|
2020-11-27 07:58:06 +00:00
|
|
|
std::string m_user_compatibility_list_filename;
|
2020-08-20 11:30:11 +00:00
|
|
|
std::string m_user_game_settings_filename;
|
2020-01-08 03:37:43 +00:00
|
|
|
bool m_database_load_tried = false;
|
2020-05-16 10:01:19 +00:00
|
|
|
bool m_compatibility_list_load_tried = false;
|
2020-08-20 11:30:11 +00:00
|
|
|
bool m_game_settings_load_tried = false;
|
2019-11-29 13:46:04 +00:00
|
|
|
};
|