mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +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) { \
|
||||
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
|
||||
|
||||
|
@ -147,7 +147,7 @@ void WavData::Read(RIFFReader &file_) {
|
||||
numFrames = numBytes / raw_bytes_per_frame; // numFrames
|
||||
|
||||
// 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_size = numBytes;
|
||||
|
||||
@ -359,8 +359,8 @@ void BackgroundAudio::Update() {
|
||||
return;
|
||||
|
||||
// Grab some audio from the current game and play it.
|
||||
std::shared_ptr<GameInfo> gameInfo = g_gameInfoCache->GetInfo(nullptr, bgGamePath_, GAMEINFO_WANTSND);
|
||||
if (!gameInfo || gameInfo->pending) {
|
||||
std::shared_ptr<GameInfo> gameInfo = g_gameInfoCache->GetInfo(nullptr, bgGamePath_, GameInfoFlags::SND);
|
||||
if (!gameInfo->Ready(GameInfoFlags::SND)) {
|
||||
// Should try again shortly..
|
||||
return;
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ CwCheatScreen::~CwCheatScreen() {
|
||||
}
|
||||
|
||||
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;
|
||||
if (info && info->paramSFOLoaded) {
|
||||
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
gameID = info->paramSFO.GetValueString("DISC_ID");
|
||||
} else {
|
||||
return false;
|
||||
|
@ -269,8 +269,8 @@ void EmuScreen::bootGame(const Path &filename) {
|
||||
invalid_ = true;
|
||||
|
||||
// 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);
|
||||
if (!info || info->pending)
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, filename, GameInfoFlags::PARAM_SFO);
|
||||
if (!info || info->Ready(GameInfoFlags::PARAM_SFO))
|
||||
return;
|
||||
|
||||
auto sc = GetI18NCategory(I18NCat::SCREEN);
|
||||
@ -952,11 +952,11 @@ public:
|
||||
|
||||
void Draw(UIContext &dc) override {
|
||||
// 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();
|
||||
|
||||
// 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;
|
||||
if (texture) {
|
||||
dc.GetDrawContext()->BindTexture(0, texture);
|
||||
|
@ -54,8 +54,9 @@ void GameInfoTex::Clear() {
|
||||
}
|
||||
}
|
||||
|
||||
GameInfo::GameInfo() : fileType(IdentifiedFileType::UNKNOWN) {
|
||||
pending = true;
|
||||
GameInfo::GameInfo() {
|
||||
// here due to a forward decl.
|
||||
fileType = IdentifiedFileType::UNKNOWN;
|
||||
}
|
||||
|
||||
GameInfo::~GameInfo() {
|
||||
@ -275,6 +276,7 @@ void GameInfo::DisposeFileLoader() {
|
||||
}
|
||||
|
||||
bool GameInfo::DeleteAllSaveData() {
|
||||
_assert_(hasFlags & GameInfoFlags::PARAM_SFO); // so we know we have the ID.
|
||||
std::vector<Path> saveDataDir = GetSaveDataDirectories();
|
||||
for (size_t j = 0; j < saveDataDir.size(); j++) {
|
||||
std::vector<File::FileInfo> fileInfo;
|
||||
@ -324,13 +326,15 @@ void GameInfo::ParseParamSFO() {
|
||||
region = GAMEREGION_CHINA;
|
||||
}*/
|
||||
}
|
||||
|
||||
paramSFOLoaded = true;
|
||||
}
|
||||
|
||||
std::string GameInfo::GetTitle() {
|
||||
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) {
|
||||
@ -352,21 +356,13 @@ void GameInfo::FinishPendingTextureLoads(Draw::DrawContext *draw) {
|
||||
|
||||
void GameInfo::SetupTexture(Draw::DrawContext *thin3d, GameInfoTex &tex) {
|
||||
using namespace Draw;
|
||||
if (tex.data.size()) {
|
||||
if (!tex.texture) {
|
||||
// TODO: Use TempImage to semi-load the image in the worker task, then here we
|
||||
// could just call CreateTextureFromTempImage.
|
||||
tex.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)tex.data.data(), (int)tex.data.size(), ImageFileType::DETECT, false, GetTitle().c_str());
|
||||
if (tex.texture) {
|
||||
tex.timeLoaded = time_now_d();
|
||||
} 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;
|
||||
}
|
||||
// TODO: Use TempImage to semi-load the image in the worker task, then here we
|
||||
// could just call CreateTextureFromTempImage.
|
||||
tex.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)tex.data.data(), (int)tex.data.size(), ImageFileType::DETECT, false, GetTitle().c_str());
|
||||
if (tex.texture) {
|
||||
tex.timeLoaded = time_now_d();
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Failed creating texture (%s) from %d-byte file", GetTitle().c_str(), (int)tex.data.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -434,15 +430,11 @@ static bool ReadVFSToString(const char *filename, std::string *contents, std::mu
|
||||
|
||||
class GameInfoWorkItem : public Task {
|
||||
public:
|
||||
GameInfoWorkItem(const Path &gamePath, std::shared_ptr<GameInfo> &info)
|
||||
: gamePath_(gamePath), info_(info) {
|
||||
}
|
||||
GameInfoWorkItem(const Path &gamePath, std::shared_ptr<GameInfo> &info, GameInfoFlags flags)
|
||||
: gamePath_(gamePath), info_(info), flags_(flags) {}
|
||||
|
||||
~GameInfoWorkItem() {
|
||||
info_->pending.store(false);
|
||||
info_->working.store(false);
|
||||
info_->DisposeFileLoader();
|
||||
info_->readyEvent.Notify();
|
||||
}
|
||||
|
||||
TaskType Type() const override {
|
||||
@ -475,8 +467,11 @@ public:
|
||||
|
||||
std::string errorString;
|
||||
|
||||
info_->working = true;
|
||||
info_->fileType = Identify_File(info_->GetFileLoader().get(), &errorString);
|
||||
if (flags_ & GameInfoFlags::FILE_TYPE) {
|
||||
info_->fileType = Identify_File(info_->GetFileLoader().get(), &errorString);
|
||||
info_->hasConfig = g_Config.hasGameConfig(info_->id);
|
||||
}
|
||||
|
||||
switch (info_->fileType) {
|
||||
case IdentifiedFileType::PSP_PBP:
|
||||
case IdentifiedFileType::PSP_PBP_DIRECTORY:
|
||||
@ -499,41 +494,45 @@ public:
|
||||
}
|
||||
|
||||
// First, PARAM.SFO.
|
||||
std::vector<u8> sfoData;
|
||||
if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO(sfoData);
|
||||
info_->ParseParamSFO();
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
std::vector<u8> sfoData;
|
||||
if (pbp.GetSubFile(PBP_PARAM_SFO, &sfoData)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO(sfoData);
|
||||
info_->ParseParamSFO();
|
||||
|
||||
// Assuming PSP_PBP_DIRECTORY without ID or with disc_total < 1 in GAME dir must be homebrew
|
||||
if ((info_->id.empty() || !info_->disc_total)
|
||||
&& gamePath_.FilePathContainsNoCase("PSP/GAME/")
|
||||
&& info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) {
|
||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
info_->id_version = info_->id + "_1.00";
|
||||
info_->region = GAMEREGION_MAX + 1; // 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)
|
||||
&& gamePath_.FilePathContainsNoCase("PSP/GAME/")
|
||||
&& info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) {
|
||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
info_->id_version = info_->id + "_1.00";
|
||||
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, ICON0.PNG.
|
||||
if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data);
|
||||
} else {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
if (File::Exists(screenshot_png))
|
||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
else if (File::Exists(screenshot_jpg))
|
||||
ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||
else
|
||||
// Read standard icon
|
||||
ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data);
|
||||
} else {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
if (File::Exists(screenshot_png))
|
||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
else if (File::Exists(screenshot_jpg))
|
||||
ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||
else
|
||||
// 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) {
|
||||
std::string data;
|
||||
pbp.GetSubFileAsString(PBP_PIC0_PNG, &data);
|
||||
@ -549,7 +548,7 @@ public:
|
||||
info_->pic1.dataLoaded = true;
|
||||
}
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
||||
if (flags_ & GameInfoFlags::SND) {
|
||||
if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) {
|
||||
std::string data;
|
||||
pbp.GetSubFileAsString(PBP_SND0_AT3, &data);
|
||||
@ -564,17 +563,17 @@ public:
|
||||
case IdentifiedFileType::PSP_ELF:
|
||||
handleELF:
|
||||
// An elf on its own has no usable information, no icons, no nothing.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
info_->id = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
info_->id_version = info_->id + "_1.00";
|
||||
info_->region = GAMEREGION_MAX + 1; // Homebrew
|
||||
|
||||
info_->paramSFOLoaded = true;
|
||||
}
|
||||
{
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
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
|
||||
if (File::Exists(screenshot_png)) {
|
||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
@ -594,17 +593,20 @@ handleELF:
|
||||
SequentialHandleAllocator handles;
|
||||
VirtualDiscFileSystem umd(&handles, gamePath_);
|
||||
|
||||
// Alright, let's fetch the PARAM.SFO.
|
||||
std::string paramSFOcontents;
|
||||
if (ReadFileToString(&umd, "/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||
info_->ParseParamSFO();
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
// Alright, let's fetch the PARAM.SFO.
|
||||
std::string paramSFOcontents;
|
||||
if (ReadFileToString(&umd, "/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||
info_->ParseParamSFO();
|
||||
}
|
||||
}
|
||||
|
||||
ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
if (flags_ & GameInfoFlags::BG) {
|
||||
ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
||||
info_->pic1.dataLoaded = true;
|
||||
}
|
||||
@ -613,34 +615,30 @@ handleELF:
|
||||
|
||||
case IdentifiedFileType::PPSSPP_SAVESTATE:
|
||||
{
|
||||
Path screenshotPath;
|
||||
{
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
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.
|
||||
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
||||
info_->icon.dataLoaded = true;
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Error loading screenshot data: '%s'", screenshotPath.c_str());
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
Path screenshotPath = gamePath_.WithReplacedExtension(".ppst", ".jpg");
|
||||
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
||||
info_->icon.dataLoaded = true;
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Error loading screenshot data: '%s'", screenshotPath.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IdentifiedFileType::PPSSPP_GE_DUMP:
|
||||
{
|
||||
Path screenshotPath;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(info_->lock);
|
||||
screenshotPath = gamePath_.WithReplacedExtension(".ppdmp", ".png");
|
||||
}
|
||||
|
||||
// Let's use the comparison screenshot as an icon, if it exists.
|
||||
if (ReadLocalFileToString(screenshotPath, &info_->icon.data, &info_->lock)) {
|
||||
info_->icon.dataLoaded = true;
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
Path screenshotPath = gamePath_.WithReplacedExtension(".ppdmp", ".png");
|
||||
// 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;
|
||||
}
|
||||
@ -651,22 +649,24 @@ handleELF:
|
||||
VirtualDiscFileSystem umd(&handles, gamePath_);
|
||||
|
||||
// Alright, let's fetch the PARAM.SFO.
|
||||
std::string paramSFOcontents;
|
||||
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||
info_->ParseParamSFO();
|
||||
if (flags_ & GameInfoFlags::PARAM_SFO) {
|
||||
std::string paramSFOcontents;
|
||||
if (ReadFileToString(&umd, "/PSP_GAME/PARAM.SFO", ¶mSFOcontents, 0)) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||
info_->ParseParamSFO();
|
||||
}
|
||||
}
|
||||
|
||||
ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
||||
if (flags_ & GameInfoFlags::BG) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
|
||||
info_->pic0.dataLoaded = true;
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
|
||||
info_->pic1.dataLoaded = true;
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
||||
if (flags_ & GameInfoFlags::SND) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
||||
info_->pic1.dataLoaded = true;
|
||||
}
|
||||
@ -691,60 +691,63 @@ handleELF:
|
||||
ISOFileSystem umd(&handles, bd);
|
||||
|
||||
// Alright, let's fetch the PARAM.SFO.
|
||||
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());
|
||||
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::PARAM_SFO) {
|
||||
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());
|
||||
info_->ParseParamSFO();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
if (File::Exists(screenshot_png))
|
||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
else if (File::Exists(screenshot_jpg))
|
||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||
else {
|
||||
DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found");
|
||||
info_->icon.dataLoaded = ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
if (File::Exists(screenshot_png))
|
||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
else if (File::Exists(screenshot_jpg))
|
||||
info_->icon.dataLoaded = ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||
else {
|
||||
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;
|
||||
}
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_ZIP:
|
||||
info_->paramSFOLoaded = true;
|
||||
{
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("zip.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_RAR:
|
||||
info_->paramSFOLoaded = true;
|
||||
{
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("rargray.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IdentifiedFileType::ARCHIVE_7Z:
|
||||
info_->paramSFOLoaded = true;
|
||||
{
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
ReadVFSToString("7z.png", &info_->icon.data, &info_->lock);
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
@ -752,28 +755,31 @@ handleELF:
|
||||
|
||||
case IdentifiedFileType::NORMAL_DIRECTORY:
|
||||
default:
|
||||
info_->paramSFOLoaded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
info_->hasConfig = g_Config.hasGameConfig(info_->id);
|
||||
|
||||
if (info_->wantFlags & GAMEINFO_WANTSIZE) {
|
||||
if (flags_ & GameInfoFlags::SIZE) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
info_->gameSizeOnDisk = info_->GetGameSizeOnDiskInBytes();
|
||||
info_->saveDataSize = info_->GetSaveDataSizeInBytes();
|
||||
info_->installDataSize = info_->GetInstallDataSizeInBytes();
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTUNCOMPRESSEDSIZE) {
|
||||
if (flags_ & GameInfoFlags::UNCOMPRESSED_SIZE) {
|
||||
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());
|
||||
}
|
||||
|
||||
private:
|
||||
Path gamePath_;
|
||||
std::shared_ptr<GameInfo> info_;
|
||||
GameInfoFlags flags_{};
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GameInfoWorkItem);
|
||||
};
|
||||
|
||||
@ -820,14 +826,18 @@ void GameInfoCache::FlushBGs() {
|
||||
iter->second->sndFileData.clear();
|
||||
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) {
|
||||
for (auto iter = info_.begin(); iter != info_.end();) {
|
||||
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) {
|
||||
iter = info_.erase(iter);
|
||||
} else {
|
||||
@ -836,51 +846,48 @@ void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
|
||||
}
|
||||
}
|
||||
|
||||
void GameInfoCache::WaitUntilDone(std::shared_ptr<GameInfo> &info) {
|
||||
info->readyEvent.Wait();
|
||||
}
|
||||
|
||||
// Runs on the main thread. Only call from render() and similar, not update()!
|
||||
// Call on the main thread ONLY - that is from stuff called from NativeFrame.
|
||||
// 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> info;
|
||||
|
||||
std::shared_ptr<GameInfo> GameInfoCache::GetInfo(Draw::DrawContext *draw, const Path &gamePath, GameInfoFlags wantFlags) {
|
||||
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);
|
||||
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->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;
|
||||
}
|
||||
|
||||
if (!info) {
|
||||
info = std::make_shared<GameInfo>();
|
||||
}
|
||||
std::shared_ptr<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) {
|
||||
// Uh oh, it's currently in process. It could mark pending = false with the wrong 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);
|
||||
// Just get all the stuff we wanted.
|
||||
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info, wantFlags);
|
||||
g_threadManager.EnqueueTask(item);
|
||||
|
||||
// Don't re-insert if we already have it.
|
||||
if (info_.find(pathStr) == info_.end())
|
||||
info_[pathStr] = info;
|
||||
return info;
|
||||
}
|
||||
|
@ -50,13 +50,16 @@ enum GameRegion {
|
||||
GAMEREGION_MAX,
|
||||
};
|
||||
|
||||
enum GameInfoWantFlags {
|
||||
GAMEINFO_WANTBG = 0x01,
|
||||
GAMEINFO_WANTSIZE = 0x02,
|
||||
GAMEINFO_WANTSND = 0x04,
|
||||
GAMEINFO_WANTBGDATA = 0x08, // Use with WANTBG.
|
||||
GAMEINFO_WANTUNCOMPRESSEDSIZE = 0x10,
|
||||
enum class GameInfoFlags {
|
||||
FILE_TYPE = 0x01, // Don't need to specify this, always included.
|
||||
PARAM_SFO = 0x02,
|
||||
ICON = 0x04,
|
||||
BG = 0x08,
|
||||
SND = 0x10,
|
||||
SIZE = 0x20,
|
||||
UNCOMPRESSED_SIZE = 0x40,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(GameInfoFlags);
|
||||
|
||||
class FileLoader;
|
||||
enum class IdentifiedFileType;
|
||||
@ -102,6 +105,11 @@ public:
|
||||
std::string GetTitle();
|
||||
void SetTitle(const std::string &newTitle);
|
||||
|
||||
bool Ready(GameInfoFlags flags) {
|
||||
std::unique_lock<std::mutex> guard(lock);
|
||||
return (hasFlags & flags) != 0;
|
||||
}
|
||||
|
||||
GameInfoTex *GetBGPic() {
|
||||
if (pic1.texture)
|
||||
return &pic1;
|
||||
@ -119,6 +127,11 @@ public:
|
||||
// Controls access to the fileLoader pointer.
|
||||
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_version;
|
||||
int disc_total = 0;
|
||||
@ -126,7 +139,6 @@ public:
|
||||
int region = -1;
|
||||
IdentifiedFileType fileType;
|
||||
ParamSFOData paramSFO;
|
||||
bool paramSFOLoaded = false;
|
||||
bool hasConfig = false;
|
||||
|
||||
// Pre read the data, create a texture the next time (GL thread..)
|
||||
@ -137,8 +149,6 @@ public:
|
||||
std::string sndFileData;
|
||||
std::atomic<bool> sndDataLoaded{};
|
||||
|
||||
int wantFlags = 0;
|
||||
|
||||
double lastAccessedTime = 0.0;
|
||||
|
||||
u64 gameSizeUncompressed = 0;
|
||||
@ -146,11 +156,6 @@ public:
|
||||
u64 saveDataSize = 0;
|
||||
u64 installDataSize = 0;
|
||||
|
||||
std::atomic<bool> pending{};
|
||||
std::atomic<bool> working{};
|
||||
|
||||
Event readyEvent;
|
||||
|
||||
protected:
|
||||
// Note: this can change while loading, use GetTitle().
|
||||
std::string title;
|
||||
@ -178,7 +183,7 @@ public:
|
||||
// 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
|
||||
// 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 CancelAll();
|
||||
@ -191,6 +196,7 @@ private:
|
||||
// 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.
|
||||
std::map<std::string, std::shared_ptr<GameInfo> > info_;
|
||||
std::mutex mapLock_;
|
||||
};
|
||||
|
||||
// This one can be global, no good reason not to.
|
||||
|
@ -86,7 +86,7 @@ void GameScreen::update() {
|
||||
}
|
||||
|
||||
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()) {
|
||||
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);
|
||||
if (System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) {
|
||||
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);
|
||||
if (info) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
// TODO: Should we block on Ready?
|
||||
System_CreateGameShortcut(gamePath_, info->GetTitle());
|
||||
}
|
||||
return UI::EVENT_DONE;
|
||||
@ -241,8 +242,8 @@ UI::Choice *GameScreen::AddOtherChoice(UI::Choice *choice) {
|
||||
}
|
||||
|
||||
UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
||||
if (!info) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
return UI::EVENT_SKIPPED;
|
||||
}
|
||||
g_Config.createGameConfig(info->id);
|
||||
@ -255,8 +256,8 @@ UI::EventReturn GameScreen::OnCreateConfig(UI::EventParams &e) {
|
||||
|
||||
void GameScreen::CallbackDeleteConfig(bool yes) {
|
||||
if (yes) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
||||
if (!info) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
return;
|
||||
}
|
||||
g_Config.deleteGameConfig(info->id);
|
||||
@ -283,7 +284,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
|
||||
|
||||
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_) {
|
||||
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.
|
||||
for (UI::Choice *choice : otherChoices_) {
|
||||
choice->SetVisibility(UI::V_VISIBLE);
|
||||
@ -448,8 +449,8 @@ UI::EventReturn GameScreen::OnPlay(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (info && info->paramSFOLoaded) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
std::string discID = info->paramSFO.GetValueString("DISC_ID");
|
||||
if ((discID.empty() || !info->disc_total) && gamePath_.FilePathContainsNoCase("PSP/GAME/"))
|
||||
discID = g_paramSFO.GenerateFakeID(gamePath_);
|
||||
@ -459,7 +460,7 @@ UI::EventReturn GameScreen::OnGameSettings(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) {
|
||||
// Check that there's any savedata to delete
|
||||
if (saveDirs.size()) {
|
||||
@ -470,14 +471,13 @@ UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
||||
std::bind(&GameScreen::CallbackDeleteSaveData, this, std::placeholders::_1)));
|
||||
}
|
||||
}
|
||||
|
||||
RecreateViews();
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
void GameScreen::CallbackDeleteSaveData(bool 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->saveDataSize = 0;
|
||||
info->installDataSize = 0;
|
||||
@ -485,21 +485,20 @@ void GameScreen::CallbackDeleteSaveData(bool yes) {
|
||||
}
|
||||
|
||||
UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (info) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info && info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
auto ga = GetI18NCategory(I18NCat::GAME);
|
||||
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"),
|
||||
std::bind(&GameScreen::CallbackDeleteGame, this, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
void GameScreen::CallbackDeleteGame(bool 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();
|
||||
g_gameInfoCache->Clear();
|
||||
screenManager()->switchScreen(new MainScreen());
|
||||
@ -560,8 +559,8 @@ void SetBackgroundPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
void SetBackgroundPopupScreen::update() {
|
||||
PopupScreen::update();
|
||||
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTBGDATA);
|
||||
if (status_ == Status::PENDING && info && !info->pending) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::BG);
|
||||
if (status_ == Status::PENDING && info && info->Ready(GameInfoFlags::BG)) {
|
||||
GameInfoTex *pic = nullptr;
|
||||
if (info->pic1.dataLoaded && info->pic1.data.size()) {
|
||||
pic = &info->pic1;
|
||||
|
@ -221,7 +221,7 @@ void GameSettingsScreen::PreCreateViews() {
|
||||
ReloadAllThemeInfo();
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@ -1454,7 +1454,7 @@ void GameSettingsScreen::onFinish(DialogResult result) {
|
||||
|
||||
if (editThenRestore_) {
|
||||
// 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.unloadGameConfig();
|
||||
}
|
||||
|
@ -226,12 +226,12 @@ private:
|
||||
};
|
||||
|
||||
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;
|
||||
u32 color = 0, shadowColor = 0;
|
||||
using namespace UI;
|
||||
|
||||
if (ginfo->icon.texture) {
|
||||
if (ginfo->Ready(GameInfoFlags::ICON) && ginfo->icon.texture) {
|
||||
texture = ginfo->icon.texture;
|
||||
}
|
||||
|
||||
@ -427,10 +427,9 @@ void GameButton::Draw(UIContext &dc) {
|
||||
}
|
||||
|
||||
std::string GameButton::DescribeText() const {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, gamePath_, 0);
|
||||
if (ginfo->pending)
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO))
|
||||
return "...";
|
||||
|
||||
auto u = GetI18NCategory(I18NCat::UI_ELEMENTS);
|
||||
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;
|
||||
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.
|
||||
dc.RebindTexture();
|
||||
|
||||
// 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;
|
||||
}
|
||||
} else {
|
||||
@ -1471,11 +1470,10 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float pr
|
||||
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||
g_Config.Save("MainScreen::OnGameSelected");
|
||||
Path path(e.s);
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, path, GAMEINFO_WANTBG);
|
||||
if (ginfo && ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, path, GameInfoFlags::FILE_TYPE);
|
||||
if (ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
if (g_GameManager.GetState() == GameManagerState::INSTALLING)
|
||||
return UI::EVENT_DONE;
|
||||
|
||||
|
@ -240,7 +240,7 @@ private:
|
||||
}
|
||||
|
||||
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.
|
||||
break;
|
||||
}
|
||||
@ -261,7 +261,7 @@ private:
|
||||
const auto recentIsos = g_Config.RecentIsos();
|
||||
if (index >= (int)recentIsos.size())
|
||||
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) {
|
||||
@ -376,13 +376,14 @@ uint32_t GetBackgroundColorWithAlpha(const UIContext &dc) {
|
||||
void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, float z) {
|
||||
using namespace Draw;
|
||||
using namespace UI;
|
||||
|
||||
std::shared_ptr<GameInfo> ginfo;
|
||||
if (!gamePath.empty())
|
||||
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GAMEINFO_WANTBG);
|
||||
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) {
|
||||
dc.GetDrawContext()->BindTexture(0, pic->texture);
|
||||
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)
|
||||
{
|
||||
if (yes) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
||||
g_Config.unloadGameConfig();
|
||||
g_Config.deleteGameConfig(info->id);
|
||||
info->hasConfig = false;
|
||||
screenManager()->RecreateAllViews();
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
g_Config.unloadGameConfig();
|
||||
g_Config.deleteGameConfig(info->id);
|
||||
info->hasConfig = false;
|
||||
screenManager()->RecreateAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UI::EventReturn GamePauseScreen::OnCreateConfig(UI::EventParams &e)
|
||||
{
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, 0);
|
||||
std::string gameId = g_paramSFO.GetDiscID();
|
||||
g_Config.createGameConfig(gameId);
|
||||
g_Config.changeGameSpecific(gameId, info->GetTitle());
|
||||
g_Config.saveGameConfig(gameId, info->GetTitle());
|
||||
if (info) {
|
||||
info->hasConfig = true;
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
std::string gameId = g_paramSFO.GetDiscID();
|
||||
g_Config.createGameConfig(gameId);
|
||||
g_Config.changeGameSpecific(gameId, info->GetTitle());
|
||||
g_Config.saveGameConfig(gameId, info->GetTitle());
|
||||
if (info) {
|
||||
info->hasConfig = true;
|
||||
}
|
||||
screenManager()->topScreen()->RecreateViews();
|
||||
}
|
||||
|
||||
screenManager()->topScreen()->RecreateViews();
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,8 @@ public:
|
||||
UIContext &dc = *screenManager()->getUIContext();
|
||||
const Style &textStyle = dc.theme->popupStyle;
|
||||
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (!ginfo)
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(screenManager()->getDrawContext(), savePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::SIZE);
|
||||
if (!ginfo->Ready(GameInfoFlags::PARAM_SFO))
|
||||
return;
|
||||
|
||||
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) {
|
||||
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();
|
||||
TriggerFinish(DR_NO);
|
||||
return UI::EVENT_DONE;
|
||||
@ -274,8 +274,8 @@ static std::string CleanSaveString(const std::string &str) {
|
||||
}
|
||||
|
||||
bool SavedataButton::UpdateText() {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GAMEINFO_WANTSIZE);
|
||||
if (!ginfo->pending) {
|
||||
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, savePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (ginfo->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
UpdateText(ginfo);
|
||||
return true;
|
||||
}
|
||||
@ -294,7 +294,7 @@ void SavedataButton::UpdateText(const std::shared_ptr<GameInfo> &ginfo) {
|
||||
}
|
||||
|
||||
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;
|
||||
u32 color = 0, shadowColor = 0;
|
||||
using namespace UI;
|
||||
@ -682,7 +682,10 @@ UI::EventReturn SavedataScreen::OnSearch(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());
|
||||
if (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) {
|
||||
using namespace UI;
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
|
||||
if (!info->icon.texture) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::ICON);
|
||||
if (!info->Ready(GameInfoFlags::ICON) || !info->icon.texture) {
|
||||
return;
|
||||
}
|
||||
|
||||
textureWidth_ = info->icon.texture->Width() * scale_;
|
||||
textureHeight_ = info->icon.texture->Height() * scale_;
|
||||
Draw::Texture *texture = info->icon.texture;
|
||||
|
||||
textureWidth_ = texture->Width() * scale_;
|
||||
textureHeight_ = texture->Height() * scale_;
|
||||
|
||||
// Fade icon with the backgrounds.
|
||||
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);
|
||||
|
||||
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.Flush();
|
||||
dc.RebindTexture();
|
||||
|
Loading…
Reference in New Issue
Block a user