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;