From 1a44b557e57ef082e1b44276ae5c461f250b0d17 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 13:44:07 -0700 Subject: [PATCH 1/9] Allow loading game info without clearing old. More seamless when we already have the icon, for example. --- UI/GameInfoCache.cpp | 20 +++++++++++++------- UI/GameInfoCache.h | 1 + 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 01d2c9fdb8..0b5b926ef8 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -523,17 +523,18 @@ void GameInfoCache::FlushBGs() { // pspFileSystem (well, we could with synchronization but there might not // even be a game running). GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { + GameInfo *info = 0; + auto iter = info_.find(gamePath); if (iter != info_.end()) { - GameInfo *info = iter->second; + info = iter->second; if (!info->wantBG && wantBG) { // Need to start over. We'll just add a new work item. - delete info; // Hm, how dangerous is this? There might be a race condition here. goto again; } { lock_guard lock(info->lock); - if (info->iconTextureData.size()) { + if (info->iconTextureData.size() && !info->iconTexture) { // We'd have to split up Texture->LoadPNG though, creating some intermediate Image class maybe. info->iconTexture = new Texture(); if (info->iconTexture->LoadPNG((const u8 *)info->iconTextureData.data(), info->iconTextureData.size(), false)) { @@ -547,7 +548,7 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { } { lock_guard lock(info->lock); - if (info->pic0TextureData.size()) { + if (info->pic0TextureData.size() && !info->pic0Texture) { info->pic0Texture = new Texture(); if (info->pic0Texture->LoadPNG((const u8 *)info->pic0TextureData.data(), info->pic0TextureData.size(), false)) { info->timePic0WasLoaded = time_now_d(); @@ -560,7 +561,7 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { } { lock_guard lock(info->lock); - if (info->pic1TextureData.size()) { + if (info->pic1TextureData.size() && !info->pic1Texture) { info->pic1Texture = new Texture(); if (info->pic1Texture->LoadPNG((const u8 *)info->pic1TextureData.data(), info->pic1TextureData.size(), false)) { info->timePic1WasLoaded = time_now_d(); @@ -577,8 +578,13 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { again: - GameInfo *info = new GameInfo(); - info->wantBG = wantBG; + if (!info) { + info = new GameInfo(); + } + { + lock_guard lock(info->lock); + info->wantBG = wantBG; + } GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info); gameInfoWQ_->Add(item); diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 8a79830fef..b2d8f6a8e3 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -47,6 +47,7 @@ public: GameInfo() : disc_total(0), disc_number(0), region(-1), fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false), iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantBG(false), + timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0), gameSize(0), saveDataSize(0), installDataSize(0) {} bool DeleteGame(); // Better be sure what you're doing when calling this. From 53547bd8b9629f7fdececd6458e9086214dbee56 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 13:49:30 -0700 Subject: [PATCH 2/9] Refactor a bit to simplify the code. --- UI/GameInfoCache.cpp | 59 ++++++++++++++------------------------------ UI/GameInfoCache.h | 2 ++ 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 0b5b926ef8..ce9957eda5 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -532,46 +532,9 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { // Need to start over. We'll just add a new work item. goto again; } - { - lock_guard lock(info->lock); - if (info->iconTextureData.size() && !info->iconTexture) { - // We'd have to split up Texture->LoadPNG though, creating some intermediate Image class maybe. - info->iconTexture = new Texture(); - if (info->iconTexture->LoadPNG((const u8 *)info->iconTextureData.data(), info->iconTextureData.size(), false)) { - info->timeIconWasLoaded = time_now_d(); - } else { - delete info->iconTexture; - info->iconTexture = 0; - } - info->iconTextureData.clear(); - } - } - { - lock_guard lock(info->lock); - if (info->pic0TextureData.size() && !info->pic0Texture) { - info->pic0Texture = new Texture(); - if (info->pic0Texture->LoadPNG((const u8 *)info->pic0TextureData.data(), info->pic0TextureData.size(), false)) { - info->timePic0WasLoaded = time_now_d(); - } else { - delete info->pic0Texture; - info->pic0Texture = 0; - } - info->pic0TextureData.clear(); - } - } - { - lock_guard lock(info->lock); - if (info->pic1TextureData.size() && !info->pic1Texture) { - info->pic1Texture = new Texture(); - if (info->pic1Texture->LoadPNG((const u8 *)info->pic1TextureData.data(), info->pic1TextureData.size(), false)) { - info->timePic1WasLoaded = time_now_d(); - } else { - delete info->pic1Texture; - info->pic1Texture = 0; - } - info->pic1TextureData.clear(); - } - } + SetupTexture(info, info->iconTextureData, info->iconTexture, info->timeIconWasLoaded); + SetupTexture(info, info->pic0TextureData, info->pic0Texture, info->timePic0WasLoaded); + SetupTexture(info, info->pic1TextureData, info->pic1Texture, info->timePic1WasLoaded); iter->second->lastAccessedTime = time_now_d(); return iter->second; } @@ -592,3 +555,19 @@ again: info_[gamePath] = info; return info; } + +void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Texture *&tex, double &loadTime) { + lock_guard lock(info->lock); + if (textureData.size()) { + if (!tex) { + tex = new Texture(); + if (tex->LoadPNG((const u8 *)textureData.data(), textureData.size(), false)) { + loadTime = time_now_d(); + } else { + delete tex; + tex = 0; + } + } + textureData.clear(); + } +} diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index b2d8f6a8e3..137b19d200 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -126,6 +126,8 @@ public: void Load(); private: + void SetupTexture(GameInfo *info, std::string &textureData, Texture *&tex, double &loadTime); + // Maps ISO path to info. std::map info_; From a22fb9289dee3b3fa9322ef3a678db6ea0efdf51 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 14:03:50 -0700 Subject: [PATCH 3/9] Load the icon on the game screen with the bg. Still looks nicer this way. --- UI/GameInfoCache.cpp | 4 ++-- UI/GameScreen.cpp | 11 ++++++++++- UI/MiscScreens.cpp | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index ce9957eda5..d216c8908a 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -341,8 +341,8 @@ handleELF: ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); if (info_->wantBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); } - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); break; } case FILETYPE_PSP_ISO: @@ -367,8 +367,8 @@ handleELF: if (info_->wantBG) { ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock); + ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); } - ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); } // Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 6f4f547cfb..9181fb27fb 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "base/colorutil.h" #include "base/timeutil.h" #include "gfx_es2/draw_buffer.h" @@ -97,7 +98,15 @@ void GameScreen::update(InputState &input) { tvTitle_->SetText(info->title + " (" + info->id + ")"); if (info->iconTexture && texvGameIcon_) { texvGameIcon_->SetTexture(info->iconTexture); - uint32_t color = whiteAlpha(ease((time_now_d() - info->timeIconWasLoaded) * 3)); + // Fade the icon with the background. + double loadTime = info->timeIconWasLoaded; + if (info->pic1Texture) { + loadTime = std::max(loadTime, info->timePic1WasLoaded); + } + if (info->pic0Texture) { + loadTime = std::max(loadTime, info->timePic0WasLoaded); + } + uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)); texvGameIcon_->SetColor(color); } diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index b9c78bca5f..66d5e7fb1b 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -110,15 +110,18 @@ void DrawGameBackground(UIContext &dc, const std::string &gamePath) { if (ginfo) { bool hasPic = false; + double loadTime; if (ginfo->pic1Texture) { ginfo->pic1Texture->Bind(0); + loadTime = ginfo->timePic1WasLoaded; hasPic = true; } else if (ginfo->pic0Texture) { ginfo->pic0Texture->Bind(0); + loadTime = ginfo->timePic0WasLoaded; hasPic = true; } if (hasPic) { - uint32_t color = whiteAlpha(ease((time_now_d() - ginfo->timePic1WasLoaded) * 3)) & 0xFFc0c0c0; + uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)) & 0xFFc0c0c0; dc.Draw()->DrawTexRect(dc.GetBounds(), 0,0,1,1, color); dc.Flush(); dc.RebindTexture(); From f4f3d280f726b89b578e191684e5e90093e450df Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 15:14:20 -0700 Subject: [PATCH 4/9] Avoid locking up the UI for gamecache loads. If the icon/bg is not loaded yet, we'd lock and block for it to load anyway. This uses a separate (or possibly atomic) lock. --- UI/GameInfoCache.cpp | 27 +++++++++++++++++++++------ UI/GameInfoCache.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index d216c8908a..bb02e5d506 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -293,12 +293,14 @@ public: } delete [] contents; } + info_->iconDataLoaded = true; } if (info_->wantBG) { if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); + info_->pic1DataLoaded = true; } } } @@ -319,6 +321,7 @@ handleELF: if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); + info_->iconDataLoaded = true; } delete [] contents; } @@ -339,9 +342,12 @@ handleELF: } ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); + info_->iconDataLoaded = true; if (info_->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; } break; } @@ -367,7 +373,9 @@ handleELF: if (info_->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; } } @@ -382,6 +390,7 @@ handleELF: } delete [] contents; } + info_->iconDataLoaded = true; break; } @@ -395,6 +404,7 @@ handleELF: if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); + info_->iconDataLoaded = true; } delete [] contents; } @@ -410,6 +420,7 @@ handleELF: if (contents) { lock_guard lock(info_->lock); info_->iconTextureData = std::string((const char *)contents, sz); + info_->iconDataLoaded = true; } delete [] contents; } @@ -455,8 +466,7 @@ void GameInfoCache::Shutdown() { StopProcessingWorkQueue(gameInfoWQ_); } -void GameInfoCache::Save() -{ +void GameInfoCache::Save() { // TODO } @@ -532,9 +542,15 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { // Need to start over. We'll just add a new work item. goto again; } - SetupTexture(info, info->iconTextureData, info->iconTexture, info->timeIconWasLoaded); - SetupTexture(info, info->pic0TextureData, info->pic0Texture, info->timePic0WasLoaded); - SetupTexture(info, info->pic1TextureData, info->pic1Texture, info->timePic1WasLoaded); + if (info->iconDataLoaded) { + SetupTexture(info, info->iconTextureData, info->iconTexture, info->timeIconWasLoaded); + } + if (info->pic0DataLoaded) { + SetupTexture(info, info->pic0TextureData, info->pic0Texture, info->timePic0WasLoaded); + } + if (info->pic1DataLoaded) { + SetupTexture(info, info->pic1TextureData, info->pic1Texture, info->timePic1WasLoaded); + } iter->second->lastAccessedTime = time_now_d(); return iter->second; } @@ -557,7 +573,6 @@ again: } void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Texture *&tex, double &loadTime) { - lock_guard lock(info->lock); if (textureData.size()) { if (!tex) { tex = new Texture(); diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 137b19d200..680baac671 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -42,6 +42,46 @@ enum GameRegion { GAMEREGION_MAX, }; +// TODO: Need to fix c++11 still on Symbian and use std::atomic instead. +class CompletionFlag { +public: + CompletionFlag() : pending(1) { + } + + void SetDone() { +#if defined(_WIN32) + _WriteBarrier(); + pending = 0; +#else + __sync_lock_release(&pending); +#endif + } + + bool IsDone() { + const bool done = pending == 0; +#if defined(_WIN32) + _ReadBarrier(); +#else + __sync_synchronize(); +#endif + return done; + } + + CompletionFlag &operator =(const bool &v) { + pending = v ? 0 : 1; + return *this; + } + + operator bool() { + return IsDone(); + } + +private: + volatile u32 pending; + + DISALLOW_COPY_AND_ASSIGN(CompletionFlag); +}; + class GameInfo { public: GameInfo() @@ -98,6 +138,10 @@ public: double timePic0WasLoaded; double timePic1WasLoaded; + CompletionFlag iconDataLoaded; + CompletionFlag pic0DataLoaded; + CompletionFlag pic1DataLoaded; + u64 gameSize; u64 saveDataSize; u64 installDataSize; From 73d77d3e8adb627d93d1e70b7b84f42c55ac8dbd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 18:04:00 -0700 Subject: [PATCH 5/9] Warning fix. --- GPU/GLES/DepalettizeShader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/DepalettizeShader.cpp b/GPU/GLES/DepalettizeShader.cpp index 48840c58e2..df409876e1 100644 --- a/GPU/GLES/DepalettizeShader.cpp +++ b/GPU/GLES/DepalettizeShader.cpp @@ -240,7 +240,7 @@ void GenerateDepalShader100(char *buffer, GEBufferFormat pixelFormat) { case GE_FORMAT_565: if ((mask & (mask + 1)) == 0 && shift < 16) { const u8 shifts[16] = {0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4}; - const u32 multipliers[16] = {31, 31, 31, 31, 31, 63, 63, 63, 63, 63, 63, 31, 31, 31, 31, 31}; + const int multipliers[16] = {31, 31, 31, 31, 31, 63, 63, 63, 63, 63, 63, 31, 31, 31, 31, 31}; const char *rgba = "rrrrrggggggbbbbb"; const u8 rgba_shift = shifts[shift]; if (rgba_shift == 0 && mask == multipliers[shift]) { From 0416f0d918bd26d3ad7c2af3a18da41fb89e23b1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 18:04:27 -0700 Subject: [PATCH 6/9] On main screen, show game bgs using controller. This won't affect touch UIs but it's a nice touch for controller based animation imho. --- UI/MainScreen.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++++- UI/MainScreen.h | 8 ++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index c1b1bacc6c..3feadee361 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -138,7 +138,13 @@ public: } } + virtual void FocusChanged(int focusFlags) { + UI::Clickable::FocusChanged(focusFlags); + TriggerOnHighlight(focusFlags); + } + UI::Event OnHoldClick; + UI::Event OnHighlight; private: void TriggerOnHoldClick() { @@ -149,6 +155,13 @@ private: down_ = false; OnHoldClick.Trigger(e); } + void TriggerOnHighlight(int focusFlags) { + UI::EventParams e; + e.v = this; + e.s = gamePath_; + e.a = focusFlags; + OnHighlight.Trigger(e); + } bool gridStyle_; std::string gamePath_; @@ -376,6 +389,7 @@ public: UI::Event OnChoice; UI::Event OnHoldChoice; + UI::Event OnHighlight; UI::Choice *HomebrewStoreButton() { return homebrewStoreButton_; } private: @@ -386,6 +400,7 @@ private: UI::EventReturn GameButtonClick(UI::EventParams &e); UI::EventReturn GameButtonHoldClick(UI::EventParams &e); + UI::EventReturn GameButtonHighlight(UI::EventParams &e); UI::EventReturn NavigateClick(UI::EventParams &e); UI::EventReturn LayoutChange(UI::EventParams &e); UI::EventReturn LastClick(UI::EventParams &e); @@ -568,6 +583,7 @@ void GameBrowser::Refresh() { GameButton *b = gameList_->Add(gameButtons[i]); b->OnClick.Handle(this, &GameBrowser::GameButtonClick); b->OnHoldClick.Handle(this, &GameBrowser::GameButtonHoldClick); + b->OnHighlight.Handle(this, &GameBrowser::GameButtonHighlight); } // Show a button to toggle pinning at the very end. @@ -667,6 +683,12 @@ UI::EventReturn GameBrowser::GameButtonHoldClick(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn GameBrowser::GameButtonHighlight(UI::EventParams &e) { + // Insta-update - here we know we are already on the right thread. + OnHighlight.Trigger(e); + return UI::EVENT_DONE; +} + UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) { DirButton *button = static_cast(e.v); std::string text = button->GetPath(); @@ -680,7 +702,7 @@ UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) { return UI::EVENT_DONE; } -MainScreen::MainScreen() : backFromStore_(false) { +MainScreen::MainScreen() : highlightProgress_(0.0f), prevHighlightProgress_(0.0f), backFromStore_(false) { System_SendMessage("event", "mainscreen"); } @@ -736,6 +758,9 @@ void MainScreen::CreateViews() { tabRecentGames->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected); tabAllGames->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected); tabHomebrew->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected); + tabRecentGames->OnHighlight.Handle(this, &MainScreen::OnGameHighlight); + tabAllGames->OnHighlight.Handle(this, &MainScreen::OnGameHighlight); + tabHomebrew->OnHighlight.Handle(this, &MainScreen::OnGameHighlight); if (g_Config.recentIsos.size() > 0) { leftColumn->SetCurrentTab(0); @@ -884,6 +909,59 @@ UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) { return UI::EVENT_DONE; } +extern void DrawBackground(UIContext &dc, float alpha); + +void MainScreen::DrawBackground(UIContext &dc) { + UIScreenWithBackground::DrawBackground(dc); + if (highlightedGamePath_.empty() && prevHighlightedGamePath_.empty()) { + return; + } + + if (DrawBackgroundFor(dc, prevHighlightedGamePath_, 1.0f - prevHighlightProgress_)) { + if (prevHighlightProgress_ < 1.0f) { + prevHighlightProgress_ += 1.0f / 20.0f; + } + } + if (!highlightedGamePath_.empty()) { + if (DrawBackgroundFor(dc, highlightedGamePath_, highlightProgress_)) { + if (highlightProgress_ < 1.0f) { + highlightProgress_ += 1.0f / 20.0f; + } + } + } +} + +bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, float progress) { + dc.Flush(); + + GameInfo *ginfo = 0; + if (!gamePath.empty()) { + ginfo = g_gameInfoCache.GetInfo(gamePath, true); + // Loading texture data may bind a texture. + dc.RebindTexture(); + + // Let's not bother if there's no picture. + if (!ginfo || (!ginfo->pic1Texture && !ginfo->pic0Texture)) { + return false; + } + } else { + return false; + } + + if (ginfo->pic1Texture) { + ginfo->pic1Texture->Bind(0); + } else if (ginfo->pic0Texture) { + ginfo->pic0Texture->Bind(0); + } + + uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0; + dc.Draw()->DrawTexRect(dc.GetBounds(), 0,0,1,1, color); + dc.Flush(); + dc.RebindTexture(); + + return true; +} + UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) { #ifdef _WIN32 std::string path = ReplaceAll(e.s, "\\", "/"); @@ -894,6 +972,27 @@ UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) { return UI::EVENT_DONE; } +UI::EventReturn MainScreen::OnGameHighlight(UI::EventParams &e) { + #ifdef _WIN32 + std::string path = ReplaceAll(e.s, "\\", "/"); +#else + std::string path = e.s; +#endif + + if (!highlightedGamePath_.empty() || (e.a == FF_LOSTFOCUS && highlightedGamePath_ == path)) { + if (prevHighlightedGamePath_.empty() || prevHighlightProgress_ >= 0.75f) { + prevHighlightedGamePath_ = highlightedGamePath_; + prevHighlightProgress_ = 1.0 - highlightProgress_; + } + highlightedGamePath_.clear(); + } + if (e.a == FF_GOTFOCUS) { + highlightedGamePath_ = path; + highlightProgress_ = 0.0f; + } + return UI::EVENT_DONE; +} + UI::EventReturn MainScreen::OnGameSelectedInstant(UI::EventParams &e) { #ifdef _WIN32 std::string path = ReplaceAll(e.s, "\\", "/"); diff --git a/UI/MainScreen.h b/UI/MainScreen.h index 791aa28e78..093cbf5a73 100644 --- a/UI/MainScreen.h +++ b/UI/MainScreen.h @@ -37,13 +37,17 @@ public: protected: virtual void CreateViews(); + virtual void DrawBackground(UIContext &dc); virtual void update(InputState &input); virtual void sendMessage(const char *message, const char *value); virtual void dialogFinished(const Screen *dialog, DialogResult result); private: + bool DrawBackgroundFor(UIContext &dc, const std::string &gamePath, float progress); + UI::EventReturn OnGameSelected(UI::EventParams &e); UI::EventReturn OnGameSelectedInstant(UI::EventParams &e); + UI::EventReturn OnGameHighlight(UI::EventParams &e); // Event handlers UI::EventReturn OnLoadFile(UI::EventParams &e); UI::EventReturn OnGameSettings(UI::EventParams &e); @@ -60,6 +64,10 @@ private: UI::LinearLayout *upgradeBar_; UI::TabHolder *tabHolder_; + std::string highlightedGamePath_; + std::string prevHighlightedGamePath_; + float highlightProgress_; + float prevHighlightProgress_; bool backFromStore_; }; From a0340debd6151b71fb9d7825b95dab4023320c6f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 18:24:21 -0700 Subject: [PATCH 7/9] Use flags to specify wanted data in gamecache. --- UI/GameInfoCache.cpp | 22 +++++++++------------- UI/GameInfoCache.h | 11 ++++++++--- UI/GameScreen.cpp | 16 ++++++++-------- UI/GameSettingsScreen.cpp | 2 +- UI/MainScreen.cpp | 4 ++-- UI/MiscScreens.cpp | 2 +- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index bb02e5d506..cad1734a91 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -296,7 +296,7 @@ public: info_->iconDataLoaded = true; } - if (info_->wantBG) { + if (info_->wantFlags & GAMEINFO_WANTBG) { if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); @@ -343,7 +343,7 @@ handleELF: ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock); info_->iconDataLoaded = true; - if (info_->wantBG) { + 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); @@ -371,7 +371,7 @@ handleELF: info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size()); info_->ParseParamSFO(); - if (info_->wantBG) { + 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); @@ -396,7 +396,6 @@ handleELF: case FILETYPE_ARCHIVE_ZIP: info_->paramSFOLoaded = true; - info_->wantBG = false; { // Read standard icon size_t sz; @@ -412,7 +411,6 @@ handleELF: case FILETYPE_ARCHIVE_RAR: info_->paramSFOLoaded = true; - info_->wantBG = false; { // Read standard icon size_t sz; @@ -429,12 +427,10 @@ handleELF: case FILETYPE_NORMAL_DIRECTORY: default: info_->paramSFOLoaded = true; - info_->wantBG = false; break; } - // probably only want these when we ask for the background image... - // should maybe flip the flag to "onlyIcon" - if (info_->wantBG) { + + if (info_->wantFlags & GAMEINFO_WANTSIZE) { info_->gameSize = info_->GetGameSizeInBytes(); info_->saveDataSize = info_->GetSaveDataSizeInBytes(); info_->installDataSize = info_->GetInstallDataSizeInBytes(); @@ -525,20 +521,20 @@ void GameInfoCache::FlushBGs() { delete iter->second->pic1Texture; iter->second->pic1Texture = 0; } - iter->second->wantBG = false; + iter->second->wantFlags &= ~GAMEINFO_WANTBG; } } // This may run off-main-thread and we thus can't use the global // pspFileSystem (well, we could with synchronization but there might not // even be a game running). -GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { +GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, int wantFlags) { GameInfo *info = 0; auto iter = info_.find(gamePath); if (iter != info_.end()) { info = iter->second; - if (!info->wantBG && wantBG) { + if ((info->wantFlags & wantFlags) != wantFlags) { // Need to start over. We'll just add a new work item. goto again; } @@ -562,7 +558,7 @@ again: } { lock_guard lock(info->lock); - info->wantBG = wantBG; + info->wantFlags |= wantFlags; } GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info); diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 680baac671..51998cf211 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -42,6 +42,11 @@ enum GameRegion { GAMEREGION_MAX, }; +enum GameInfoWantFlags { + GAMEINFO_WANTBG = 0x01, + GAMEINFO_WANTSIZE = 0x02, +}; + // TODO: Need to fix c++11 still on Symbian and use std::atomic instead. class CompletionFlag { public: @@ -86,7 +91,7 @@ class GameInfo { public: GameInfo() : disc_total(0), disc_number(0), region(-1), fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false), - iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantBG(false), + iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantFlags(0), timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0), gameSize(0), saveDataSize(0), installDataSize(0) {} @@ -128,7 +133,7 @@ public: std::string pic1TextureData; Texture *pic1Texture; - bool wantBG; + int wantFlags; double lastAccessedTime; @@ -161,7 +166,7 @@ public: // but filled in later asynchronously in the background. So keep calling this, // redrawing the UI often. Only set wantBG if you really want it because // it's big. bgTextures may be discarded over time as well. - GameInfo *GetInfo(const std::string &gamePath, bool wantBG); + GameInfo *GetInfo(const std::string &gamePath, int wantFlags); void Decimate(); // Deletes old info. void FlushBGs(); // Gets rid of all BG textures. diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 9181fb27fb..df36195c7e 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -35,7 +35,7 @@ #include "Core/Config.h" void GameScreen::CreateViews() { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); I18NCategory *d = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); @@ -92,7 +92,7 @@ void GameScreen::update(InputState &input) { UIScreen::update(input); I18NCategory *ga = GetI18NCategory("Game"); - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (tvTitle_) tvTitle_->SetText(info->title + " (" + info->id + ")"); @@ -153,7 +153,7 @@ UI::EventReturn GameScreen::OnPlay(UI::EventParams &e) { } UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info && info->paramSFOLoaded) { std::string discID = info->paramSFO.GetValueString("DISC_ID"); screenManager()->push(new GameSettingsScreen(gamePath_, discID)); @@ -164,7 +164,7 @@ UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) { UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) { I18NCategory *d = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info) { screenManager()->push( new PromptScreen(d->T("DeleteConfirmAll", "Do you really want to delete all\nyour save data for this game?"), ga->T("ConfirmDelete"), d->T("Cancel"), @@ -176,7 +176,7 @@ UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) { } void GameScreen::CallbackDeleteSaveData(bool yes) { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0); if (yes) { info->DeleteAllSaveData(); info->saveDataSize = 0; @@ -187,7 +187,7 @@ void GameScreen::CallbackDeleteSaveData(bool yes) { UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) { I18NCategory *d = GetI18NCategory("Dialog"); I18NCategory *ga = GetI18NCategory("Game"); - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); if (info) { screenManager()->push( new PromptScreen(d->T("DeleteConfirmGame", "Do you really want to delete this game\nfrom your device? You can't undo this."), ga->T("ConfirmDelete"), d->T("Cancel"), @@ -198,7 +198,7 @@ UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) { } void GameScreen::CallbackDeleteGame(bool yes) { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0); if (yes) { info->DeleteGame(); g_gameInfoCache.Clear(); @@ -207,7 +207,7 @@ void GameScreen::CallbackDeleteGame(bool yes) { } UI::EventReturn GameScreen::OnCreateShortcut(UI::EventParams &e) { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0); if (info) { host->CreateDesktopShortcut(gamePath_, info->title); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 56b172bbb9..42cbc0997f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -54,7 +54,7 @@ extern bool iosCanUseJit; #endif void GameSettingsScreen::CreateViews() { - GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); + GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE); cap60FPS_ = g_Config.iForceMaxEmulatedFPS == 60; diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 3feadee361..286bc76175 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -173,7 +173,7 @@ private: }; void GameButton::Draw(UIContext &dc) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath_, false); + GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath_, 0); Texture *texture = 0; u32 color = 0, shadowColor = 0; @@ -936,7 +936,7 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f GameInfo *ginfo = 0; if (!gamePath.empty()) { - ginfo = g_gameInfoCache.GetInfo(gamePath, true); + ginfo = g_gameInfoCache.GetInfo(gamePath, GAMEINFO_WANTBG); // Loading texture data may bind a texture. dc.RebindTexture(); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 66d5e7fb1b..e0bccc56ae 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -105,7 +105,7 @@ void DrawBackground(UIContext &dc, float alpha = 1.0f) { } void DrawGameBackground(UIContext &dc, const std::string &gamePath) { - GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath, true); + GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath, GAMEINFO_WANTBG); dc.Flush(); if (ginfo) { From a6436d04f5cf96164b478700d16413665ef0c33a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 18:29:54 -0700 Subject: [PATCH 8/9] Support PIC0 in PBP files. --- Core/ELF/PBPReader.h | 2 +- UI/GameInfoCache.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/ELF/PBPReader.h b/Core/ELF/PBPReader.h index 791365af12..ab68ea73ba 100644 --- a/Core/ELF/PBPReader.h +++ b/Core/ELF/PBPReader.h @@ -24,7 +24,7 @@ enum PBPSubFile { PBP_PARAM_SFO, PBP_ICON0_PNG, PBP_ICON1_PMF, - PBP_UNKNOWN_PNG, // PIC0? + PBP_PIC0_PNG, PBP_PIC1_PNG, PBP_SND0_AT3, PBP_EXECUTABLE_PSP, diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index cad1734a91..2fdb9d23bc 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -297,6 +297,11 @@ public: } if (info_->wantFlags & GAMEINFO_WANTBG) { + if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) { + lock_guard lock(info_->lock); + pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0TextureData); + info_->pic0DataLoaded = true; + } if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) { lock_guard lock(info_->lock); pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData); From d5ddf4c438354c9147e8ea323e50aa51f9293c9d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 21 Jun 2014 18:38:26 -0700 Subject: [PATCH 9/9] Make it easy to get the SND0.AT3 data. --- UI/GameInfoCache.cpp | 15 +++++++++++++++ UI/GameInfoCache.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 2fdb9d23bc..34cd18e2a0 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -308,6 +308,13 @@ public: info_->pic1DataLoaded = true; } } + if (info_->wantFlags & GAMEINFO_WANTSND) { + if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) { + lock_guard lock(info_->lock); + pbp.GetSubFileAsString(PBP_SND0_AT3, &info_->sndFileData); + info_->sndDataLoaded = true; + } + } } break; @@ -354,6 +361,10 @@ handleELF: ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } + if (info_->wantFlags & GAMEINFO_WANTSND) { + ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); + info_->pic1DataLoaded = true; + } break; } case FILETYPE_PSP_ISO: @@ -382,6 +393,10 @@ handleELF: ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock); info_->pic1DataLoaded = true; } + if (info_->wantFlags & GAMEINFO_WANTSND) { + ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock); + info_->pic1DataLoaded = true; + } } // Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 51998cf211..47ca650c91 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -45,6 +45,7 @@ enum GameRegion { enum GameInfoWantFlags { GAMEINFO_WANTBG = 0x01, GAMEINFO_WANTSIZE = 0x02, + GAMEINFO_WANTSND = 0x04, }; // TODO: Need to fix c++11 still on Symbian and use std::atomic instead. @@ -133,6 +134,8 @@ public: std::string pic1TextureData; Texture *pic1Texture; + std::string sndFileData; + int wantFlags; double lastAccessedTime; @@ -146,6 +149,7 @@ public: CompletionFlag iconDataLoaded; CompletionFlag pic0DataLoaded; CompletionFlag pic1DataLoaded; + CompletionFlag sndDataLoaded; u64 gameSize; u64 saveDataSize;