// 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 {41EMPTY = 0x00,42FILE_TYPE = 0x01, // Don't need to specify this, always included.43PARAM_SFO = 0x02,44ICON = 0x04,45PIC1 = 0x08,46PIC0 = 0x10,47SND = 0x20,48SIZE = 0x40,49UNCOMPRESSED_SIZE = 0x80,50};51ENUM_CLASS_BITOPS(GameInfoFlags);5253class FileLoader;54enum class IdentifiedFileType;5556struct GameInfoTex {57std::string data;58Draw::Texture *texture = nullptr;59// The time at which the Icon and the BG were loaded.60// Can be useful to fade them in smoothly once they appear.61// Also, timeLoaded != 0 && texture == nullptr means that the load failed.62double timeLoaded = 0.0;63std::atomic<bool> dataLoaded{};6465// Can ONLY be called from the main thread!66void Clear();67bool Failed() const {68return timeLoaded != 0.0 && !texture;69}70};7172class GameInfo {73public:74GameInfo(const Path &gamePath);75~GameInfo();7677bool Delete(); // Better be sure what you're doing when calling this. Will move to trash if available on the system, though.78bool DeleteAllSaveData();79bool CreateLoader();8081bool HasFileLoader() const {82return fileLoader.get() != nullptr;83}8485std::shared_ptr<FileLoader> GetFileLoader();86void DisposeFileLoader();8788u64 GetSizeUncompressedInBytes(); // NOTE: More expensive than GetGameSizeOnDiskInBytes().89u64 GetSizeOnDiskInBytes();90u64 GetGameSavedataSizeInBytes(); // For games91u64 GetInstallDataSizeInBytes();9293// For various kinds of savedata, mainly.94// NOTE: This one actually performs I/O directly, not cached.95std::string GetMTime() const;9697void ParseParamSFO(IdentifiedFileType type);98const ParamSFOData &GetParamSFO() const {99_dbg_assert_(hasFlags & GameInfoFlags::PARAM_SFO);100return paramSFO;101}102void FinishPendingTextureLoads(Draw::DrawContext *draw);103104std::vector<Path> GetSaveDataDirectories();105106std::string GetTitle();107std::string GetDBTitle(); // Falls back to GetTitle if not in the DB.108109void SetTitle(const std::string &newTitle);110111const Path &GetFilePath() const {112return filePath_;113}114115bool Ready(GameInfoFlags flags) {116std::unique_lock<std::mutex> guard(lock);117// Avoid the operator, we want to check all the bits.118return ((int)hasFlags & (int)flags) == (int)flags;119}120121void MarkReadyNoLock(GameInfoFlags flags) {122hasFlags |= flags;123pendingFlags &= ~flags;124}125126GameInfoTex *GetPIC1() {127if (pic1.texture)128return &pic1;129return nullptr;130}131132// Hold this when reading or writing from the GameInfo.133// Don't need to hold it when just passing around the pointer,134// and obviously also not when creating it and holding the only pointer135// to it.136std::mutex lock;137138// Controls access to the fileLoader pointer.139std::mutex loaderLock;140141// Keep track of what we have, or what we're processing.142// These are protected by the mutex. While pendingFlags != 0, something is being loaded.143GameInfoFlags hasFlags{};144GameInfoFlags pendingFlags{};145146std::string id;147std::string id_version;148int disc_total = 0;149int disc_number = 0;150GameRegion region = GameRegion::UNKNOWN;151IdentifiedFileType fileType;152bool hasConfig = false;153154// Pre read the data, create a texture the next time155GameInfoTex icon;156GameInfoTex pic0;157GameInfoTex pic1;158159std::string sndFileData;160std::atomic<bool> sndDataLoaded{};161162double lastAccessedTime = 0.0;163164u64 gameSizeUncompressed = 0;165u64 gameSizeOnDisk = 0; // compressed size, in case of CSO166u64 saveDataSize = 0;167u64 installDataSize = 0;168169std::string errorString;170171protected:172ParamSFOData paramSFO;173// Note: this can change while loading, use GetTitle().174std::string title;175176// TODO: Get rid of this shared_ptr and managae lifetime better instead.177std::shared_ptr<FileLoader> fileLoader;178Path filePath_;179180void SetupTexture(Draw::DrawContext *draw, GameInfoTex &tex);181182private:183DISALLOW_COPY_AND_ASSIGN(GameInfo);184friend class GameInfoWorkItem;185};186187class GameInfoCache {188public:189GameInfoCache();190~GameInfoCache();191192// This creates a background worker thread!193void Clear();194void PurgeType(IdentifiedFileType fileType);195196// All data in GameInfo including icon.texture may be zero the first time you call this197// but filled in later asynchronously in the background. So keep calling this,198// redrawing the UI often. Only set flags to GAMEINFO_WANTBG or WANTSND if you really want them199// because they're big. bgTextures and sound may be discarded over time as well.200// NOTE: This never returns null, so you don't need to check for that. Do check Ready() flags though.201// It's OK to pass in nullptr for draw if you don't need the actual texture right now.202std::shared_ptr<GameInfo> GetInfo(Draw::DrawContext *draw, const Path &gamePath, GameInfoFlags wantFlags, GameInfoFlags *outHasFlags = nullptr);203void FlushBGs(); // Gets rid of all BG textures. Also gets rid of bg sounds.204205void CancelAll();206207private:208void Shutdown();209210// Maps ISO path to info. Need to use shared_ptr as we can return these pointers -211// and if they get destructed while being in use, that's bad.212std::map<std::string, std::shared_ptr<GameInfo> > info_;213std::mutex mapLock_;214};215216// This one can be global, no good reason not to.217extern GameInfoCache *g_gameInfoCache;218219220