Merge pull request #20686 from hrydgard/pic0-support

PIC0 support
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2025-08-03 09:37:57 +02:00
commit ef87839b86
8 files changed
+92 -35

No files matched your search

+2 -2
View File
@@ -1834,7 +1834,7 @@ void LoongArch64Emitter::SetRegToImmediate(LoongArch64Reg rd, uint64_t value) {
return;
}
if (svalue <= 0x7fffffffl && svalue >= -0x80000000l) {
if (svalue <= 0x7fffffffll && svalue >= -0x80000000ll) {
// Use lu12i.w/ori to load 32-bits immediate.
LU12I_W(rd, (s32)((svalue & 0xffffffff) >> 12));
ORI(rd, rd, (s16)(svalue & 0xFFF));
@@ -6328,4 +6328,4 @@ void LoongArch64CodeBlock::PoisonMemory(int offset) {
*ptr++ = 0x002a0000;
}
};
};
+2 -2
View File
@@ -1177,11 +1177,11 @@ public:
void Draw(UIContext &dc) override {
// Should only be called when visible.
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::BG);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath_, GameInfoFlags::PIC1);
dc.Flush();
// PIC1 is the loading image, so let's only draw if it's available.
if (ginfo->Ready(GameInfoFlags::BG) && ginfo->pic1.texture) {
if (ginfo->Ready(GameInfoFlags::PIC1) && ginfo->pic1.texture) {
Draw::Texture *texture = ginfo->pic1.texture;
if (texture) {
dc.GetDrawContext()->BindTexture(0, texture);
+12 -5
View File
@@ -604,7 +604,7 @@ public:
info_->icon.dataLoaded = true;
}
if (flags_ & GameInfoFlags::BG) {
if (flags_ & GameInfoFlags::PIC0) {
if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) {
std::string data;
pbp.GetSubFileAsString(PBP_PIC0_PNG, &data);
@@ -612,6 +612,8 @@ public:
info_->pic0.data = std::move(data);
info_->pic0.dataLoaded = true;
}
}
if (flags_ & GameInfoFlags::PIC1) {
if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) {
std::string data;
pbp.GetSubFileAsString(PBP_PIC1_PNG, &data);
@@ -679,7 +681,7 @@ handleELF:
ReadFileToString(&umd, "/ICON0.PNG", &info_->icon.data, &info_->lock);
info_->icon.dataLoaded = true;
}
if (flags_ & GameInfoFlags::BG) {
if (flags_ & GameInfoFlags::PIC1) {
ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1.data, &info_->lock);
info_->pic1.dataLoaded = true;
}
@@ -735,9 +737,11 @@ handleELF:
ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock);
info_->icon.dataLoaded = true;
}
if (flags_ & GameInfoFlags::BG) {
if (flags_ & GameInfoFlags::PIC0) {
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
info_->pic0.dataLoaded = true;
}
if (flags_ & GameInfoFlags::PIC1) {
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
info_->pic1.dataLoaded = true;
}
@@ -787,8 +791,11 @@ handleELF:
}
}
if (flags_ & GameInfoFlags::BG) {
if (flags_ & GameInfoFlags::PIC0) {
info_->pic0.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0.data, &info_->lock);
}
if (flags_ & GameInfoFlags::PIC1) {
info_->pic1.dataLoaded = ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1.data, &info_->lock);
}
@@ -933,7 +940,7 @@ void GameInfoCache::FlushBGs() {
iter->second->sndFileData.clear();
iter->second->sndDataLoaded = false;
}
iter->second->hasFlags &= ~(GameInfoFlags::BG | GameInfoFlags::SND);
iter->second->hasFlags &= ~(GameInfoFlags::PIC0 | GameInfoFlags::PIC1 | GameInfoFlags::SND);
}
}
+7 -8
View File
@@ -42,10 +42,11 @@ 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,
PIC1 = 0x08,
PIC0 = 0x10,
SND = 0x20,
SIZE = 0x40,
UNCOMPRESSED_SIZE = 0x80,
};
ENUM_CLASS_BITOPS(GameInfoFlags);
@@ -120,11 +121,9 @@ public:
pendingFlags &= ~flags;
}
GameInfoTex *GetBGPic() {
GameInfoTex *GetPIC1() {
if (pic1.texture)
return &pic1;
if (pic0.texture)
return &pic0;
return nullptr;
}
@@ -150,7 +149,7 @@ public:
IdentifiedFileType fileType;
bool hasConfig = false;
// Pre read the data, create a texture the next time (GL thread..)
// Pre read the data, create a texture the next time
GameInfoTex icon;
GameInfoTex pic0;
GameInfoTex pic1;
+59 -8
View File
@@ -96,7 +96,7 @@ void GameScreen::update() {
}
void GameScreen::CreateViews() {
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::BG);
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::PIC0 | GameInfoFlags::PIC1);
auto di = GetI18NCategory(I18NCat::DIALOG);
auto ga = GetI18NCategory(I18NCat::GAME);
@@ -347,12 +347,20 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
auto ga = GetI18NCategory(I18NCat::GAME);
Draw::DrawContext *draw = screenManager()->getDrawContext();
UIContext &dc = *screenManager()->getUIContext();
Draw::DrawContext *draw = dc.GetDrawContext();
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(draw, gamePath_, GameInfoFlags::BG | GameInfoFlags::SIZE | GameInfoFlags::UNCOMPRESSED_SIZE);
float maxY = 0;
// NOTE: This won't be correct the first frame.
auto updateMaxY = [&](UI::View *v) {
maxY = std::max(maxY, v->GetBounds().y2());
};
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(draw, gamePath_, GameInfoFlags::PIC1 | GameInfoFlags::SIZE | GameInfoFlags::UNCOMPRESSED_SIZE);
if (tvTitle_) {
tvTitle_->SetText(info->GetTitle());
updateMaxY(tvTitle_);
}
if (info->Ready(GameInfoFlags::SIZE | GameInfoFlags::UNCOMPRESSED_SIZE)) {
@@ -364,6 +372,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
snprintf(temp + len, sizeof(temp) - len, " (%s: %s)", ga->T_cstr("Uncompressed"), NiceSizeFormat(info->gameSizeUncompressed).c_str());
}
tvGameSize_->SetText(temp);
updateMaxY(tvGameSize_);
}
if (tvSaveDataSize_) {
if (info->saveDataSize > 0) {
@@ -372,12 +381,14 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
} else {
tvSaveDataSize_->SetVisibility(UI::V_GONE);
}
updateMaxY(tvSaveDataSize_);
}
if (info->installDataSize > 0 && tvInstallDataSize_) {
snprintf(temp, sizeof(temp), "%s: %1.2f %s", ga->T_cstr("InstallData"), (float) (info->installDataSize) / 1024.f / 1024.f, ga->T_cstr("MB"));
tvInstallDataSize_->SetText(temp);
tvInstallDataSize_->SetVisibility(UI::V_VISIBLE);
}
updateMaxY(tvInstallDataSize_);
}
if (tvRegion_) {
@@ -386,6 +397,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
} else {
tvRegion_->SetText(ga->T(GameRegionToString(info->region)));
}
updateMaxY(tvRegion_);
}
if (tvPlayTime_) {
@@ -394,6 +406,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
tvPlayTime_->SetText(str);
tvPlayTime_->SetVisibility(UI::V_VISIBLE);
}
updateMaxY(tvPlayTime_);
}
if (tvCRC_ && Reporting::HasCRC(gamePath_)) {
@@ -431,6 +444,9 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
// tvVerified_->SetLevel(NoticeLevel::WARN);
tvVerified_->SetVisibility(UI::V_GONE);
}
updateMaxY(tvCRC_);
updateMaxY(tvVerified_);
} else if (!isHomebrew_) {
GameDBInfo dbInfo;
if (tvVerified_) {
@@ -458,11 +474,13 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
tvVerified_->SetLevel(NoticeLevel::INFO);
}
}
updateMaxY(tvVerified_);
}
}
if (tvID_) {
tvID_->SetText(ReplaceAll(info->id_version, "_", " v"));
updateMaxY(tvID_);
}
if (!info->id.empty()) {
@@ -473,7 +491,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
if (info->saveDataSize) {
btnDeleteSaveData_->SetVisibility(UI::V_VISIBLE);
}
if (info->pic0.texture || info->pic1.texture) {
if (info->pic1.texture) {
btnSetBackground_->SetVisibility(UI::V_VISIBLE);
}
}
@@ -484,6 +502,41 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) {
choice->SetVisibility(UI::V_VISIBLE);
}
}
if (info->Ready(GameInfoFlags::PIC0) && info->pic0.texture) {
// Draw PIC0 as an overlay.
bool draw = true;
const float w = dc.GetBounds().w - 500;
const float h = w * (info->pic0.texture->Height() / (float)info->pic0.texture->Width());
// Bottom align the image.
Bounds bounds(180, dc.GetBounds().h - h - 10, w, h);
maxY += 20;
if (bounds.y < maxY) {
// Recalculate.
bounds.h = dc.GetBounds().h - 10 - maxY;
if (bounds.h < 0) {
// let's not draw it.
draw = false;
}
bounds.w = bounds.h * (info->pic0.texture->Width() / (float)info->pic0.texture->Height());
bounds.y = dc.GetBounds().h - 10 - bounds.h;
}
if (draw) {
dc.Flush();
dc.GetDrawContext()->BindTexture(0, info->pic0.texture);
uint32_t color = 0xFFFFFFFF;
dc.Draw()->DrawTexRect(bounds, 0, 0, 1, 1, color);
dc.Flush();
dc.Begin();
}
}
return flags;
}
@@ -613,13 +666,11 @@ void SetBackgroundPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
void SetBackgroundPopupScreen::update() {
PopupScreen::update();
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::BG);
if (status_ == Status::PENDING && info->Ready(GameInfoFlags::BG)) {
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PIC1);
if (status_ == Status::PENDING && info->Ready(GameInfoFlags::PIC1)) {
GameInfoTex *pic = nullptr;
if (info->pic1.dataLoaded && info->pic1.data.size()) {
pic = &info->pic1;
} else if (info->pic0.dataLoaded && info->pic0.data.size()) {
pic = &info->pic0;
}
if (pic) {
+3 -3
View File
@@ -1449,19 +1449,19 @@ 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, GameInfoFlags::BG);
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GameInfoFlags::PIC1);
// Loading texture data may bind a texture.
dc.RebindTexture();
// Let's not bother if there's no picture.
if (!ginfo->Ready(GameInfoFlags::BG) || (!ginfo->pic1.texture && !ginfo->pic0.texture)) {
if (!ginfo->Ready(GameInfoFlags::PIC1) || !ginfo->pic1.texture) {
return false;
}
} else {
return false;
}
auto pic = ginfo->GetBGPic();
auto pic = ginfo->GetPIC1();
Draw::Texture *texture = pic ? pic->texture : nullptr;
uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0;
+6 -6
View File
@@ -246,11 +246,11 @@ private:
}
std::shared_ptr<GameInfo> ginfo = GetInfo(dc, index);
if (ginfo && !ginfo->Ready(GameInfoFlags::BG)) {
if (ginfo && !ginfo->Ready(GameInfoFlags::PIC1)) {
// Wait for it to load. It might be the next one.
break;
}
if (ginfo && (ginfo->pic1.texture || ginfo->pic0.texture)) {
if (ginfo && ginfo->pic1.texture) {
nextIndex_ = index;
nextT_ = t + INTERVAL;
break;
@@ -267,13 +267,13 @@ private:
const auto recentIsos = g_recentFiles.GetRecentFiles();
if (index >= (int)recentIsos.size())
return std::shared_ptr<GameInfo>();
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(recentIsos[index]), GameInfoFlags::BG);
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(recentIsos[index]), GameInfoFlags::PIC1);
}
static void DrawTex(UIContext &dc, std::shared_ptr<GameInfo> &ginfo, float amount) {
if (!ginfo || amount <= 0.0f)
return;
GameInfoTex *pic = ginfo->GetBGPic();
GameInfoTex *pic = ginfo->GetPIC1();
if (!pic)
return;
@@ -488,10 +488,10 @@ void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, f
std::shared_ptr<GameInfo> ginfo;
if (!gamePath.empty()) {
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GameInfoFlags::BG);
ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GameInfoFlags::PIC1);
}
GameInfoTex *pic = (ginfo && ginfo->Ready(GameInfoFlags::BG)) ? ginfo->GetBGPic() : nullptr;
GameInfoTex *pic = (ginfo && ginfo->Ready(GameInfoFlags::PIC1)) ? ginfo->GetPIC1() : nullptr;
if (pic) {
dc.GetDrawContext()->BindTexture(0, pic->texture);
uint32_t color = whiteAlpha(ease((time_now_d() - pic->timeLoaded) * 3)) & 0xFFc0c0c0;
+1 -1
View File
@@ -748,7 +748,7 @@ void GameIconView::Draw(UIContext &dc) {
// Fade icon with the backgrounds.
double loadTime = info->icon.timeLoaded;
auto pic = info->GetBGPic();
auto pic = info->GetPIC1();
if (pic) {
loadTime = std::max(loadTime, pic->timeLoaded);
}