move fw install
Signed-off-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
11db0f0dbf
commit
7a0712af1f
4 changed files with 155 additions and 97 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "qt_common.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "uisettings.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
|
@ -21,17 +22,18 @@ MetadataResult ResetMetadata()
|
|||
{
|
||||
if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir)
|
||||
/ "game_list/")) {
|
||||
return Empty;
|
||||
return MetadataResult::Empty;
|
||||
} else if (Common::FS::RemoveDirRecursively(
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) {
|
||||
return Success;
|
||||
return MetadataResult::Success;
|
||||
UISettings::values.is_game_list_reload_pending.exchange(true);
|
||||
} else {
|
||||
return Failure;
|
||||
return MetadataResult::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
Core::Frontend::WindowSystemType GetWindowSystemType() {
|
||||
Core::Frontend::WindowSystemType GetWindowSystemType()
|
||||
{
|
||||
// Determine WSI type based on Qt platform.
|
||||
QString platform_name = QGuiApplication::platformName();
|
||||
if (platform_name == QStringLiteral("windows"))
|
||||
|
@ -51,7 +53,8 @@ Core::Frontend::WindowSystemType GetWindowSystemType() {
|
|||
return Core::Frontend::WindowSystemType::Windows;
|
||||
} // namespace Core::Frontend::WindowSystemType
|
||||
|
||||
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) {
|
||||
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
|
||||
{
|
||||
Core::Frontend::EmuWindow::WindowSystemInfo wsi;
|
||||
wsi.type = GetWindowSystemType();
|
||||
|
||||
|
@ -59,8 +62,8 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
|
|||
// Our Win32 Qt external doesn't have the private API.
|
||||
wsi.render_surface = reinterpret_cast<void*>(window->winId());
|
||||
#elif defined(__APPLE__)
|
||||
wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)(
|
||||
reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
|
||||
wsi.render_surface = reinterpret_cast<void* (*) (id, SEL)>(
|
||||
objc_msgSend)(reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
|
||||
#else
|
||||
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||
wsi.display_connection = pni->nativeResourceForWindow("display", window);
|
||||
|
@ -74,4 +77,92 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window)
|
|||
return wsi;
|
||||
}
|
||||
|
||||
FirmwareInstallResult InstallFirmware(const QString& location,
|
||||
bool recursive,
|
||||
std::function<bool(size_t, size_t)> QtProgressCallback,
|
||||
Core::System* system,
|
||||
FileSys::VfsFilesystem* vfs)
|
||||
{
|
||||
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
||||
|
||||
// Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in
|
||||
// there.)
|
||||
std::filesystem::path firmware_source_path = location.toStdString();
|
||||
if (!Common::FS::IsDir(firmware_source_path)) {
|
||||
return FirmwareInstallResult::NoOp;
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> out;
|
||||
const Common::FS::DirEntryCallable callback =
|
||||
[&out](const std::filesystem::directory_entry& entry) {
|
||||
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
|
||||
out.emplace_back(entry.path());
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
QtProgressCallback(100, 10);
|
||||
|
||||
if (recursive) {
|
||||
Common::FS::IterateDirEntriesRecursively(firmware_source_path,
|
||||
callback,
|
||||
Common::FS::DirEntryFilter::File);
|
||||
} else {
|
||||
Common::FS::IterateDirEntries(firmware_source_path,
|
||||
callback,
|
||||
Common::FS::DirEntryFilter::File);
|
||||
}
|
||||
|
||||
if (out.size() <= 0) {
|
||||
return FirmwareInstallResult::NoNCAs;
|
||||
}
|
||||
|
||||
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
|
||||
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
|
||||
if (!sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
|
||||
return FirmwareInstallResult::FailedDelete;
|
||||
}
|
||||
|
||||
LOG_INFO(Frontend,
|
||||
"Cleaned nand/system/Content/registered folder in preparation for new firmware.");
|
||||
|
||||
QtProgressCallback(100, 20);
|
||||
|
||||
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
||||
|
||||
bool success = true;
|
||||
int i = 0;
|
||||
for (const auto& firmware_src_path : out) {
|
||||
i++;
|
||||
auto firmware_src_vfile = vfs->OpenFile(firmware_src_path.generic_string(),
|
||||
FileSys::OpenMode::Read);
|
||||
auto firmware_dst_vfile = firmware_vdir
|
||||
->CreateFileRelative(firmware_src_path.filename().string());
|
||||
|
||||
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
|
||||
LOG_ERROR(Frontend,
|
||||
"Failed to copy firmware file {} to {} in registered folder!",
|
||||
firmware_src_path.generic_string(),
|
||||
firmware_src_path.filename().string());
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (QtProgressCallback(100,
|
||||
20
|
||||
+ static_cast<int>(((i) / static_cast<float>(out.size()))
|
||||
* 70.0))) {
|
||||
return FirmwareInstallResult::FailedCorrupted;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
return FirmwareInstallResult::FailedCopy;
|
||||
}
|
||||
|
||||
// Re-scan VFS for the newly placed firmware files.
|
||||
system->GetFileSystemController().CreateFactories(*vfs);
|
||||
return FirmwareInstallResult::Success;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
#include <array>
|
||||
|
||||
#include <QWindow>
|
||||
#include "core/core.h"
|
||||
#include <core/frontend/emu_window.h>
|
||||
|
||||
#include <core/file_sys/vfs/vfs_real.h>
|
||||
|
||||
namespace QtCommon {
|
||||
|
||||
static constexpr std::array<const char *, 3> METADATA_RESULTS = {
|
||||
|
@ -17,7 +20,7 @@ static constexpr std::array<const char *, 3> METADATA_RESULTS = {
|
|||
"The metadata cache is already empty.",
|
||||
};
|
||||
|
||||
enum MetadataResult {
|
||||
enum class MetadataResult {
|
||||
Success,
|
||||
Failure,
|
||||
Empty,
|
||||
|
@ -38,6 +41,36 @@ inline constexpr const char *GetResetMetadataResultString(MetadataResult result)
|
|||
return METADATA_RESULTS.at(static_cast<std::size_t>(result));
|
||||
}
|
||||
|
||||
static constexpr std::array<const char *, 6> FIRMWARE_RESULTS = {
|
||||
"",
|
||||
"",
|
||||
"Unable to locate potential firmware NCA files",
|
||||
"Failed to delete one or more firmware files.",
|
||||
"One or more firmware files failed to copy into NAND.",
|
||||
"Firmware installation cancelled, firmware may be in a bad state or corrupted."
|
||||
"Restart Eden or re-install firmware."
|
||||
};
|
||||
|
||||
enum class FirmwareInstallResult {
|
||||
Success,
|
||||
NoOp,
|
||||
NoNCAs,
|
||||
FailedDelete,
|
||||
FailedCopy,
|
||||
FailedCorrupted,
|
||||
};
|
||||
|
||||
FirmwareInstallResult InstallFirmware(const QString &location,
|
||||
bool recursive,
|
||||
std::function<bool(size_t, size_t)> QtProgressCallback,
|
||||
Core::System *system,
|
||||
FileSys::VfsFilesystem *vfs);
|
||||
|
||||
inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result)
|
||||
{
|
||||
return FIRMWARE_RESULTS.at(static_cast<std::size_t>(result));
|
||||
}
|
||||
|
||||
Core::Frontend::WindowSystemType GetWindowSystemType();
|
||||
|
||||
Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window);
|
||||
|
|
|
@ -132,7 +132,7 @@ void ConfigureFilesystem::ResetMetadata() {
|
|||
const QString title = tr("Reset Metadata Cache");
|
||||
|
||||
switch (result) {
|
||||
case QtCommon::Failure:
|
||||
case QtCommon::MetadataResult::Failure:
|
||||
QMessageBox::warning(this, title, resultMessage);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -4356,106 +4356,40 @@ void GMainWindow::InstallFirmware(const QString& location, bool recursive) {
|
|||
return progress.wasCanceled();
|
||||
};
|
||||
|
||||
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
||||
auto result = QtCommon::InstallFirmware(location, recursive, QtProgressCallback, system.get(), vfs.get());
|
||||
const char* resultMessage = QtCommon::GetFirmwareInstallResultString(result);
|
||||
|
||||
// Check for a reasonable number of .nca files (don't hardcode them, just see if there's some in
|
||||
// there.)
|
||||
std::filesystem::path firmware_source_path = location.toStdString();
|
||||
if (!Common::FS::IsDir(firmware_source_path)) {
|
||||
progress.close();
|
||||
progress.close();
|
||||
|
||||
QMessageBox *box = new QMessageBox(QMessageBox::Icon::NoIcon, tr("Firmware Install Failed"), tr(resultMessage), QMessageBox::Ok, this);
|
||||
|
||||
switch (result) {
|
||||
case QtCommon::FirmwareInstallResult::NoNCAs:
|
||||
case QtCommon::FirmwareInstallResult::FailedCorrupted:
|
||||
box->setIcon(QMessageBox::Icon::Warning);
|
||||
box->exec();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> out;
|
||||
const Common::FS::DirEntryCallable callback =
|
||||
[&out](const std::filesystem::directory_entry& entry) {
|
||||
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
|
||||
out.emplace_back(entry.path());
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
QtProgressCallback(100, 10);
|
||||
|
||||
if (recursive) {
|
||||
Common::FS::IterateDirEntriesRecursively(firmware_source_path, callback,
|
||||
Common::FS::DirEntryFilter::File);
|
||||
} else {
|
||||
Common::FS::IterateDirEntries(firmware_source_path, callback,
|
||||
Common::FS::DirEntryFilter::File);
|
||||
}
|
||||
|
||||
if (out.size() <= 0) {
|
||||
progress.close();
|
||||
QMessageBox::warning(this, tr("Firmware install failed"),
|
||||
tr("Unable to locate potential firmware NCA files"));
|
||||
case QtCommon::FirmwareInstallResult::FailedCopy:
|
||||
case QtCommon::FirmwareInstallResult::FailedDelete:
|
||||
box->setIcon(QMessageBox::Icon::Critical);
|
||||
box->exec();
|
||||
return;
|
||||
default:
|
||||
box->deleteLater();
|
||||
break;
|
||||
}
|
||||
|
||||
// Locate and erase the content of nand/system/Content/registered/*.nca, if any.
|
||||
auto sysnand_content_vdir = system->GetFileSystemController().GetSystemNANDContentDirectory();
|
||||
if (!sysnand_content_vdir->CleanSubdirectoryRecursive("registered")) {
|
||||
progress.close();
|
||||
QMessageBox::critical(this, tr("Firmware install failed"),
|
||||
tr("Failed to delete one or more firmware file."));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO(Frontend,
|
||||
"Cleaned nand/system/Content/registered folder in preparation for new firmware.");
|
||||
|
||||
QtProgressCallback(100, 20);
|
||||
|
||||
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
||||
|
||||
bool success = true;
|
||||
int i = 0;
|
||||
for (const auto& firmware_src_path : out) {
|
||||
i++;
|
||||
auto firmware_src_vfile =
|
||||
vfs->OpenFile(firmware_src_path.generic_string(), FileSys::OpenMode::Read);
|
||||
auto firmware_dst_vfile =
|
||||
firmware_vdir->CreateFileRelative(firmware_src_path.filename().string());
|
||||
|
||||
if (!VfsRawCopy(firmware_src_vfile, firmware_dst_vfile)) {
|
||||
LOG_ERROR(Frontend, "Failed to copy firmware file {} to {} in registered folder!",
|
||||
firmware_src_path.generic_string(), firmware_src_path.filename().string());
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (QtProgressCallback(
|
||||
100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) {
|
||||
progress.close();
|
||||
QMessageBox::warning(
|
||||
this, tr("Firmware install failed"),
|
||||
tr("Firmware installation cancelled, firmware may be in a bad state or corrupted. "
|
||||
"Restart Eden or re-install firmware."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
progress.close();
|
||||
QMessageBox::critical(this, tr("Firmware install failed"),
|
||||
tr("One or more firmware files failed to copy into NAND."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-scan VFS for the newly placed firmware files.
|
||||
system->GetFileSystemController().CreateFactories(*vfs);
|
||||
|
||||
auto VerifyFirmwareCallback = [&](size_t total_size, size_t processed_size) {
|
||||
progress.setValue(90 + static_cast<int>((processed_size * 10) / total_size));
|
||||
return progress.wasCanceled();
|
||||
};
|
||||
|
||||
auto result =
|
||||
ContentManager::VerifyInstalledContents(*system, *provider, VerifyFirmwareCallback, true);
|
||||
auto results =
|
||||
ContentManager::VerifyInstalledContents(*system, *provider, VerifyFirmwareCallback, true);
|
||||
|
||||
if (result.size() > 0) {
|
||||
if (results.size() > 0) {
|
||||
const auto failed_names =
|
||||
QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
|
||||
QString::fromStdString(fmt::format("{}", fmt::join(results, "\n")));
|
||||
progress.close();
|
||||
QMessageBox::critical(
|
||||
this, tr("Firmware integrity verification failed!"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue