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 <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-09 16:25:13 -06:00
1 parent 63eb3d5b21
commit 29c5d1baf1
3 files changed
+23 -6

No files matched your search

+12
View File
@@ -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")));
+3 -2
View File
@@ -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.
+8 -4
View File
@@ -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;