UI: Massive revamp, new features and improvements

This commit is contained in:
Connor McLaughlin
2022-07-11 23:03:29 +10:00
parent 3fb61865e5
commit b42b5501f6
425 changed files with 39701 additions and 29487 deletions

View File

@@ -1,22 +1,18 @@
#pragma once
#include "core/game_database.h"
#include "core/types.h"
#include "game_database.h"
#include "game_settings.h"
#include "util/cd_image.h"
#include <ctime>
#include <memory>
#include <optional>
#include <mutex>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
class ByteStream;
class ProgressCallback;
class SettingsInterface;
struct SystemBootParameters;
enum class GameListEntryType
namespace GameList {
enum class EntryType
{
Disc,
PSExe,
@@ -25,30 +21,19 @@ enum class GameListEntryType
Count
};
enum class GameListCompatibilityRating
struct Entry
{
Unknown = 0,
DoesntBoot = 1,
CrashesInIntro = 2,
CrashesInGame = 3,
GraphicalAudioIssues = 4,
NoIssues = 5,
Count,
};
struct GameListEntry
{
GameListEntryType type = GameListEntryType::Disc;
EntryType type = EntryType::Disc;
DiscRegion region = DiscRegion::Other;
std::string path;
std::string code;
std::string serial;
std::string title;
std::string genre;
std::string publisher;
std::string developer;
u64 total_size = 0;
u64 last_modified_time = 0;
std::time_t last_modified_time = 0;
u64 release_date = 0;
u32 supported_controllers = ~static_cast<u32>(0);
@@ -57,137 +42,47 @@ struct GameListEntry
u8 min_blocks = 0;
u8 max_blocks = 0;
GameListCompatibilityRating compatibility_rating = GameListCompatibilityRating::Unknown;
GameSettings::Entry settings;
GameDatabase::CompatibilityRating compatibility = GameDatabase::CompatibilityRating::Unknown;
size_t GetReleaseDateString(char* buffer, size_t buffer_size) const;
ALWAYS_INLINE bool IsDisc() const { return (type == EntryType::Disc); }
static_assert(sizeof(std::time_t) == sizeof(u64));
};
struct GameListCompatibilityEntry
{
std::string code;
std::string title;
std::string version_tested;
std::string upscaling_issues;
std::string comments;
DiscRegion region = DiscRegion::Other;
GameListCompatibilityRating compatibility_rating = GameListCompatibilityRating::Unknown;
};
const char* GetEntryTypeName(EntryType type);
const char* GetEntryTypeDisplayName(EntryType type);
class GameList
{
public:
using EntryList = std::vector<GameListEntry>;
bool IsScannableFilename(const std::string_view& path);
struct DirectoryEntry
{
std::string path;
bool recursive;
};
/// Populates a game list entry struct with information from the iso/elf.
/// Do *not* call while the system is running, it will mess with CDVD state.
bool PopulateEntryFromPath(const std::string& path, Entry* entry);
GameList();
~GameList();
// Game list access. It's the caller's responsibility to hold the lock while manipulating the entry in any way.
std::unique_lock<std::recursive_mutex> GetLock();
const Entry* GetEntryByIndex(u32 index);
const Entry* GetEntryForPath(const char* path);
const Entry* GetEntryBySerial(const std::string_view& serial);
u32 GetEntryCount();
static const char* EntryTypeToString(GameListEntryType type);
static const char* EntryCompatibilityRatingToString(GameListCompatibilityRating rating);
bool IsGameListLoaded();
/// Returns a string representation of a compatibility level.
static const char* GetGameListCompatibilityRatingString(GameListCompatibilityRating rating);
/// Populates the game list with files in the configured directories.
/// If invalidate_cache is set, all files will be re-scanned.
/// If only_cache is set, no new files will be scanned, only those present in the cache.
void Refresh(bool invalidate_cache, bool only_cache = false, ProgressCallback* progress = nullptr);
static bool IsScannableFilename(const std::string& path);
std::string GetCoverImagePathForEntry(const Entry* entry);
std::string GetCoverImagePath(const std::string& path, const std::string& serial, const std::string& title);
std::string GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename);
}; // namespace GameList
const EntryList& GetEntries() const { return m_entries; }
const u32 GetEntryCount() const { return static_cast<u32>(m_entries.size()); }
const std::vector<DirectoryEntry>& GetSearchDirectories() const { return m_search_directories; }
const u32 GetSearchDirectoryCount() const { return static_cast<u32>(m_search_directories.size()); }
const bool IsGameListLoaded() const { return m_game_list_loaded; }
namespace Host {
/// Asynchronously starts refreshing the game list.
void RefreshGameListAsync(bool invalidate_cache);
const GameListEntry* GetEntryForPath(const char* path) const;
const GameListCompatibilityEntry* GetCompatibilityEntryForCode(const std::string& code) const;
bool GetDatabaseEntryForCode(const std::string_view& code, GameDatabaseEntry* entry);
bool GetDatabaseEntryForDisc(CDImage* image, GameDatabaseEntry* entry);
bool IsPathExcluded(const std::string& path) const;
void SetCacheFilename(std::string filename) { m_cache_filename = std::move(filename); }
void SetUserCompatibilityListFilename(std::string filename)
{
m_user_compatibility_list_filename = std::move(filename);
}
void SetUserGameSettingsFilename(std::string filename) { m_user_game_settings_filename = std::move(filename); }
void SetSearchDirectoriesFromSettings(SettingsInterface& si);
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);
const GameSettings::Entry* GetGameSettings(const std::string& filename, const std::string& game_code);
const GameSettings::Entry* GetGameSettingsForCode(const std::string& game_code);
void UpdateGameSettings(const std::string& filename, const std::string& game_code, const std::string& game_title,
const GameSettings::Entry& new_entry, bool save_to_list = true);
std::string GetCoverImagePathForEntry(const GameListEntry* entry) const;
std::string GetCoverImagePath(const std::string& path, const std::string& code, const std::string& title) const;
std::string GetNewCoverImagePathForEntry(const GameListEntry* entry, const char* new_filename) const;
private:
enum : u32
{
GAME_LIST_CACHE_SIGNATURE = 0x45434C47,
GAME_LIST_CACHE_VERSION = 31
};
using CacheMap = std::unordered_map<std::string, GameListEntry>;
using CompatibilityMap = std::unordered_map<std::string, GameListCompatibilityEntry>;
class RedumpDatVisitor;
class CompatibilityListVisitor;
GameListEntry* GetMutableEntryForPath(const char* path);
static bool GetExeListEntry(const std::string& path, GameListEntry* entry);
static bool GetPsfListEntry(const std::string& 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, ProgressCallback* progress);
bool AddFileFromCache(const std::string& path, std::time_t timestamp);
bool ScanFile(std::string path, std::time_t timestamp);
void LoadCache();
bool LoadEntriesFromCache(ByteStream* stream);
bool OpenCacheForWriting();
bool WriteEntryToCache(const GameListEntry* entry, ByteStream* stream);
void FlushCacheFileStream();
void CloseCacheFileStream();
void RewriteCacheFile();
void DeleteCacheFile();
void LoadDatabase();
void ClearDatabase();
void LoadCompatibilityList();
bool LoadCompatibilityListFromXML(const std::string& xml);
bool SaveCompatibilityDatabaseForEntry(const GameListCompatibilityEntry* entry);
void LoadGameSettings();
EntryList m_entries;
CacheMap m_cache_map;
GameDatabase m_database;
CompatibilityMap m_compatibility_list;
GameSettings::Database m_game_settings;
std::unique_ptr<ByteStream> m_cache_write_stream;
std::vector<DirectoryEntry> m_search_directories;
std::vector<std::string> m_excluded_paths;
std::string m_cache_filename;
std::string m_user_compatibility_list_filename;
std::string m_user_game_settings_filename;
bool m_database_load_tried = false;
bool m_compatibility_list_load_tried = false;
bool m_game_settings_load_tried = false;
bool m_game_list_loaded = false;
};
/// Cancels game list refresh, if there is one in progress.
void CancelGameListRefresh();
} // namespace Host