duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

game_list.h (5978B)


      1 // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
      2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
      3 
      4 #pragma once
      5 
      6 #include "game_database.h"
      7 #include "types.h"
      8 
      9 #include "util/cd_image.h"
     10 
     11 #include "common/small_string.h"
     12 
     13 #include <ctime>
     14 #include <functional>
     15 #include <mutex>
     16 #include <span>
     17 #include <string>
     18 
     19 class ByteStream;
     20 class ProgressCallback;
     21 
     22 struct SystemBootParameters;
     23 
     24 namespace GameList {
     25 enum class EntryType
     26 {
     27   Disc,
     28   DiscSet,
     29   PSExe,
     30   Playlist,
     31   PSF,
     32   Count
     33 };
     34 
     35 struct Entry
     36 {
     37   EntryType type = EntryType::Disc;
     38   DiscRegion region = DiscRegion::Other;
     39 
     40   std::string path;
     41   std::string serial;
     42   std::string title;
     43   std::string disc_set_name;
     44   std::string genre;
     45   std::string publisher;
     46   std::string developer;
     47   u64 hash = 0;
     48   s64 file_size = 0;
     49   u64 uncompressed_size = 0;
     50   std::time_t last_modified_time = 0;
     51   std::time_t last_played_time = 0;
     52   std::time_t total_played_time = 0;
     53 
     54   u64 release_date = 0;
     55   u16 supported_controllers = static_cast<u16>(~0u);
     56   u8 min_players = 1;
     57   u8 max_players = 1;
     58   u8 min_blocks = 0;
     59   u8 max_blocks = 0;
     60   s8 disc_set_index = -1;
     61   bool disc_set_member = false;
     62   bool has_custom_title = false;
     63   bool has_custom_region = false;
     64 
     65   GameDatabase::CompatibilityRating compatibility = GameDatabase::CompatibilityRating::Unknown;
     66 
     67   size_t GetReleaseDateString(char* buffer, size_t buffer_size) const;
     68 
     69   ALWAYS_INLINE bool IsDisc() const { return (type == EntryType::Disc); }
     70   ALWAYS_INLINE bool IsDiscSet() const { return (type == EntryType::DiscSet); }
     71   ALWAYS_INLINE EntryType GetSortType() const { return (type == EntryType::DiscSet) ? EntryType::Disc : type; }
     72 };
     73 
     74 using EntryList = std::vector<Entry>;
     75 
     76 const char* GetEntryTypeName(EntryType type);
     77 const char* GetEntryTypeDisplayName(EntryType type);
     78 
     79 bool IsScannableFilename(std::string_view path);
     80 
     81 /// Populates a game list entry struct with information from the iso/elf.
     82 /// Do *not* call while the system is running, it will mess with CDVD state.
     83 bool PopulateEntryFromPath(const std::string& path, Entry* entry);
     84 
     85 // Game list access. It's the caller's responsibility to hold the lock while manipulating the entry in any way.
     86 std::unique_lock<std::recursive_mutex> GetLock();
     87 const Entry* GetEntryByIndex(u32 index);
     88 const Entry* GetEntryForPath(std::string_view path);
     89 const Entry* GetEntryBySerial(std::string_view serial);
     90 const Entry* GetEntryBySerialAndHash(std::string_view serial, u64 hash);
     91 std::vector<const Entry*> GetDiscSetMembers(std::string_view disc_set_name, bool sort_by_most_recent = false);
     92 const Entry* GetFirstDiscSetMember(std::string_view disc_set_name);
     93 u32 GetEntryCount();
     94 
     95 bool IsGameListLoaded();
     96 
     97 /// Populates the game list with files in the configured directories.
     98 /// If invalidate_cache is set, all files will be re-scanned.
     99 /// If only_cache is set, no new files will be scanned, only those present in the cache.
    100 void Refresh(bool invalidate_cache, bool only_cache = false, ProgressCallback* progress = nullptr);
    101 
    102 /// Moves the current game list, which can be temporarily displayed in the UI until refresh completes.
    103 /// The caller **must** call Refresh() afterward, otherwise it will be permanently lost.
    104 EntryList TakeEntryList();
    105 
    106 /// Add played time for the specified serial.
    107 void AddPlayedTimeForSerial(const std::string& serial, std::time_t last_time, std::time_t add_time);
    108 void ClearPlayedTimeForSerial(const std::string& serial);
    109 
    110 /// Returns the total time played for a game. Requires the game to be scanned in the list.
    111 std::time_t GetCachedPlayedTimeForSerial(const std::string& serial);
    112 
    113 /// Formats a timestamp to something human readable (e.g. Today, Yesterday, 10/11/12).
    114 TinyString FormatTimestamp(std::time_t timestamp);
    115 
    116 /// Formats a timespan to something human readable (e.g. 1h2m3s or 1 hour).
    117 TinyString FormatTimespan(std::time_t timespan, bool long_format = false);
    118 
    119 std::string GetCoverImagePathForEntry(const Entry* entry);
    120 std::string GetCoverImagePath(const std::string& path, const std::string& serial, const std::string& title);
    121 std::string GetNewCoverImagePathForEntry(const Entry* entry, const char* new_filename, bool use_serial);
    122 
    123 /// Returns a list of (title, entry) for entries matching serials. Titles will match the gamedb title,
    124 /// except when two files have the same serial, in which case the filename will be used instead.
    125 std::vector<std::pair<std::string, const Entry*>>
    126 GetMatchingEntriesForSerial(const std::span<const std::string> serials);
    127 
    128 /// Downloads covers using the specified URL templates. By default, covers are saved by title, but this can be changed
    129 /// with the use_serial parameter. save_callback optionall takes the entry and the path the new cover is saved to.
    130 bool DownloadCovers(const std::vector<std::string>& url_templates, bool use_serial = false,
    131                     ProgressCallback* progress = nullptr,
    132                     std::function<void(const Entry*, std::string)> save_callback = {});
    133 
    134 // Custom properties support
    135 void SaveCustomTitleForPath(const std::string& path, const std::string& custom_title);
    136 void SaveCustomRegionForPath(const std::string& path, const std::optional<DiscRegion> custom_region);
    137 std::string GetCustomTitleForPath(const std::string_view path);
    138 std::optional<DiscRegion> GetCustomRegionForPath(const std::string_view path);
    139 
    140 /// The purpose of this cache is to stop us trying to constantly extract memory card icons, when we know a game
    141 /// doesn't have any saves yet. It caches the serial:memcard_timestamp pair, and only tries extraction when the
    142 /// timestamp of the memory card has changed.
    143 std::string GetGameIconPath(std::string_view serial, std::string_view path);
    144 void ReloadMemcardTimestampCache();
    145 
    146 }; // namespace GameList
    147 
    148 namespace Host {
    149 /// Asynchronously starts refreshing the game list.
    150 void RefreshGameListAsync(bool invalidate_cache);
    151 
    152 /// Cancels game list refresh, if there is one in progress.
    153 void CancelGameListRefresh();
    154 } // namespace Host