diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 838d824e0e..c2de1c7d98 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -45,17 +45,13 @@ GameInfoCache *g_gameInfoCache; -GameInfo::GameInfo() - : region(-1), fileType(IdentifiedFileType::UNKNOWN), paramSFOLoaded(false), - hasConfig(false), iconTexture(nullptr), pic0Texture(nullptr), pic1Texture(nullptr), wantFlags(0), - lastAccessedTime(0.0), timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0), - gameSize(0), saveDataSize(0), installDataSize(0), pending(true), working(false), fileLoader(nullptr) { +GameInfo::GameInfo() : fileType(IdentifiedFileType::UNKNOWN) { } GameInfo::~GameInfo() { - delete iconTexture; - delete pic0Texture; - delete pic1Texture; + delete icon.texture; + delete pic0.texture; + delete pic1.texture; delete fileLoader; } @@ -412,23 +408,23 @@ public: // Then, ICON0.PNG. if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) { std::lock_guard lock(info_->lock); - pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->iconTextureData); + pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data); } else { // Read standard icon - ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); + ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); } - info_->iconDataLoaded = true; + info_->icon.dataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) { std::lock_guard lock(info_->lock); - pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0TextureData); - info_->pic0DataLoaded = true; + pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0.data); + info_->pic0.dataLoaded = true; } if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { std::lock_guard lock(info_->lock); - pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); - info_->pic1DataLoaded = true; + pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1.data); + info_->pic1.dataLoaded = true; } } if (info_->wantFlags & GAMEINFO_WANTSND) { @@ -453,8 +449,8 @@ handleELF: // Read standard icon DEBUG_LOG(LOADER, "Loading unknown.png because there was an ELF"); - ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; break; case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: @@ -470,11 +466,11 @@ handleELF: info_->ParseParamSFO(); } - ReadFileToString(&umd, "/ICON0.PNG", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { - ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1TextureData, &info_->lock); - info_->pic1DataLoaded = true; + ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1.data, &info_->lock); + info_->pic1.dataLoaded = true; } break; } @@ -488,8 +484,8 @@ handleELF: // Let's use the screenshot as an icon, too. std::string screenshotPath = ReplaceAll(gamePath_, ".ppst", ".jpg"); if (File::Exists(screenshotPath)) { - if (readFileToString(false, screenshotPath.c_str(), info_->iconTextureData)) { - info_->iconDataLoaded = true; + if (readFileToString(false, screenshotPath.c_str(), info_->icon.data)) { + info_->icon.dataLoaded = true; } } break; @@ -509,17 +505,17 @@ handleELF: info_->ParseParamSFO(); } - ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; if (info_->wantFlags & GAMEINFO_WANTBG) { - ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); - info_->pic0DataLoaded = true; - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); - info_->pic1DataLoaded = true; + 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) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); - info_->pic1DataLoaded = true; + info_->pic1.dataLoaded = true; } break; } @@ -548,47 +544,47 @@ handleELF: info_->ParseParamSFO(); if (info_->wantFlags & GAMEINFO_WANTBG) { - ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, nullptr); - info_->pic0DataLoaded = true; - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, nullptr); - info_->pic1DataLoaded = true; + ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, nullptr); + info_->pic0.dataLoaded = true; + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, nullptr); + info_->pic1.dataLoaded = true; } if (info_->wantFlags & GAMEINFO_WANTSND) { ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, nullptr); - info_->pic1DataLoaded = true; + info_->pic1.dataLoaded = true; } } // 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_->iconTextureData, &info_->lock)) { + if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) { DEBUG_LOG(LOADER, "Loading unknown.png because no icon was found"); - ReadVFSToString("unknown.png", &info_->iconTextureData, &info_->lock); + ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock); } - info_->iconDataLoaded = true; + info_->icon.dataLoaded = true; break; } case IdentifiedFileType::ARCHIVE_ZIP: info_->paramSFOLoaded = true; { - ReadVFSToString("zip.png", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadVFSToString("zip.png", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; } break; case IdentifiedFileType::ARCHIVE_RAR: info_->paramSFOLoaded = true; { - ReadVFSToString("rargray.png", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadVFSToString("rargray.png", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; } break; case IdentifiedFileType::ARCHIVE_7Z: info_->paramSFOLoaded = true; { - ReadVFSToString("7z.png", &info_->iconTextureData, &info_->lock); - info_->iconDataLoaded = true; + ReadVFSToString("7z.png", &info_->icon.data, &info_->lock); + info_->icon.dataLoaded = true; } break; @@ -653,30 +649,9 @@ void GameInfoCache::Clear() { for (auto iter = info_.begin(); iter != info_.end(); iter++) { { std::lock_guard lock(iter->second->lock); - if (!iter->second->pic0TextureData.empty()) { - iter->second->pic0TextureData.clear(); - iter->second->pic0DataLoaded = false; - } - if (iter->second->pic0Texture) { - delete iter->second->pic0Texture; - iter->second->pic0Texture = 0; - } - if (!iter->second->pic1TextureData.empty()) { - iter->second->pic1TextureData.clear(); - iter->second->pic1DataLoaded = false; - } - if (iter->second->pic1Texture) { - delete iter->second->pic1Texture; - iter->second->pic1Texture = 0; - } - if (!iter->second->iconTextureData.empty()) { - iter->second->iconTextureData.clear(); - iter->second->iconDataLoaded = false; - } - if (iter->second->iconTexture) { - delete iter->second->iconTexture; - iter->second->iconTexture = 0; - } + iter->second->pic0.Clear(); + iter->second->pic1.Clear(); + iter->second->icon.Clear(); if (!iter->second->sndFileData.empty()) { iter->second->sndFileData.clear(); @@ -691,23 +666,8 @@ void GameInfoCache::Clear() { void GameInfoCache::FlushBGs() { for (auto iter = info_.begin(); iter != info_.end(); iter++) { std::lock_guard lock(iter->second->lock); - if (!iter->second->pic0TextureData.empty()) { - iter->second->pic0TextureData.clear(); - iter->second->pic0DataLoaded = false; - } - if (iter->second->pic0Texture) { - delete iter->second->pic0Texture; - iter->second->pic0Texture = 0; - } - - if (!iter->second->pic1TextureData.empty()) { - iter->second->pic1TextureData.clear(); - iter->second->pic1DataLoaded = false; - } - if (iter->second->pic1Texture) { - delete iter->second->pic1Texture; - iter->second->pic1Texture = 0; - } + iter->second->pic0.Clear(); + iter->second->pic1.Clear(); if (!iter->second->sndFileData.empty()) { iter->second->sndFileData.clear(); @@ -749,27 +709,22 @@ GameInfo *GameInfoCache::GetInfo(Draw::DrawContext *draw, const std::string &gam auto iter = info_.find(gamePath); if (iter != info_.end()) { info = iter->second; - if ((info->wantFlags & wantFlags) != wantFlags) { - // Need to start over. We'll just add a new work item. - goto again; - } - if (draw && info->iconDataLoaded) { - SetupTexture(info, info->iconTextureData, draw, info->iconTexture, info->timeIconWasLoaded); - info->iconDataLoaded = false; - } - if (draw && info->pic0DataLoaded) { - SetupTexture(info, info->pic0TextureData, draw, info->pic0Texture, info->timePic0WasLoaded); - info->pic0DataLoaded = false; - } - if (draw && info->pic1DataLoaded) { - SetupTexture(info, info->pic1TextureData, draw, info->pic1Texture, info->timePic1WasLoaded); - info->pic1DataLoaded = false; - } - iter->second->lastAccessedTime = time_now_d(); - return iter->second; } -again: + // If wantFlags don't match, we need to start over. We'll just queue the work item again. + if (info && (info->wantFlags & wantFlags) == wantFlags) { + if (draw && info->icon.dataLoaded && !info->icon.texture) { + SetupTexture(info, draw, info->icon); + } + if (draw && info->pic0.dataLoaded && !info->pic0.texture) { + SetupTexture(info, draw, info->pic0); + } + if (draw && info->pic1.dataLoaded && !info->pic1.texture) { + SetupTexture(info, draw, info->pic1); + } + info->lastAccessedTime = time_now_d(); + return info; + } if (!info) { info = new GameInfo(); @@ -794,15 +749,16 @@ again: return info; } -void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *thin3d, ManagedTexture *&tex, double &loadTime) { +void GameInfoCache::SetupTexture(GameInfo *info, Draw::DrawContext *thin3d, GameInfoTex &icon) { using namespace Draw; - if (textureData.size()) { - if (!tex) { - tex = CreateTextureFromFileData(thin3d, (const uint8_t *)textureData.data(), (int)textureData.size(), ImageFileType::DETECT); - if (tex) { - loadTime = time_now_d(); + if (icon.data.size()) { + if (!icon.texture) { + icon.texture = CreateTextureFromFileData(thin3d, (const uint8_t *)icon.data.data(), (int)icon.data.size(), ImageFileType::DETECT); + if (icon.texture) { + icon.timeLoaded = time_now_d(); } } - textureData.clear(); + icon.data.clear(); + icon.dataLoaded = false; } } diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index a4cf583ab1..deddeed624 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -58,6 +58,26 @@ enum GameInfoWantFlags { class FileLoader; enum class IdentifiedFileType; +struct GameInfoTex { + std::string data; + ManagedTexture *texture = nullptr; + // The time at which the Icon and the BG were loaded. + // Can be useful to fade them in smoothly once they appear. + double timeLoaded = 0.0; + std::atomic dataLoaded = false; + + void Clear() { + if (!data.empty()) { + data.clear(); + dataLoaded = false; + } + if (texture) { + delete texture; + texture = nullptr; + } + } +}; + class GameInfo { public: GameInfo(); @@ -97,45 +117,32 @@ public: int region = -1; IdentifiedFileType fileType; ParamSFOData paramSFO; - bool paramSFOLoaded; - bool hasConfig; + bool paramSFOLoaded = false; + bool hasConfig = false; // Pre read the data, create a texture the next time (GL thread..) - std::string iconTextureData; - ManagedTexture *iconTexture; - std::string pic0TextureData; - ManagedTexture *pic0Texture; - std::string pic1TextureData; - ManagedTexture *pic1Texture; + GameInfoTex icon; + GameInfoTex pic0; + GameInfoTex pic1; std::string sndFileData; + std::atomic sndDataLoaded = false; - int wantFlags; + int wantFlags = 0; - double lastAccessedTime; + double lastAccessedTime = 0.0; - // The time at which the Icon and the BG were loaded. - // Can be useful to fade them in smoothly once they appear. - double timeIconWasLoaded; - double timePic0WasLoaded; - double timePic1WasLoaded; - - std::atomic iconDataLoaded; - std::atomic pic0DataLoaded; - std::atomic pic1DataLoaded; - std::atomic sndDataLoaded; - - u64 gameSize; - u64 saveDataSize; - u64 installDataSize; - bool pending; - bool working; + u64 gameSize = 0; + u64 saveDataSize = 0; + u64 installDataSize = 0; + bool pending = true; + bool working = false; protected: // Note: this can change while loading, use GetTitle(). std::string title; - FileLoader *fileLoader; + FileLoader *fileLoader = nullptr; std::string filePath_; }; @@ -148,7 +155,7 @@ public: void Clear(); void PurgeType(IdentifiedFileType fileType); - // All data in GameInfo including iconTexture may be zero the first time you call this + // All data in GameInfo including icon.texture may be zero the first time you call 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 // because they're big. bgTextures and sound may be discarded over time as well. @@ -162,7 +169,7 @@ public: private: void Init(); void Shutdown(); - void SetupTexture(GameInfo *info, std::string &textureData, Draw::DrawContext *draw, ManagedTexture *&tex, double &loadTime); + void SetupTexture(GameInfo *info, Draw::DrawContext *draw, GameInfoTex &icon); // Maps ISO path to info. std::map info_; diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index c701803384..5867e0915b 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -202,15 +202,15 @@ void GameScreen::update() { if (tvTitle_) tvTitle_->SetText(info->GetTitle() + " (" + info->id + ")"); - if (info->iconTexture && texvGameIcon_) { - texvGameIcon_->SetTexture(info->iconTexture->GetTexture()); + if (info->icon.texture && texvGameIcon_) { + texvGameIcon_->SetTexture(info->icon.texture->GetTexture()); // Fade the icon with the background. - double loadTime = info->timeIconWasLoaded; - if (info->pic1Texture) { - loadTime = std::max(loadTime, info->timePic1WasLoaded); + double loadTime = info->icon.timeLoaded; + if (info->pic1.texture) { + loadTime = std::max(loadTime, info->pic1.timeLoaded); } - if (info->pic0Texture) { - loadTime = std::max(loadTime, info->timePic0WasLoaded); + if (info->pic0.texture) { + loadTime = std::max(loadTime, info->pic0.timeLoaded); } uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)); texvGameIcon_->SetColor(color); diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 23411e9108..6ff03dd5ee 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -180,8 +180,8 @@ void GameButton::Draw(UIContext &dc) { u32 color = 0, shadowColor = 0; using namespace UI; - if (ginfo->iconTexture) { - texture = ginfo->iconTexture->GetTexture(); + if (ginfo->icon.texture) { + texture = ginfo->icon.texture->GetTexture(); } int x = bounds_.x; @@ -207,8 +207,8 @@ void GameButton::Draw(UIContext &dc) { } if (texture) { - color = whiteAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); - shadowColor = blackAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); + color = whiteAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2)); + shadowColor = blackAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2)); float tw = texture->Width(); float th = texture->Height(); @@ -1017,17 +1017,17 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f dc.RebindTexture(); // Let's not bother if there's no picture. - if (!ginfo || (!ginfo->pic1Texture && !ginfo->pic0Texture)) { + if (!ginfo || (!ginfo->pic1.texture && !ginfo->pic0.texture)) { return false; } } else { return false; } - if (ginfo->pic1Texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic1Texture->GetTexture()); - } else if (ginfo->pic0Texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic0Texture->GetTexture()); + if (ginfo->pic1.texture) { + dc.GetDrawContext()->BindTexture(0, ginfo->pic1.texture->GetTexture()); + } else if (ginfo->pic0.texture) { + dc.GetDrawContext()->BindTexture(0, ginfo->pic0.texture->GetTexture()); } uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0; diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index da352bce31..4d49057e7c 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -109,13 +109,13 @@ void DrawGameBackground(UIContext &dc, const std::string &gamePath) { bool hasPic = false; double loadTime; - if (ginfo && ginfo->pic1Texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic1Texture->GetTexture()); - loadTime = ginfo->timePic1WasLoaded; + if (ginfo && ginfo->pic1.texture) { + dc.GetDrawContext()->BindTexture(0, ginfo->pic1.texture->GetTexture()); + loadTime = ginfo->pic1.timeLoaded; hasPic = true; - } else if (ginfo && ginfo->pic0Texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic0Texture->GetTexture()); - loadTime = ginfo->timePic0WasLoaded; + } else if (ginfo && ginfo->pic0.texture) { + dc.GetDrawContext()->BindTexture(0, ginfo->pic0.texture->GetTexture()); + loadTime = ginfo->pic0.timeLoaded; hasPic = true; } if (hasPic) { diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index 43a7869163..d9fff6f708 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -80,8 +80,8 @@ public: std::string savedata_detail = ginfo->paramSFO.GetValueString("SAVEDATA_DETAIL"); std::string savedata_title = ginfo->paramSFO.GetValueString("SAVEDATA_TITLE"); - if (ginfo->iconTexture) { - toprow->Add(new TextureView(ginfo->iconTexture->GetTexture(), IS_FIXED, new LinearLayoutParams(Margins(10, 5)))); + if (ginfo->icon.texture) { + toprow->Add(new TextureView(ginfo->icon.texture->GetTexture(), IS_FIXED, new LinearLayoutParams(Margins(10, 5)))); } LinearLayout *topright = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1.0f)); topright->SetSpacing(1.0f); @@ -159,8 +159,8 @@ void SavedataButton::Draw(UIContext &dc) { u32 color = 0, shadowColor = 0; using namespace UI; - if (ginfo->iconTexture) { - texture = ginfo->iconTexture->GetTexture(); + if (ginfo->icon.texture) { + texture = ginfo->icon.texture->GetTexture(); } int x = bounds_.x; @@ -184,8 +184,8 @@ void SavedataButton::Draw(UIContext &dc) { dc.Draw()->Flush(); if (texture) { - color = whiteAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); - shadowColor = blackAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); + color = whiteAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2)); + shadowColor = blackAlpha(ease((time_now_d() - ginfo->icon.timeLoaded) * 2)); float tw = texture->Width(); float th = texture->Height();