// Copyright (c) 2013- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include <string>20#include <map>21#include <memory>22#include <mutex>23#include <atomic>2425#include "Common/Thread/Event.h"26#include "Core/ELF/ParamSFO.h"27#include "Common/File/Path.h"2829namespace Draw {30class DrawContext;31class Texture;32}3334// A GameInfo holds information about a game, and also lets you do things that the VSH35// does on the PSP, namely checking for and deleting savedata, and similar things.36// Only cares about games that are installed on the current device.3738// A GameInfo object can also represent a piece of savedata.3940enum class GameInfoFlags {41FILE_TYPE = 0x01, // Don't need to specify this, always included.42PARAM_SFO = 0x02,43ICON = 0x04,44PIC1 = 0x08,45PIC0 = 0x10,46SND = 0x20,47SIZE = 0x40,48UNCOMPRESSED_SIZE = 0x80,49};50ENUM_CLASS_BITOPS(GameInfoFlags);5152class FileLoader;53enum class IdentifiedFileType;5455struct GameInfoTex {56std::string data;57Draw::Texture *texture = nullptr;58// The time at which the Icon and the BG were loaded.59// Can be useful to fade them in smoothly once they appear.60// Also, timeLoaded != 0 && texture == nullptr means that the load failed.61double timeLoaded = 0.0;62std::atomic<bool> dataLoaded{};6364// Can ONLY be called from the main thread!65void Clear();66bool Failed() const {67return timeLoaded != 0.0 && !texture;68}69};7071class GameInfo {72public:73GameInfo(const Path &gamePath);74~GameInfo();7576bool Delete(); // Better be sure what you're doing when calling this. Will move to trash if available on the system, though.77bool DeleteAllSaveData();78bool CreateLoader();7980bool HasFileLoader() const {81return fileLoader.get() != nullptr;82}8384std::shared_ptr<FileLoader> GetFileLoader();85void DisposeFileLoader();8687u64 GetSizeUncompressedInBytes(); // NOTE: More expensive than GetGameSizeOnDiskInBytes().88u64 GetSizeOnDiskInBytes();89u64 GetGameSavedataSizeInBytes(); // For games90u64 GetInstallDataSizeInBytes();9192// For various kinds of savedata, mainly.93// NOTE: This one actually performs I/O directly, not cached.94std::string GetMTime() const;9596void ParseParamSFO();97const ParamSFOData &GetParamSFO() const {98_dbg_assert_(hasFlags & GameInfoFlags::PARAM_SFO);99return paramSFO;100}101void FinishPendingTextureLoads(Draw::DrawContext *draw);102103std::vector<Path> GetSaveDataDirectories();104105std::string GetTitle();106void SetTitle(const std::string &newTitle);107108const Path &GetFilePath() const {109return filePath_;110}111112bool Ready(GameInfoFlags flags) {113std::unique_lock<std::mutex> guard(lock);114// Avoid the operator, we want to check all the bits.115return ((int)hasFlags & (int)flags) == (int)flags;116}117118void MarkReadyNoLock(GameInfoFlags flags) {119hasFlags |= flags;120pendingFlags &= ~flags;121}122123GameInfoTex *GetPIC1() {124if (pic1.texture)125return &pic1;126return nullptr;127}128129// Hold this when reading or writing from the GameInfo.130// Don't need to hold it when just passing around the pointer,131// and obviously also not when creating it and holding the only pointer132// to it.133std::mutex lock;134135// Controls access to the fileLoader pointer.136std::mutex loaderLock;137138// Keep track of what we have, or what we're processing.139// These are protected by the mutex. While pendingFlags != 0, something is being loaded.140GameInfoFlags hasFlags{};141GameInfoFlags pendingFlags{};142143std::string id;144std::string id_version;145int disc_total = 0;146int disc_number = 0;147GameRegion region = GameRegion::OTHER;148IdentifiedFileType fileType;149bool hasConfig = false;150151// Pre read the data, create a texture the next time152GameInfoTex icon;153GameInfoTex pic0;154GameInfoTex pic1;155156std::string sndFileData;157std::atomic<bool> sndDataLoaded{};158159double lastAccessedTime = 0.0;160161u64 gameSizeUncompressed = 0;162u64 gameSizeOnDisk = 0; // compressed size, in case of CSO163u64 saveDataSize = 0;164u64 installDataSize = 0;165166protected:167ParamSFOData paramSFO;168// Note: this can change while loading, use GetTitle().169std::string title;170171// TODO: Get rid of this shared_ptr and managae lifetime better instead.172std::shared_ptr<FileLoader> fileLoader;173Path filePath_;174175void SetupTexture(Draw::DrawContext *draw, GameInfoTex &tex);176177private:178DISALLOW_COPY_AND_ASSIGN(GameInfo);179friend class GameInfoWorkItem;180};181182class GameInfoCache {183public:184GameInfoCache();185~GameInfoCache();186187// This creates a background worker thread!188void Clear();189void PurgeType(IdentifiedFileType fileType);190191// All data in GameInfo including icon.texture may be zero the first time you call this192// but filled in later asynchronously in the background. So keep calling this,193// redrawing the UI often. Only set flags to GAMEINFO_WANTBG or WANTSND if you really want them194// because they're big. bgTextures and sound may be discarded over time as well.195// NOTE: This never returns null, so you don't need to check for that. Do check Ready() flags though.196std::shared_ptr<GameInfo> GetInfo(Draw::DrawContext *draw, const Path &gamePath, GameInfoFlags wantFlags);197void FlushBGs(); // Gets rid of all BG textures. Also gets rid of bg sounds.198199void CancelAll();200201private:202void Init();203void Shutdown();204205// Maps ISO path to info. Need to use shared_ptr as we can return these pointers -206// and if they get destructed while being in use, that's bad.207std::map<std::string, std::shared_ptr<GameInfo> > info_;208std::mutex mapLock_;209};210211// This one can be global, no good reason not to.212extern GameInfoCache *g_gameInfoCache;213214215