Duckstation/src/core/game_list.h

179 lines
5.4 KiB
C
Raw Normal View History

#pragma once
#include "types.h"
2020-01-10 03:31:12 +00:00
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
2019-11-30 15:27:01 +00:00
#include <vector>
class CDImage;
2020-01-08 03:37:43 +00:00
class ByteStream;
class ProgressCallback;
2019-12-31 06:17:17 +00:00
class SettingsInterface;
enum class GameListEntryType
{
Disc,
2020-08-15 09:54:33 +00:00
PSExe,
Playlist
};
2019-12-04 11:12:50 +00:00
enum class GameListCompatibilityRating
{
Unknown = 0,
DoesntBoot = 1,
CrashesInIntro = 2,
CrashesInGame = 3,
GraphicalAudioIssues = 4,
NoIssues = 5,
Count,
};
struct GameListDatabaseEntry
{
std::string code;
std::string title;
DiscRegion region;
};
struct GameListEntry
{
std::string path;
std::string code;
std::string title;
u64 total_size;
u64 last_modified_time;
DiscRegion region;
GameListEntryType type;
GameListCompatibilityRating compatibility_rating;
};
struct GameListCompatibilityEntry
{
std::string code;
std::string title;
std::string version_tested;
std::string upscaling_issues;
std::string comments;
DiscRegion region;
GameListCompatibilityRating compatibility_rating;
};
class GameList
{
public:
using EntryList = std::vector<GameListEntry>;
GameList();
~GameList();
static const char* EntryTypeToString(GameListEntryType type);
static const char* EntryCompatibilityRatingToString(GameListCompatibilityRating rating);
2020-01-10 03:31:12 +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);
2020-07-22 16:36:05 +00:00
/// Returns true if the filename is a M3U Playlist we can handle.
static bool IsM3UFileName(const char* path);
/// Parses an M3U playlist, returning the entries.
static std::vector<std::string> ParseM3UFile(const char* path);
/// Returns a string representation of a compatibility level.
static const char* GetGameListCompatibilityRatingString(GameListCompatibilityRating rating);
static std::string GetGameCodeForImage(CDImage* cdi);
static std::string GetGameCodeForPath(const char* image_path);
static DiscRegion GetRegionForCode(std::string_view code);
static DiscRegion GetRegionFromSystemArea(CDImage* cdi);
static DiscRegion GetRegionForImage(CDImage* cdi);
static std::optional<DiscRegion> GetRegionForPath(const char* image_path);
static std::string_view GetTitleForPath(const char* path);
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()); }
const GameListEntry* GetEntryForPath(const char* path) const;
const GameListDatabaseEntry* GetDatabaseEntryForCode(const std::string& code) const;
const GameListCompatibilityEntry* GetCompatibilityEntryForCode(const std::string& code) const;
const std::string& GetCacheFilename() const { return m_cache_filename; }
const std::string& GetDatabaseFilename() const { return m_database_filename; }
const std::string& GetCompatibilityFilename() const { return m_database_filename; }
void SetCacheFilename(std::string filename) { m_cache_filename = std::move(filename); }
void SetDatabaseFilename(std::string filename) { m_database_filename = std::move(filename); }
void SetCompatibilityFilename(std::string filename) { m_compatibility_list_filename = std::move(filename); }
void SetSearchDirectoriesFromSettings(SettingsInterface& si);
bool IsDatabasePresent() const;
2019-12-31 06:17:17 +00:00
void AddDirectory(std::string path, bool recursive);
void Refresh(bool invalidate_cache, bool invalidate_database, ProgressCallback* progress = nullptr);
void UpdateCompatibilityEntry(GameListCompatibilityEntry new_entry, bool save_to_list = true);
static std::string ExportCompatibilityEntry(const GameListCompatibilityEntry* entry);
private:
2020-01-08 03:37:43 +00:00
enum : u32
{
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
GAME_LIST_CACHE_VERSION = 5
2020-01-08 03:37:43 +00:00
};
using DatabaseMap = std::unordered_map<std::string, GameListDatabaseEntry>;
using CacheMap = std::unordered_map<std::string, GameListEntry>;
using CompatibilityMap = std::unordered_map<std::string, GameListCompatibilityEntry>;
2019-12-31 06:17:17 +00:00
struct DirectoryEntry
{
std::string path;
bool recursive;
};
class RedumpDatVisitor;
class CompatibilityListVisitor;
2019-12-04 11:12:50 +00:00
static bool GetExeListEntry(const char* path, GameListEntry* entry);
2020-08-15 09:54:33 +00:00
bool GetM3UListEntry(const char* path, GameListEntry* entry);
2020-01-08 03:37:43 +00:00
bool GetGameListEntry(const std::string& path, GameListEntry* entry);
bool GetGameListEntryFromCache(const std::string& path, GameListEntry* entry);
void ScanDirectory(const char* path, bool recursive, ProgressCallback* progress);
2020-01-08 03:37:43 +00:00
void LoadCache();
bool LoadEntriesFromCache(ByteStream* stream);
bool OpenCacheForWriting();
bool WriteEntryToCache(const GameListEntry* entry, ByteStream* stream);
void FlushCacheFileStream();
2020-01-08 03:37:43 +00:00
void CloseCacheFileStream();
void RewriteCacheFile();
2020-01-08 03:37:43 +00:00
void DeleteCacheFile();
void LoadDatabase();
void ClearDatabase();
void LoadCompatibilityList();
bool SaveCompatibilityDatabase();
bool SaveCompatibilityDatabaseForEntry(const GameListCompatibilityEntry* entry);
DatabaseMap m_database;
EntryList m_entries;
2020-01-08 03:37:43 +00:00
CacheMap m_cache_map;
CompatibilityMap m_compatibility_list;
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;
std::string m_database_filename;
std::string m_compatibility_list_filename;
2020-01-08 03:37:43 +00:00
bool m_database_load_tried = false;
bool m_compatibility_list_load_tried = false;
};