mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Fix some longstanding issues with the GameInfoCache and optimize away double work
This commit is contained in:
parent
9b3c14a931
commit
884c366692
@ -47,6 +47,13 @@
|
|||||||
} \
|
} \
|
||||||
static inline bool operator &(const T &lhs, const T &rhs) { \
|
static inline bool operator &(const T &lhs, const T &rhs) { \
|
||||||
return ((int)lhs & (int)rhs) != 0; \
|
return ((int)lhs & (int)rhs) != 0; \
|
||||||
|
} \
|
||||||
|
static inline T &operator &= (T &lhs, const T &rhs) { \
|
||||||
|
lhs = (T)((int)lhs & (int)rhs); \
|
||||||
|
return lhs; \
|
||||||
|
} \
|
||||||
|
static inline T operator ~(const T &rhs) { \
|
||||||
|
return (T)(~((int)rhs)); \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ void WavData::Read(RIFFReader &file_) {
|
|||||||
numFrames = numBytes / raw_bytes_per_frame; // numFrames
|
numFrames = numBytes / raw_bytes_per_frame; // numFrames
|
||||||
|
|
||||||
// It seems the atrac3 codec likes to read a little bit outside.
|
// It seems the atrac3 codec likes to read a little bit outside.
|
||||||
int padding = 16;
|
const int padding = 32; // 32 is the value FFMPEG uses.
|
||||||
raw_data = (uint8_t *)malloc(numBytes + padding);
|
raw_data = (uint8_t *)malloc(numBytes + padding);
|
||||||
raw_data_size = numBytes;
|
raw_data_size = numBytes;
|
||||||
|
|
||||||
@ -359,8 +359,8 @@ void BackgroundAudio::Update() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Grab some audio from the current game and play it.
|
// Grab some audio from the current game and play it.
|
||||||
std::shared_ptr<GameInfo> gameInfo = g_gameInfoCache->GetInfo(nullptr, bgGamePath_, GAMEINFO_WANTSND);
|
std::shared_ptr<GameInfo> gameInfo = g_gameInfoCache->GetInfo(nullptr, bgGamePath_, GameInfoFlags::SND);
|
||||||
if (!gameInfo || gameInfo->pending) {
|
if (!gameInfo->Ready(GameInfoFlags::SND)) {
|
||||||
// Should try again shortly..
|
// Should try again shortly..
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,9 @@ CwCheatScreen::~CwCheatScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CwCheatScreen::TryLoadCheatInfo() {
|
bool CwCheatScreen::TryLoadCheatInfo() {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
std::string gameID;
|
std::string gameID;
|
||||||
if (info && info->paramSFOLoaded) {
|
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
gameID = info->paramSFO.GetValueString("DISC_ID");
|
gameID = info->paramSFO.GetValueString("DISC_ID");
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -269,8 +269,8 @@ void EmuScreen::bootGame(const Path &filename) {
|
|||||||
invalid_ = true;
|
invalid_ = true;
|
||||||
|
|
||||||
// We don't want to boot with the wrong game specific config, so wait until info is ready.
|
// We don't want to boot with the wrong game specific config, so wait until info is ready.
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, filename, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, filename, GameInfoFlags::PARAM_SFO);
|
||||||
if (!info || info->pending)
|
if (!info || info->Ready(GameInfoFlags::PARAM_SFO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto sc = GetI18NCategory(I18NCat::SCREEN);
|
auto sc = GetI18NCategory(I18NCat::SCREEN);
|
||||||
@ -952,11 +952,11 @@ public:
|
|||||||
|
|
||||||
void Draw(UIContext &dc) override {
|
void Draw(UIContext &dc) override {
|
||||||
// Should only be called when visible.
|
// Should only be called when visible.
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GAMEINFO_WANTBG);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::BG);
|
||||||
dc.Flush();
|
dc.Flush();
|
||||||
|
|
||||||
// PIC1 is the loading image, so let's only draw if it's available.
|
// PIC1 is the loading image, so let's only draw if it's available.
|
||||||
if (ginfo && ginfo->pic1.texture) {
|
if (ginfo && ginfo->Ready(GameInfoFlags::BG) && ginfo->pic1.texture) {
|
||||||
Draw::Texture *texture = ginfo->pic1.texture;
|
Draw::Texture *texture = ginfo->pic1.texture;
|
||||||
if (texture) {
|
if (texture) {
|
||||||
dc.GetDrawContext()->BindTexture(0, texture);
|
dc.GetDrawContext()->BindTexture(0, texture);
|
||||||
|
@ -54,8 +54,9 @@ void GameInfoTex::Clear() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GameInfo::GameInfo() : fileType(IdentifiedFileType::UNKNOWN) {
|
GameInfo::GameInfo() {
|
||||||
pending = true;
|
// here due to a forward decl.
|
||||||
|
fileType = IdentifiedFileType::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameInfo::~GameInfo() {
|
GameInfo::~GameInfo() {
|
||||||
@ -275,6 +276,7 @@ void GameInfo::DisposeFileLoader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GameInfo::DeleteAllSaveData() {
|
bool GameInfo::DeleteAllSaveData() {
|
||||||
|
_assert_(hasFlags & GameInfoFlags::PARAM_SFO); // so we know we have the ID.
|
||||||
std::vector<Path> saveDataDir = GetSaveDataDirectories();
|
std::vector<Path> saveDataDir = GetSaveDataDirectories();
|
||||||
for (size_t j = 0; j < saveDataDir.size(); j++) {
|
for (size_t j = 0; j < saveDataDir.size(); j++) {
|
||||||
std::vector<File::FileInfo> fileInfo;
|
std::vector<File::FileInfo> fileInfo;
|
||||||
@ -324,13 +326,15 @@ void GameInfo::ParseParamSFO() {
|
|||||||
region = GAMEREGION_CHINA;
|
region = GAMEREGION_CHINA;
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
paramSFOLoaded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameInfo::GetTitle() {
|
std::string GameInfo::GetTitle() {
|
||||||
std::lock_guard<std::mutex> guard(lock);
|
std::lock_guard<std::mutex> guard(lock);
|
||||||
return title;
|
if (hasFlags & GameInfoFlags::PARAM_SFO) {
|
||||||
|
return title;
|
||||||
|
} else {
|
||||||
|
return filePath_.GetFilename();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInfo::SetTitle(const std::string &newTitle) {
|
void GameInfo::SetTitle(const std::string &newTitle) {
|
||||||
@ -352,21 +356,13 @@ void GameInfo::FinishPendingTextureLoads(Draw::DrawContext *draw) {
|
|||||||
|
|
||||||
void GameInfo::SetupTexture(Draw::DrawContext *thin3d, GameInfoTex &tex) {
|
void GameInfo::SetupTexture(Draw::DrawContext *thin3d, GameInfoTex &tex) {
|
||||||
using namespace Draw;
|
using namespace Draw;
|
||||||
if (tex.data.size()) {
|
// TODO: Use TempImage to semi-load the image in the worker task, then here we
|
||||||
if (!tex.texture) {
|
// could just call CreateTextureFromTempImage.
|
||||||
// TODO: Use TempImage to semi-load the image in the worker task, then here we
|
tex.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)tex.data.data(), (int)tex.data.size(), ImageFileType::DETECT, false, GetTitle().c_str());
|
||||||
// could just call CreateTextureFromTempImage.
|
if (tex.texture) {
|
||||||
tex.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)tex.data.data(), (int)tex.data.size(), ImageFileType::DETECT, false, GetTitle().c_str());
|
tex.timeLoaded = time_now_d();
|
||||||
if (tex.texture) {
|
} else {
|
||||||
tex.timeLoaded = time_now_d();
|
ERROR_LOG(G3D, "Failed creating texture (%s) from %d-byte file", GetTitle().c_str(), (int)tex.data.size());
|
||||||
} else {
|
|
||||||
ERROR_LOG(G3D, "Failed creating texture (%s) from %d-byte file", GetTitle().c_str(), (int)tex.data.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((wantFlags & GAMEINFO_WANTBGDATA) == 0) {
|
|
||||||
tex.data.clear();
|
|
||||||
tex.dataLoaded = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,15 +430,11 @@ static bool ReadVFSToString(const char *filename, std::string *contents, std::mu
|
|||||||
|
|
||||||
class GameInfoWorkItem : public Task {
|
class GameInfoWorkItem : public Task {
|
||||||
public:
|
public:
|
||||||
GameInfoWorkItem(const Path &gamePath, std::shared_ptr<GameInfo> &info)
|
GameInfoWorkItem(const Path &gamePath, std::shared_ptr<GameInfo> &info, GameInfoFlags flags)
|
||||||
: gamePath_(gamePath), info_(info) {
|
: gamePath_(gamePath), info_(info), flags_(flags) {}
|
||||||
}
|
|
||||||
|
|
||||||
~GameInfoWorkItem() {
|
~GameInfoWorkItem() {
|
||||||
info_->pending.store(false);
|
|
||||||
info_->working.store(false);
|
|
||||||
info_->DisposeFileLoader();
|
info_->DisposeFileLoader();
|
||||||
info_->readyEvent.Notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskType Type() const override {
|
TaskType Type() const override {
|
||||||
@ -475,8 +467,11 @@ public:
|
|||||||
|
|
||||||
std::string errorString;
|
std::string errorString;
|
||||||
|
|
||||||
info_->working = true;
|
if (flags_ & GameInfoFlags::FILE_TYPE) {
|
||||||
info_->fileType = Identify_File(info_->GetFileLoader().get(), &errorString);
|
info_->fileType = Identify_File(info_->GetFileLoader().get(), &errorString);
|
||||||
|
info_->hasConfig = g_Config.hasGameConfig(info_->id);
|
||||||
|
}
|
||||||
|
|
||||||
switch (info_->fileType) {
|
switch (info_->fileType) {
|
||||||
case IdentifiedFileType::PSP_PBP:
|
case IdentifiedFileType::PSP_PBP:
|
||||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||||
@ -499,41 +494,45 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// First, PARAM.SFO.
|
// First, PARAM.SFO.
|
||||||
std::vector<u8> sfoData;
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) {
|
std::vector<u8> sfoData;
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) {
|
||||||
info_->paramSFO.ReadSFO(sfoData);
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
info_->ParseParamSFO();
|
info_->paramSFO.ReadSFO(sfoData);
|
||||||
|
info_->ParseParamSFO();
|
||||||
|
|
||||||
// Assuming PSP_PBP_DIRECTORY without ID or with disc_total < 1 in GAME dir must be homebrew
|
// Assuming PSP_PBP_DIRECTORY without ID or with disc_total < 1 in GAME dir must be homebrew
|
||||||
if ((info_->id.empty() || !info_->disc_total)
|
if ((info_->id.empty() || !info_->disc_total)
|
||||||
&& gamePath_.FilePathContainsNoCase("PSP/GAME/")
|
&& gamePath_.FilePathContainsNoCase("PSP/GAME/")
|
||||||
&& info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) {
|
&& info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) {
|
||||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||||
info_->id_version = info_->id + "_1.00";
|
info_->id_version = info_->id + "_1.00";
|
||||||
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, ICON0.PNG.
|
// Then, ICON0.PNG.
|
||||||
if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
||||||
pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data);
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
} else {
|
pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data);
|
||||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
} else {
|
||||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||||
// Try using png/jpg screenshots first
|
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||||
if (File::Exists(screenshot_png))
|
// Try using png/jpg screenshots first
|
||||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
if (File::Exists(screenshot_png))
|
||||||
else if (File::Exists(screenshot_jpg))
|
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||||
ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
else if (File::Exists(screenshot_jpg))
|
||||||
else
|
ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||||
// Read standard icon
|
else
|
||||||
ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
// Read standard icon
|
||||||
|
ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||||
|
}
|
||||||
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
info_->icon.dataLoaded = true;
|
|
||||||
|
|
||||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
if (flags_ & GameInfoFlags::BG) {
|
||||||
if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) {
|
if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) {
|
||||||
std::string data;
|
std::string data;
|
||||||
pbp.GetSubFileAsString(PBP_PIC0_PNG, &data);
|
pbp.GetSubFileAsString(PBP_PIC0_PNG, &data);
|
||||||
@ -549,7 +548,7 @@ public:
|
|||||||
info_->pic1.dataLoaded = true;
|
info_->pic1.dataLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
if (flags_ & GameInfoFlags::SND) {
|
||||||
if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) {
|
if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) {
|
||||||
std::string data;
|
std::string data;
|
||||||
pbp.GetSubFileAsString(PBP_SND0_AT3, &data);
|
pbp.GetSubFileAsString(PBP_SND0_AT3, &data);
|
||||||
@ -564,17 +563,17 @@ public:
|
|||||||
case IdentifiedFileType::PSP_ELF:
|
case IdentifiedFileType::PSP_ELF:
|
||||||
handleELF:
|
handleELF:
|
||||||
// An elf on its own has no usable information, no icons, no nothing.
|
// An elf on its own has no usable information, no icons, no nothing.
|
||||||
{
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
|
||||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||||
info_->id_version = info_->id + "_1.00";
|
info_->id_version = info_->id + "_1.00";
|
||||||
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
||||||
|
|
||||||
info_->paramSFOLoaded = true;
|
|
||||||
}
|
}
|
||||||
{
|
|
||||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
std::string id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||||
|
// Due to the dependency of the BASIC info, we fetch it already here.
|
||||||
|
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (id + "_00000.jpg");
|
||||||
|
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (id + "_00000.png");
|
||||||
// Try using png/jpg screenshots first
|
// Try using png/jpg screenshots first
|
||||||
if (File::Exists(screenshot_png)) {
|
if (File::Exists(screenshot_png)) {
|
||||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||||
@ -594,17 +593,20 @@ handleELF:
|
|||||||
SequentialHandleAllocator handles;
|
SequentialHandleAllocator handles;
|
||||||
VirtualDiscFileSystem umd(&handles, gamePath_);
|
VirtualDiscFileSystem umd(&handles, gamePath_);
|
||||||
|
|
||||||
// Alright, let's fetch the PARAM.SFO.
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
std::string paramSFOcontents;
|
// Alright, let's fetch the PARAM.SFO.
|
||||||
if (ReadFileToString(&umd, "/PARAM.SFO", ¶mSFOcontents, 0)) {
|
std::string paramSFOcontents;
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
if (ReadFileToString(&umd, "/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
info_->ParseParamSFO();
|
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||||
|
info_->ParseParamSFO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock);
|
ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = true;
|
info_->icon.dataLoaded = true;
|
||||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
}
|
||||||
|
if (flags_ & GameInfoFlags::BG) {
|
||||||
ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
||||||
info_->pic1.dataLoaded = true;
|
info_->pic1.dataLoaded = true;
|
||||||
}
|
}
|
||||||
@ -613,34 +615,30 @@ handleELF:
|
|||||||
|
|
||||||
case IdentifiedFileType::PPSSPP_SAVESTATE:
|
case IdentifiedFileType::PPSSPP_SAVESTATE:
|
||||||
{
|
{
|
||||||
Path screenshotPath;
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
{
|
|
||||||
info_->SetTitle(SaveState::GetTitle(gamePath_));
|
info_->SetTitle(SaveState::GetTitle(gamePath_));
|
||||||
std::lock_guard<std::mutex> guard(info_->lock);
|
|
||||||
screenshotPath = gamePath_.WithReplacedExtension(".ppst", ".jpg");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's use the screenshot as an icon, too.
|
// Let's use the screenshot as an icon, too.
|
||||||
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
info_->icon.dataLoaded = true;
|
Path screenshotPath = gamePath_.WithReplacedExtension(".ppst", ".jpg");
|
||||||
} else {
|
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
||||||
ERROR_LOG(G3D, "Error loading screenshot data: '%s'", screenshotPath.c_str());
|
info_->icon.dataLoaded = true;
|
||||||
|
} else {
|
||||||
|
ERROR_LOG(G3D, "Error loading screenshot data: '%s'", screenshotPath.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
||||||
{
|
{
|
||||||
Path screenshotPath;
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
|
Path screenshotPath = gamePath_.WithReplacedExtension(".ppdmp", ".png");
|
||||||
{
|
// Let's use the comparison screenshot as an icon, if it exists.
|
||||||
std::lock_guard<std::mutex> guard(info_->lock);
|
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
||||||
screenshotPath = gamePath_.WithReplacedExtension(".ppdmp", ".png");
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's use the comparison screenshot as an icon, if it exists.
|
|
||||||
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
|
||||||
info_->icon.dataLoaded = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -651,22 +649,24 @@ handleELF:
|
|||||||
VirtualDiscFileSystem umd(&handles, gamePath_);
|
VirtualDiscFileSystem umd(&handles, gamePath_);
|
||||||
|
|
||||||
// Alright, let's fetch the PARAM.SFO.
|
// Alright, let's fetch the PARAM.SFO.
|
||||||
std::string paramSFOcontents;
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) {
|
std::string paramSFOcontents;
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
info_->ParseParamSFO();
|
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||||
|
info_->ParseParamSFO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock);
|
ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = true;
|
info_->icon.dataLoaded = true;
|
||||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
if (flags_ & GameInfoFlags::BG) {
|
||||||
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
|
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
|
||||||
info_->pic0.dataLoaded = true;
|
info_->pic0.dataLoaded = true;
|
||||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
||||||
info_->pic1.dataLoaded = true;
|
info_->pic1.dataLoaded = true;
|
||||||
}
|
}
|
||||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
if (flags_ & GameInfoFlags::SND) {
|
||||||
ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
||||||
info_->pic1.dataLoaded = true;
|
info_->pic1.dataLoaded = true;
|
||||||
}
|
}
|
||||||
@ -691,60 +691,63 @@ handleELF:
|
|||||||
ISOFileSystem umd(&handles, bd);
|
ISOFileSystem umd(&handles, bd);
|
||||||
|
|
||||||
// Alright, let's fetch the PARAM.SFO.
|
// Alright, let's fetch the PARAM.SFO.
|
||||||
std::string paramSFOcontents;
|
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||||
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, nullptr)) {
|
std::string paramSFOcontents;
|
||||||
{
|
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, nullptr)) {
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
{
|
||||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
info_->ParseParamSFO();
|
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||||
}
|
info_->ParseParamSFO();
|
||||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
}
|
||||||
info_->pic0.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
|
|
||||||
info_->pic1.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
|
||||||
}
|
|
||||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
|
||||||
info_->sndDataLoaded = ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags_ & GameInfoFlags::BG) {
|
||||||
|
info_->pic0.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
|
||||||
|
info_->pic1.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags_ & GameInfoFlags::SND) {
|
||||||
|
info_->sndDataLoaded = ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
||||||
|
}
|
||||||
|
|
||||||
// Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though
|
// Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though
|
||||||
if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
||||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||||
// Try using png/jpg screenshots first
|
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||||
if (File::Exists(screenshot_png))
|
// Try using png/jpg screenshots first
|
||||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
if (File::Exists(screenshot_png))
|
||||||
else if (File::Exists(screenshot_jpg))
|
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
else if (File::Exists(screenshot_jpg))
|
||||||
else {
|
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||||
DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found");
|
else {
|
||||||
info_->icon.dataLoaded = ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found");
|
||||||
|
info_->icon.dataLoaded = ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
info_->icon.dataLoaded = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IdentifiedFileType::ARCHIVE_ZIP:
|
case IdentifiedFileType::ARCHIVE_ZIP:
|
||||||
info_->paramSFOLoaded = true;
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
{
|
|
||||||
ReadVFSToString("zip.png", &info_->icon.data, &info_->lock);
|
ReadVFSToString("zip.png", &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = true;
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IdentifiedFileType::ARCHIVE_RAR:
|
case IdentifiedFileType::ARCHIVE_RAR:
|
||||||
info_->paramSFOLoaded = true;
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
{
|
|
||||||
ReadVFSToString("rargray.png", &info_->icon.data, &info_->lock);
|
ReadVFSToString("rargray.png", &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = true;
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IdentifiedFileType::ARCHIVE_7Z:
|
case IdentifiedFileType::ARCHIVE_7Z:
|
||||||
info_->paramSFOLoaded = true;
|
if (flags_ & GameInfoFlags::ICON) {
|
||||||
{
|
|
||||||
ReadVFSToString("7z.png", &info_->icon.data, &info_->lock);
|
ReadVFSToString("7z.png", &info_->icon.data, &info_->lock);
|
||||||
info_->icon.dataLoaded = true;
|
info_->icon.dataLoaded = true;
|
||||||
}
|
}
|
||||||
@ -752,28 +755,31 @@ handleELF:
|
|||||||
|
|
||||||
case IdentifiedFileType::NORMAL_DIRECTORY:
|
case IdentifiedFileType::NORMAL_DIRECTORY:
|
||||||
default:
|
default:
|
||||||
info_->paramSFOLoaded = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
info_->hasConfig = g_Config.hasGameConfig(info_->id);
|
if (flags_ & GameInfoFlags::SIZE) {
|
||||||
|
|
||||||
if (info_->wantFlags & GAMEINFO_WANTSIZE) {
|
|
||||||
std::lock_guard<std::mutex> lock(info_->lock);
|
std::lock_guard<std::mutex> lock(info_->lock);
|
||||||
info_->gameSizeOnDisk = info_->GetGameSizeOnDiskInBytes();
|
info_->gameSizeOnDisk = info_->GetGameSizeOnDiskInBytes();
|
||||||
info_->saveDataSize = info_->GetSaveDataSizeInBytes();
|
info_->saveDataSize = info_->GetSaveDataSizeInBytes();
|
||||||
info_->installDataSize = info_->GetInstallDataSizeInBytes();
|
info_->installDataSize = info_->GetInstallDataSizeInBytes();
|
||||||
}
|
}
|
||||||
if (info_->wantFlags & GAMEINFO_WANTUNCOMPRESSEDSIZE) {
|
if (flags_ & GameInfoFlags::UNCOMPRESSED_SIZE) {
|
||||||
info_->gameSizeUncompressed = info_->GetGameSizeUncompressedInBytes();
|
info_->gameSizeUncompressed = info_->GetGameSizeUncompressedInBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time to update the flags.
|
||||||
|
std::unique_lock<std::mutex> lock(info_->lock);
|
||||||
|
info_->hasFlags |= flags_;
|
||||||
|
info_->pendingFlags &= ~flags_;
|
||||||
// INFO_LOG(SYSTEM, "Completed writing info for %s", info_->GetTitle().c_str());
|
// INFO_LOG(SYSTEM, "Completed writing info for %s", info_->GetTitle().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Path gamePath_;
|
Path gamePath_;
|
||||||
std::shared_ptr<GameInfo> info_;
|
std::shared_ptr<GameInfo> info_;
|
||||||
|
GameInfoFlags flags_{};
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(GameInfoWorkItem);
|
DISALLOW_COPY_AND_ASSIGN(GameInfoWorkItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -820,14 +826,18 @@ void GameInfoCache::FlushBGs() {
|
|||||||
iter->second->sndFileData.clear();
|
iter->second->sndFileData.clear();
|
||||||
iter->second->sndDataLoaded = false;
|
iter->second->sndDataLoaded = false;
|
||||||
}
|
}
|
||||||
iter->second->wantFlags &= ~(GAMEINFO_WANTBG | GAMEINFO_WANTSND | GAMEINFO_WANTBGDATA);
|
iter->second->hasFlags &= ~(GameInfoFlags::BG | GameInfoFlags::SND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
|
void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
|
||||||
for (auto iter = info_.begin(); iter != info_.end();) {
|
for (auto iter = info_.begin(); iter != info_.end();) {
|
||||||
auto &info = iter->second;
|
auto &info = iter->second;
|
||||||
info->readyEvent.Wait();
|
|
||||||
|
// TODO: Find a better way to wait here.
|
||||||
|
while (info->pendingFlags != (GameInfoFlags)0) {
|
||||||
|
sleep_ms(1);
|
||||||
|
}
|
||||||
if (info->fileType == fileType) {
|
if (info->fileType == fileType) {
|
||||||
iter = info_.erase(iter);
|
iter = info_.erase(iter);
|
||||||
} else {
|
} else {
|
||||||
@ -836,51 +846,48 @@ void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInfoCache::WaitUntilDone(std::shared_ptr<GameInfo> &info) {
|
// Call on the main thread ONLY - that is from stuff called from NativeFrame.
|
||||||
info->readyEvent.Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs on the main thread. Only call from render() and similar, not update()!
|
|
||||||
// Can also be called from the audio thread for menu background music, but that cannot request images!
|
// Can also be called from the audio thread for menu background music, but that cannot request images!
|
||||||
std::shared_ptr<GameInfo> GameInfoCache::GetInfo(Draw::DrawContext *draw, const Path &gamePath, int wantFlags) {
|
std::shared_ptr<GameInfo> GameInfoCache::GetInfo(Draw::DrawContext *draw, const Path &gamePath, GameInfoFlags wantFlags) {
|
||||||
std::shared_ptr<GameInfo> info;
|
|
||||||
|
|
||||||
const std::string &pathStr = gamePath.ToString();
|
const std::string &pathStr = gamePath.ToString();
|
||||||
|
|
||||||
|
// This is always needed to determine the method to get the other info, so make sure it's computed first.
|
||||||
|
wantFlags |= GameInfoFlags::FILE_TYPE;
|
||||||
|
|
||||||
|
mapLock_.lock();
|
||||||
|
|
||||||
auto iter = info_.find(pathStr);
|
auto iter = info_.find(pathStr);
|
||||||
if (iter != info_.end()) {
|
if (iter != info_.end()) {
|
||||||
info = iter->second;
|
// There's already a structure about this game. Let's check.
|
||||||
}
|
std::shared_ptr<GameInfo> info = iter->second;
|
||||||
|
mapLock_.unlock();
|
||||||
|
|
||||||
// If wantFlags don't match, we need to start over. We'll just queue the work item again.
|
|
||||||
if (info && (info->wantFlags & wantFlags) == wantFlags) {
|
|
||||||
info->FinishPendingTextureLoads(draw);
|
info->FinishPendingTextureLoads(draw);
|
||||||
info->lastAccessedTime = time_now_d();
|
info->lastAccessedTime = time_now_d();
|
||||||
|
GameInfoFlags wanted = (GameInfoFlags)0;
|
||||||
|
{
|
||||||
|
// Careful now!
|
||||||
|
std::unique_lock<std::mutex> lock(info->lock);
|
||||||
|
GameInfoFlags hasFlags = info->hasFlags | info->pendingFlags; // We don't want to re-fetch data that we have, so or in pendingFlags.
|
||||||
|
wanted = (GameInfoFlags)((int)wantFlags & ~(int)hasFlags); // & is reserved for testing. ugh.
|
||||||
|
info->pendingFlags |= wanted;
|
||||||
|
}
|
||||||
|
if (wanted != (GameInfoFlags)0) {
|
||||||
|
// We're missing info that we want. Go get it!
|
||||||
|
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info, wanted);
|
||||||
|
g_threadManager.EnqueueTask(item);
|
||||||
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info) {
|
std::shared_ptr<GameInfo> info = std::make_shared<GameInfo>();
|
||||||
info = std::make_shared<GameInfo>();
|
info->pendingFlags = wantFlags;
|
||||||
}
|
info->lastAccessedTime = time_now_d();
|
||||||
|
info_.insert(std::make_pair(pathStr, info));
|
||||||
|
mapLock_.unlock();
|
||||||
|
|
||||||
if (info->working) {
|
// Just get all the stuff we wanted.
|
||||||
// Uh oh, it's currently in process. It could mark pending = false with the wrong wantFlags.
|
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info, wantFlags);
|
||||||
// Let's wait it out, then queue.
|
|
||||||
// NOTE: This is bad because we're likely on the UI thread....
|
|
||||||
WaitUntilDone(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(info->lock);
|
|
||||||
info->wantFlags |= wantFlags;
|
|
||||||
info->pending = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info);
|
|
||||||
g_threadManager.EnqueueTask(item);
|
g_threadManager.EnqueueTask(item);
|
||||||
|
|
||||||
// Don't re-insert if we already have it.
|
|
||||||
if (info_.find(pathStr) == info_.end())
|
|
||||||
info_[pathStr] = info;
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -50,13 +50,16 @@ enum GameRegion {
|
|||||||
GAMEREGION_MAX,
|
GAMEREGION_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GameInfoWantFlags {
|
enum class GameInfoFlags {
|
||||||
GAMEINFO_WANTBG = 0x01,
|
FILE_TYPE = 0x01, // Don't need to specify this, always included.
|
||||||
GAMEINFO_WANTSIZE = 0x02,
|
PARAM_SFO = 0x02,
|
||||||
GAMEINFO_WANTSND = 0x04,
|
ICON = 0x04,
|
||||||
GAMEINFO_WANTBGDATA = 0x08, // Use with WANTBG.
|
BG = 0x08,
|
||||||
GAMEINFO_WANTUNCOMPRESSEDSIZE = 0x10,
|
SND = 0x10,
|
||||||
|
SIZE = 0x20,
|
||||||
|
UNCOMPRESSED_SIZE = 0x40,
|
||||||
};
|
};
|
||||||
|
ENUM_CLASS_BITOPS(GameInfoFlags);
|
||||||
|
|
||||||
class FileLoader;
|
class FileLoader;
|
||||||
enum class IdentifiedFileType;
|
enum class IdentifiedFileType;
|
||||||
@ -102,6 +105,11 @@ public:
|
|||||||
std::string GetTitle();
|
std::string GetTitle();
|
||||||
void SetTitle(const std::string &newTitle);
|
void SetTitle(const std::string &newTitle);
|
||||||
|
|
||||||
|
bool Ready(GameInfoFlags flags) {
|
||||||
|
std::unique_lock<std::mutex> guard(lock);
|
||||||
|
return (hasFlags & flags) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
GameInfoTex *GetBGPic() {
|
GameInfoTex *GetBGPic() {
|
||||||
if (pic1.texture)
|
if (pic1.texture)
|
||||||
return &pic1;
|
return &pic1;
|
||||||
@ -119,6 +127,11 @@ public:
|
|||||||
// Controls access to the fileLoader pointer.
|
// Controls access to the fileLoader pointer.
|
||||||
std::mutex loaderLock;
|
std::mutex loaderLock;
|
||||||
|
|
||||||
|
// Keep track of what we have, or what we're processing.
|
||||||
|
// These are protected by the mutex. While pendingFlags != 0, something is being loaded.
|
||||||
|
GameInfoFlags hasFlags{};
|
||||||
|
GameInfoFlags pendingFlags{};
|
||||||
|
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string id_version;
|
std::string id_version;
|
||||||
int disc_total = 0;
|
int disc_total = 0;
|
||||||
@ -126,7 +139,6 @@ public:
|
|||||||
int region = -1;
|
int region = -1;
|
||||||
IdentifiedFileType fileType;
|
IdentifiedFileType fileType;
|
||||||
ParamSFOData paramSFO;
|
ParamSFOData paramSFO;
|
||||||
bool paramSFOLoaded = false;
|
|
||||||
bool hasConfig = false;
|
bool hasConfig = false;
|
||||||
|
|
||||||
// Pre read the data, create a texture the next time (GL thread..)
|
// Pre read the data, create a texture the next time (GL thread..)
|
||||||
@ -137,8 +149,6 @@ public:
|
|||||||
std::string sndFileData;
|
std::string sndFileData;
|
||||||
std::atomic<bool> sndDataLoaded{};
|
std::atomic<bool> sndDataLoaded{};
|
||||||
|
|
||||||
int wantFlags = 0;
|
|
||||||
|
|
||||||
double lastAccessedTime = 0.0;
|
double lastAccessedTime = 0.0;
|
||||||
|
|
||||||
u64 gameSizeUncompressed = 0;
|
u64 gameSizeUncompressed = 0;
|
||||||
@ -146,11 +156,6 @@ public:
|
|||||||
u64 saveDataSize = 0;
|
u64 saveDataSize = 0;
|
||||||
u64 installDataSize = 0;
|
u64 installDataSize = 0;
|
||||||
|
|
||||||
std::atomic<bool> pending{};
|
|
||||||
std::atomic<bool> working{};
|
|
||||||
|
|
||||||
Event readyEvent;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Note: this can change while loading, use GetTitle().
|
// Note: this can change while loading, use GetTitle().
|
||||||
std::string title;
|
std::string title;
|
||||||
@ -178,7 +183,7 @@ public:
|
|||||||
// but filled in later asynchronously in the background. So keep calling this,
|
// but filled in later asynchronously in the background. So keep calling this,
|
||||||
// redrawing the UI often. Only set flags to GAMEINFO_WANTBG or WANTSND if you really want them
|
// redrawing the UI often. Only set flags to GAMEINFO_WANTBG or WANTSND if you really want them
|
||||||
// because they're big. bgTextures and sound may be discarded over time as well.
|
// because they're big. bgTextures and sound may be discarded over time as well.
|
||||||
std::shared_ptr<GameInfo> GetInfo(Draw::DrawContext *draw, const Path &gamePath, int wantFlags);
|
std::shared_ptr<GameInfo> GetInfo(Draw::DrawContext *draw, const Path &gamePath, GameInfoFlags wantFlags);
|
||||||
void FlushBGs(); // Gets rid of all BG textures. Also gets rid of bg sounds.
|
void FlushBGs(); // Gets rid of all BG textures. Also gets rid of bg sounds.
|
||||||
|
|
||||||
void CancelAll();
|
void CancelAll();
|
||||||
@ -191,6 +196,7 @@ private:
|
|||||||
// Maps ISO path to info. Need to use shared_ptr as we can return these pointers -
|
// Maps ISO path to info. Need to use shared_ptr as we can return these pointers -
|
||||||
// and if they get destructed while being in use, that's bad.
|
// and if they get destructed while being in use, that's bad.
|
||||||
std::map<std::string, std::shared_ptr<GameInfo> > info_;
|
std::map<std::string, std::shared_ptr<GameInfo> > info_;
|
||||||
|
std::mutex mapLock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This one can be global, no good reason not to.
|
// This one can be global, no good reason not to.
|
||||||
|
@ -86,7 +86,7 @@ void GameScreen::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameScreen::CreateViews() {
|
void GameScreen::CreateViews() {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::BG);
|
||||||
|
|
||||||
if (info && !info->id.empty()) {
|
if (info && !info->id.empty()) {
|
||||||
saveDirs = info->GetSaveDataDirectories(); // Get's very heavy, let's not do it in update()
|
saveDirs = info->GetSaveDataDirectories(); // Get's very heavy, let's not do it in update()
|
||||||
@ -187,8 +187,9 @@ void GameScreen::CreateViews() {
|
|||||||
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Delete Game"))))->OnClick.Handle(this, &GameScreen::OnDeleteGame);
|
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Delete Game"))))->OnClick.Handle(this, &GameScreen::OnDeleteGame);
|
||||||
if (System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) {
|
if (System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) {
|
||||||
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Add([=](UI::EventParams &e) {
|
rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Add([=](UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (info) {
|
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
|
// TODO: Should we block on Ready?
|
||||||
System_CreateGameShortcut(gamePath_, info->GetTitle());
|
System_CreateGameShortcut(gamePath_, info->GetTitle());
|
||||||
}
|
}
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
@ -241,8 +242,8 @@ UI::Choice *GameScreen::AddOtherChoice(UI::Choice *choice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) {
|
UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (!info) {
|
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
return UI::EVENT_SKIPPED;
|
return UI::EVENT_SKIPPED;
|
||||||
}
|
}
|
||||||
g_Config.createGameConfig(info->id);
|
g_Config.createGameConfig(info->id);
|
||||||
@ -255,8 +256,8 @@ UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) {
|
|||||||
|
|
||||||
void GameScreen::CallbackDeleteConfig(bool yes) {
|
void GameScreen::CallbackDeleteConfig(bool yes) {
|
||||||
if (yes) {
|
if (yes) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (!info) {
|
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
g_Config.deleteGameConfig(info->id);
|
g_Config.deleteGameConfig(info->id);
|
||||||
@ -283,7 +284,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
|
|||||||
|
|
||||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||||
|
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(draw, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE | GAMEINFO_WANTUNCOMPRESSEDSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(draw, gamePath_, GameInfoFlags::BG | GameInfoFlags::SIZE | GameInfoFlags::UNCOMPRESSED_SIZE);
|
||||||
|
|
||||||
if (tvTitle_) {
|
if (tvTitle_) {
|
||||||
tvTitle_->SetText(info->GetTitle());
|
tvTitle_->SetText(info->GetTitle());
|
||||||
@ -410,7 +411,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info->pending) {
|
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
// At this point, the above buttons won't become visible. We can show these now.
|
// At this point, the above buttons won't become visible. We can show these now.
|
||||||
for (UI::Choice *choice : otherChoices_) {
|
for (UI::Choice *choice : otherChoices_) {
|
||||||
choice->SetVisibility(UI::V_VISIBLE);
|
choice->SetVisibility(UI::V_VISIBLE);
|
||||||
@ -448,8 +449,8 @@ UI::EventReturn GameScreen::OnPlay(UI::EventParams &e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (info && info->paramSFOLoaded) {
|
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
std::string discID = info->paramSFO.GetValueString("DISC_ID");
|
std::string discID = info->paramSFO.GetValueString("DISC_ID");
|
||||||
if ((discID.empty() || !info->disc_total) && gamePath_.FilePathContainsNoCase("PSP/GAME/"))
|
if ((discID.empty() || !info->disc_total) && gamePath_.FilePathContainsNoCase("PSP/GAME/"))
|
||||||
discID = g_paramSFO.GenerateFakeID(gamePath_);
|
discID = g_paramSFO.GenerateFakeID(gamePath_);
|
||||||
@ -459,7 +460,7 @@ UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (info) {
|
if (info) {
|
||||||
// Check that there's any savedata to delete
|
// Check that there's any savedata to delete
|
||||||
if (saveDirs.size()) {
|
if (saveDirs.size()) {
|
||||||
@ -470,14 +471,13 @@ UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
|||||||
std::bind(&GameScreen::CallbackDeleteSaveData, this, std::placeholders::_1)));
|
std::bind(&GameScreen::CallbackDeleteSaveData, this, std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RecreateViews();
|
RecreateViews();
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameScreen::CallbackDeleteSaveData(bool yes) {
|
void GameScreen::CallbackDeleteSaveData(bool yes) {
|
||||||
if (yes) {
|
if (yes) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
info->DeleteAllSaveData();
|
info->DeleteAllSaveData();
|
||||||
info->saveDataSize = 0;
|
info->saveDataSize = 0;
|
||||||
info->installDataSize = 0;
|
info->installDataSize = 0;
|
||||||
@ -485,21 +485,20 @@ void GameScreen::CallbackDeleteSaveData(bool yes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
|
UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (info) {
|
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||||
auto ga = GetI18NCategory(I18NCat::GAME);
|
auto ga = GetI18NCategory(I18NCat::GAME);
|
||||||
screenManager()->push(
|
screenManager()->push(
|
||||||
new PromptScreen(gamePath_, di->T("DeleteConfirmGame", "Do you really want to delete this game\nfrom your device? You can't undo this."), ga->T("ConfirmDelete"), di->T("Cancel"),
|
new PromptScreen(gamePath_, di->T("DeleteConfirmGame", "Do you really want to delete this game\nfrom your device? You can't undo this."), ga->T("ConfirmDelete"), di->T("Cancel"),
|
||||||
std::bind(&GameScreen::CallbackDeleteGame, this, std::placeholders::_1)));
|
std::bind(&GameScreen::CallbackDeleteGame, this, std::placeholders::_1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameScreen::CallbackDeleteGame(bool yes) {
|
void GameScreen::CallbackDeleteGame(bool yes) {
|
||||||
if (yes) {
|
if (yes) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
info->Delete();
|
info->Delete();
|
||||||
g_gameInfoCache->Clear();
|
g_gameInfoCache->Clear();
|
||||||
screenManager()->switchScreen(new MainScreen());
|
screenManager()->switchScreen(new MainScreen());
|
||||||
@ -560,8 +559,8 @@ void SetBackgroundPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
|||||||
void SetBackgroundPopupScreen::update() {
|
void SetBackgroundPopupScreen::update() {
|
||||||
PopupScreen::update();
|
PopupScreen::update();
|
||||||
|
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTBGDATA);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::BG);
|
||||||
if (status_ == Status::PENDING && info && !info->pending) {
|
if (status_ == Status::PENDING && info && info->Ready(GameInfoFlags::BG)) {
|
||||||
GameInfoTex *pic = nullptr;
|
GameInfoTex *pic = nullptr;
|
||||||
if (info->pic1.dataLoaded && info->pic1.data.size()) {
|
if (info->pic1.dataLoaded && info->pic1.data.size()) {
|
||||||
pic = &info->pic1;
|
pic = &info->pic1;
|
||||||
|
@ -221,7 +221,7 @@ void GameSettingsScreen::PreCreateViews() {
|
|||||||
ReloadAllThemeInfo();
|
ReloadAllThemeInfo();
|
||||||
|
|
||||||
if (editThenRestore_) {
|
if (editThenRestore_) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
g_Config.loadGameConfig(gameID_, info->GetTitle());
|
g_Config.loadGameConfig(gameID_, info->GetTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1454,7 +1454,7 @@ void GameSettingsScreen::onFinish(DialogResult result) {
|
|||||||
|
|
||||||
if (editThenRestore_) {
|
if (editThenRestore_) {
|
||||||
// In case we didn't have the title yet before, try again.
|
// In case we didn't have the title yet before, try again.
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
g_Config.changeGameSpecific(gameID_, info->GetTitle());
|
g_Config.changeGameSpecific(gameID_, info->GetTitle());
|
||||||
g_Config.unloadGameConfig();
|
g_Config.unloadGameConfig();
|
||||||
}
|
}
|
||||||
|
@ -226,12 +226,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void GameButton::Draw(UIContext &dc) {
|
void GameButton::Draw(UIContext &dc) {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, 0);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON);
|
||||||
Draw::Texture *texture = 0;
|
Draw::Texture *texture = 0;
|
||||||
u32 color = 0, shadowColor = 0;
|
u32 color = 0, shadowColor = 0;
|
||||||
using namespace UI;
|
using namespace UI;
|
||||||
|
|
||||||
if (ginfo->icon.texture) {
|
if (ginfo->Ready(GameInfoFlags::ICON) && ginfo->icon.texture) {
|
||||||
texture = ginfo->icon.texture;
|
texture = ginfo->icon.texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,10 +427,9 @@ void GameButton::Draw(UIContext &dc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GameButton::DescribeText() const {
|
std::string GameButton::DescribeText() const {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (ginfo->pending)
|
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO))
|
||||||
return "...";
|
return "...";
|
||||||
|
|
||||||
auto u = GetI18NCategory(I18NCat::UI_ELEMENTS);
|
auto u = GetI18NCategory(I18NCat::UI_ELEMENTS);
|
||||||
return ApplySafeSubstitutions(u->T("%1 button"), ginfo->GetTitle());
|
return ApplySafeSubstitutions(u->T("%1 button"), ginfo->GetTitle());
|
||||||
}
|
}
|
||||||
@ -1443,12 +1442,12 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float pr
|
|||||||
|
|
||||||
std::shared_ptr<GameInfo> ginfo;
|
std::shared_ptr<GameInfo> ginfo;
|
||||||
if (!gamePath.empty()) {
|
if (!gamePath.empty()) {
|
||||||
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GAMEINFO_WANTBG);
|
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GameInfoFlags::BG);
|
||||||
// Loading texture data may bind a texture.
|
// Loading texture data may bind a texture.
|
||||||
dc.RebindTexture();
|
dc.RebindTexture();
|
||||||
|
|
||||||
// Let's not bother if there's no picture.
|
// Let's not bother if there's no picture.
|
||||||
if (!ginfo || (!ginfo->pic1.texture && !ginfo->pic0.texture)) {
|
if (!ginfo->Ready(GameInfoFlags::BG) || (!ginfo->pic1.texture && !ginfo->pic0.texture)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1471,11 +1470,10 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float pr
|
|||||||
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
|
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||||
g_Config.Save("MainScreen::OnGameSelected");
|
g_Config.Save("MainScreen::OnGameSelected");
|
||||||
Path path(e.s);
|
Path path(e.s);
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, path, GAMEINFO_WANTBG);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, path, GameInfoFlags::FILE_TYPE);
|
||||||
if (ginfo && ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
if (ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_GameManager.GetState() == GameManagerState::INSTALLING)
|
if (g_GameManager.GetState() == GameManagerState::INSTALLING)
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<GameInfo> ginfo = GetInfo(dc, index);
|
std::shared_ptr<GameInfo> ginfo = GetInfo(dc, index);
|
||||||
if (ginfo && ginfo->pending) {
|
if (ginfo && !ginfo->Ready(GameInfoFlags::BG)) {
|
||||||
// Wait for it to load. It might be the next one.
|
// Wait for it to load. It might be the next one.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ private:
|
|||||||
const auto recentIsos = g_Config.RecentIsos();
|
const auto recentIsos = g_Config.RecentIsos();
|
||||||
if (index >= (int)recentIsos.size())
|
if (index >= (int)recentIsos.size())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(recentIsos[index]), GAMEINFO_WANTBG);
|
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(recentIsos[index]), GameInfoFlags::BG);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTex(UIContext &dc, std::shared_ptr<GameInfo> &ginfo, float amount) {
|
void DrawTex(UIContext &dc, std::shared_ptr<GameInfo> &ginfo, float amount) {
|
||||||
@ -376,13 +376,14 @@ uint32_t GetBackgroundColorWithAlpha(const UIContext &dc) {
|
|||||||
void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, float z) {
|
void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, float z) {
|
||||||
using namespace Draw;
|
using namespace Draw;
|
||||||
using namespace UI;
|
using namespace UI;
|
||||||
|
|
||||||
std::shared_ptr<GameInfo> ginfo;
|
|
||||||
if (!gamePath.empty())
|
|
||||||
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GAMEINFO_WANTBG);
|
|
||||||
dc.Flush();
|
dc.Flush();
|
||||||
|
|
||||||
GameInfoTex *pic = ginfo ? ginfo->GetBGPic() : nullptr;
|
std::shared_ptr<GameInfo> ginfo;
|
||||||
|
if (!gamePath.empty()) {
|
||||||
|
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GameInfoFlags::BG);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameInfoTex *pic = (ginfo && ginfo->Ready(GameInfoFlags::BG)) ? ginfo->GetBGPic() : nullptr;
|
||||||
if (pic) {
|
if (pic) {
|
||||||
dc.GetDrawContext()->BindTexture(0, pic->texture);
|
dc.GetDrawContext()->BindTexture(0, pic->texture);
|
||||||
uint32_t color = whiteAlpha(ease((time_now_d() - pic->timeLoaded) * 3)) & 0xFFc0c0c0;
|
uint32_t color = whiteAlpha(ease((time_now_d() - pic->timeLoaded) * 3)) & 0xFFc0c0c0;
|
||||||
|
@ -531,26 +531,29 @@ UI::EventReturn GamePauseScreen::OnLastSaveUndo(UI::EventParams &e) {
|
|||||||
void GamePauseScreen::CallbackDeleteConfig(bool yes)
|
void GamePauseScreen::CallbackDeleteConfig(bool yes)
|
||||||
{
|
{
|
||||||
if (yes) {
|
if (yes) {
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
g_Config.unloadGameConfig();
|
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
g_Config.deleteGameConfig(info->id);
|
g_Config.unloadGameConfig();
|
||||||
info->hasConfig = false;
|
g_Config.deleteGameConfig(info->id);
|
||||||
screenManager()->RecreateAllViews();
|
info->hasConfig = false;
|
||||||
|
screenManager()->RecreateAllViews();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e)
|
UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e)
|
||||||
{
|
{
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||||
std::string gameId = g_paramSFO.GetDiscID();
|
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
g_Config.createGameConfig(gameId);
|
std::string gameId = g_paramSFO.GetDiscID();
|
||||||
g_Config.changeGameSpecific(gameId, info->GetTitle());
|
g_Config.createGameConfig(gameId);
|
||||||
g_Config.saveGameConfig(gameId, info->GetTitle());
|
g_Config.changeGameSpecific(gameId, info->GetTitle());
|
||||||
if (info) {
|
g_Config.saveGameConfig(gameId, info->GetTitle());
|
||||||
info->hasConfig = true;
|
if (info) {
|
||||||
|
info->hasConfig = true;
|
||||||
|
}
|
||||||
|
screenManager()->topScreen()->RecreateViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
screenManager()->topScreen()->RecreateViews();
|
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +87,8 @@ public:
|
|||||||
UIContext &dc = *screenManager()->getUIContext();
|
UIContext &dc = *screenManager()->getUIContext();
|
||||||
const Style &textStyle = dc.theme->popupStyle;
|
const Style &textStyle = dc.theme->popupStyle;
|
||||||
|
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::SIZE);
|
||||||
if (!ginfo)
|
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
|
ScrollView *contentScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f));
|
||||||
@ -260,7 +260,7 @@ void SavedataButton::UpdateDateSeconds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn SavedataPopupScreen::OnDeleteButtonClick(UI::EventParams &e) {
|
UI::EventReturn SavedataPopupScreen::OnDeleteButtonClick(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
|
||||||
ginfo->Delete();
|
ginfo->Delete();
|
||||||
TriggerFinish(DR_NO);
|
TriggerFinish(DR_NO);
|
||||||
return UI::EVENT_DONE;
|
return UI::EVENT_DONE;
|
||||||
@ -274,8 +274,8 @@ static std::string CleanSaveString(const std::string &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SavedataButton::UpdateText() {
|
bool SavedataButton::UpdateText() {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
|
||||||
if (!ginfo->pending) {
|
if (ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
UpdateText(ginfo);
|
UpdateText(ginfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -294,7 +294,7 @@ void SavedataButton::UpdateText(const std::shared_ptr<GameInfo> &ginfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SavedataButton::Draw(UIContext &dc) {
|
void SavedataButton::Draw(UIContext &dc) {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), savePath_, GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::SIZE);
|
||||||
Draw::Texture *texture = 0;
|
Draw::Texture *texture = 0;
|
||||||
u32 color = 0, shadowColor = 0;
|
u32 color = 0, shadowColor = 0;
|
||||||
using namespace UI;
|
using namespace UI;
|
||||||
@ -682,7 +682,10 @@ UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UI::EventReturn SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) {
|
UI::EventReturn SavedataScreen::OnSavedataButtonClick(UI::EventParams &e) {
|
||||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), Path(e.s), 0);
|
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), Path(e.s), GameInfoFlags::PARAM_SFO);
|
||||||
|
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||||
|
return UI::EVENT_DONE;
|
||||||
|
}
|
||||||
SavedataPopupScreen *popupScreen = new SavedataPopupScreen(e.s, ginfo->GetTitle());
|
SavedataPopupScreen *popupScreen = new SavedataPopupScreen(e.s, ginfo->GetTitle());
|
||||||
if (e.v) {
|
if (e.v) {
|
||||||
popupScreen->SetPopupOrigin(e.v);
|
popupScreen->SetPopupOrigin(e.v);
|
||||||
@ -714,14 +717,15 @@ void GameIconView::GetContentDimensions(const UIContext &dc, float &w, float &h)
|
|||||||
|
|
||||||
void GameIconView::Draw(UIContext &dc) {
|
void GameIconView::Draw(UIContext &dc) {
|
||||||
using namespace UI;
|
using namespace UI;
|
||||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::ICON);
|
||||||
|
if (!info->Ready(GameInfoFlags::ICON) || !info->icon.texture) {
|
||||||
if (!info->icon.texture) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
textureWidth_ = info->icon.texture->Width() * scale_;
|
Draw::Texture *texture = info->icon.texture;
|
||||||
textureHeight_ = info->icon.texture->Height() * scale_;
|
|
||||||
|
textureWidth_ = texture->Width() * scale_;
|
||||||
|
textureHeight_ = texture->Height() * scale_;
|
||||||
|
|
||||||
// Fade icon with the backgrounds.
|
// Fade icon with the backgrounds.
|
||||||
double loadTime = info->icon.timeLoaded;
|
double loadTime = info->icon.timeLoaded;
|
||||||
@ -736,7 +740,7 @@ void GameIconView::Draw(UIContext &dc) {
|
|||||||
float nw = std::min(bounds_.h * textureWidth_ / textureHeight_, (float)bounds_.w);
|
float nw = std::min(bounds_.h * textureWidth_ / textureHeight_, (float)bounds_.w);
|
||||||
|
|
||||||
dc.Flush();
|
dc.Flush();
|
||||||
dc.GetDrawContext()->BindTexture(0, info->icon.texture);
|
dc.GetDrawContext()->BindTexture(0, texture);
|
||||||
dc.Draw()->Rect(bounds_.x, bounds_.y, nw, bounds_.h, color);
|
dc.Draw()->Rect(bounds_.x, bounds_.y, nw, bounds_.h, color);
|
||||||
dc.Flush();
|
dc.Flush();
|
||||||
dc.RebindTexture();
|
dc.RebindTexture();
|
||||||
|
Loading…
Reference in New Issue
Block a user