From 29c5d1baf1124aae13145fdcad9ced70e5483210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 9 Sep 2026 16:25:13 -0600 Subject: [PATCH] Offer to install the disc's firmware updater from the game context menu The game screen already reports which updater a disc carries, but there was no way to act on it - the only route to installing one was picking an updater PBP out of the browser. The unpacker already handles being pointed at a disc, so this just wires the menu entry to it. Shown only when the disc actually has one, and not while a game is running: installing wipes the NAND that game has mounted. InstallUpdateScreen takes the archive size now, because for a disc the size of the file it was handed is the game's and says nothing about the firmware. Co-Authored-By: Claude Opus 5 --- UI/GameScreen.cpp | 12 ++++++++++++ UI/InstallUpdateScreen.cpp | 5 +++-- UI/InstallUpdateScreen.h | 12 ++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 66f071efb0..86c01d86c8 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -51,6 +51,7 @@ #include "UI/GameScreen.h" #include "UI/GameSettingsScreen.h" #include "UI/GameInfoCache.h" +#include "UI/InstallUpdateScreen.h" #include "UI/BaseScreens.h" #include "UI/MiscScreens.h" #include "UI/MainScreen.h" @@ -658,6 +659,17 @@ void GameScreen::CreateContextMenu(UI::ViewGroup *parent) { btnDeleteUpdate->OnClick.Handle(this, &GameScreen::OnDeleteGameUpdate); } + // Most discs carry a firmware updater, and the firmware inside it is what our flash0 wants. + // Not while a game is running, though - installing wipes the NAND the running game has mounted. + if (!inGame_ && (knownFlags_ & GameInfoFlags::BUNDLED_UPDATE_INFO) && info_->bundledUpdate.present) { + auto iz = GetI18NCategory(I18NCat::INSTALLZIP); + Choice *btnInstallFirmware = parent->Add(new Choice(iz->T("Install PSP firmware update"), ImageID("I_FOLDER_UPLOAD"))); + const BundledUpdateInfo update = info_->bundledUpdate; + btnInstallFirmware->OnClick.Add([this, update](UI::EventParams &e) { + screenManager()->push(new InstallUpdateScreen(gamePath_, update.title, false, update.archiveSize)); + }); + } + // Don't want to be able to delete the game while it's running. if (!inGame_) { Choice *deleteChoice = parent->Add(new Choice(ga->T("Delete Game"), ImageID("I_WARNING"))); diff --git a/UI/InstallUpdateScreen.cpp b/UI/InstallUpdateScreen.cpp index 6a0e98e453..8cb94d2458 100644 --- a/UI/InstallUpdateScreen.cpp +++ b/UI/InstallUpdateScreen.cpp @@ -36,12 +36,13 @@ #include "UI/MiscViews.h" #include "UI/EmuScreen.h" -InstallUpdateScreen::InstallUpdateScreen(const Path &path, std::string_view title, bool allowRun) +InstallUpdateScreen::InstallUpdateScreen(const Path &path, std::string_view title, bool allowRun, u64 archiveSize) : UISimpleBaseDialogScreen(Path(), SimpleDialogFlags::ContentsCanScroll), path_(path), title_(title), allowRun_(allowRun) { destination_ = GetSysDirectory(DIRECTORY_NAND); + fileSize_ = archiveSize; File::FileInfo fileInfo; - if (File::GetFileInfo(path_, &fileInfo)) { + if (fileSize_ == 0 && File::GetFileInfo(path_, &fileInfo)) { fileSize_ = fileInfo.size; } // There's no practical way to merge two firmwares, so an install replaces whatever is there. diff --git a/UI/InstallUpdateScreen.h b/UI/InstallUpdateScreen.h index 7c7933fc6e..69b7eb1da1 100644 --- a/UI/InstallUpdateScreen.h +++ b/UI/InstallUpdateScreen.h @@ -33,15 +33,19 @@ #include "UI/BaseScreens.h" #include "UI/SimpleDialogScreen.h" -// An official PSP firmware updater (a PSP/GAME/UPDATE/EBOOT.PBP, or the folder holding one). -// Running it isn't going to get anyone anywhere, but the firmware inside it is exactly what the -// emulated flash0/flash1 want, so offer to unpack it into the NAND directory instead. +// An official PSP firmware updater: a PSP/GAME/UPDATE/EBOOT.PBP (or the folder holding one), or +// a game disc, most of which carry one at PSP_GAME/SYSDIR/UPDATE/DATA.BIN. Running an updater +// isn't going to get anyone anywhere, but the firmware inside it is exactly what the emulated +// flash0/flash1 want, so offer to unpack it into the NAND directory instead. class InstallUpdateScreen : public UISimpleBaseDialogScreen { public: // title is the updater's SFO title, which already carries the version ("PSP Update ver 6.61"). // allowRun offers to boot the updater instead of unpacking it - which makes sense when the // user picked the updater to launch it, but not when they came here to install a firmware. - InstallUpdateScreen(const Path &path, std::string_view title, bool allowRun); + // archiveSize is how big the firmware itself is; pass it for a disc, where the size of the + // file we were handed is the game's and says nothing about what's being installed. Zero means + // "the file is the updater", which is the PBP case. + InstallUpdateScreen(const Path &path, std::string_view title, bool allowRun, u64 archiveSize = 0); void CreateDialogViews(UI::ViewGroup *parent) override; void update() override;