yuzu: Display firmware version

This commit is contained in:
Narr the Reg 2023-11-24 11:53:31 -06:00
parent 91c12db070
commit 2d4e7c8264
4 changed files with 98 additions and 33 deletions

View File

@ -19,19 +19,8 @@
namespace Service::Set { namespace Service::Set {
namespace { Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
constexpr u64 SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET = 0x05;
enum class GetFirmwareVersionType {
Version1,
Version2,
};
void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
GetFirmwareVersionType type) { GetFirmwareVersionType type) {
ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100,
"FirmwareVersion output buffer must be 0x100 bytes in size!");
constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809; constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809;
auto& fsc = system.GetFileSystemController(); auto& fsc = system.GetFileSystemController();
@ -52,39 +41,34 @@ void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId)); FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId));
} }
const auto early_exit_failure = [&ctx](std::string_view desc, Result code) { const auto early_exit_failure = [](std::string_view desc, Result code) {
LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).", LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
desc); desc);
IPC::ResponseBuilder rb{ctx, 2}; return code;
rb.Push(code);
}; };
const auto ver_file = romfs->GetFile("file"); const auto ver_file = romfs->GetFile("file");
if (ver_file == nullptr) { if (ver_file == nullptr) {
early_exit_failure("The system version archive didn't contain the file 'file'.", return early_exit_failure("The system version archive didn't contain the file 'file'.",
FileSys::ERROR_INVALID_ARGUMENT); FileSys::ERROR_INVALID_ARGUMENT);
return;
} }
auto data = ver_file->ReadAllBytes(); auto data = ver_file->ReadAllBytes();
if (data.size() != 0x100) { if (data.size() != sizeof(FirmwareVersionFormat)) {
early_exit_failure("The system version file 'file' was not the correct size.", return early_exit_failure("The system version file 'file' was not the correct size.",
FileSys::ERROR_OUT_OF_BOUNDS); FileSys::ERROR_OUT_OF_BOUNDS);
return;
} }
std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat));
// If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will // If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will
// zero out the REVISION_MINOR field. // zero out the REVISION_MINOR field.
if (type == GetFirmwareVersionType::Version1) { if (type == GetFirmwareVersionType::Version1) {
data[SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET] = 0; out_firmware.revision_minor = 0;
} }
ctx.WriteBuffer(data); return ResultSuccess;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
} // Anonymous namespace
void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
@ -98,12 +82,32 @@ void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called"); LOG_DEBUG(Service_SET, "called");
GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version1);
FirmwareVersionFormat firmware_data{};
const auto result =
GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1);
if (result.IsSuccess()) {
ctx.WriteBuffer(firmware_data);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
} }
void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called"); LOG_DEBUG(Service_SET, "called");
GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version2);
FirmwareVersionFormat firmware_data{};
const auto result =
GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2);
if (result.IsSuccess()) {
ctx.WriteBuffer(firmware_data);
}
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result);
} }
void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include "common/uuid.h" #include "common/uuid.h"
#include "core/hle/result.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/time/clock_types.h" #include "core/hle/service/time/clock_types.h"
@ -12,6 +13,29 @@ class System;
} }
namespace Service::Set { namespace Service::Set {
enum class LanguageCode : u64;
enum class GetFirmwareVersionType {
Version1,
Version2,
};
struct FirmwareVersionFormat {
u8 major;
u8 minor;
u8 micro;
INSERT_PADDING_BYTES(1);
u8 revision_major;
u8 revision_minor;
INSERT_PADDING_BYTES(2);
std::array<char, 0x20> platform;
std::array<u8, 0x40> version_hash;
std::array<char, 0x18> display_version;
std::array<char, 0x80> display_title;
};
static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size");
Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system,
GetFirmwareVersionType type);
class SET_SYS final : public ServiceFramework<SET_SYS> { class SET_SYS final : public ServiceFramework<SET_SYS> {
public: public:

View File

@ -47,6 +47,7 @@
#include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h" #include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h" #include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/set/set_sys.h"
#include "yuzu/multiplayer/state.h" #include "yuzu/multiplayer/state.h"
#include "yuzu/util/controller_navigation.h" #include "yuzu/util/controller_navigation.h"
@ -1047,7 +1048,12 @@ void GMainWindow::InitializeWidgets() {
statusBar()->addPermanentWidget(label); statusBar()->addPermanentWidget(label);
} }
// TODO (flTobi): Add the widget when multiplayer is fully implemented firmware_label = new QLabel();
firmware_label->setObjectName(QStringLiteral("FirmwareLabel"));
firmware_label->setVisible(false);
firmware_label->setFocusPolicy(Qt::NoFocus);
statusBar()->addPermanentWidget(firmware_label);
statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0);
statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0);
@ -2161,6 +2167,10 @@ void GMainWindow::OnEmulationStopped() {
emu_frametime_label->setVisible(false); emu_frametime_label->setVisible(false);
renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
if (!firmware_label->text().isEmpty()) {
firmware_label->setVisible(true);
}
current_game_path.clear(); current_game_path.clear();
// When closing the game, destroy the GLWindow to clear the context after the game is closed // When closing the game, destroy the GLWindow to clear the context after the game is closed
@ -4586,6 +4596,7 @@ void GMainWindow::UpdateStatusBar() {
emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue());
game_fps_label->setVisible(true); game_fps_label->setVisible(true);
emu_frametime_label->setVisible(true); emu_frametime_label->setVisible(true);
firmware_label->setVisible(false);
} }
void GMainWindow::UpdateGPUAccuracyButton() { void GMainWindow::UpdateGPUAccuracyButton() {
@ -4803,6 +4814,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
"games.")); "games."));
} }
SetFirmwareVersion();
if (behavior == ReinitializeKeyBehavior::Warning) { if (behavior == ReinitializeKeyBehavior::Warning) {
game_list->PopulateAsync(UISettings::values.game_dirs); game_list->PopulateAsync(UISettings::values.game_dirs);
} }
@ -4830,7 +4843,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
} }
bool GMainWindow::CheckFirmwarePresence() { bool GMainWindow::CheckFirmwarePresence() {
constexpr u64 MiiEditId = 0x0100000000001009ull; constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) { if (!bis_system) {
@ -4845,6 +4858,28 @@ bool GMainWindow::CheckFirmwarePresence() {
return true; return true;
} }
void GMainWindow::SetFirmwareVersion() {
Service::Set::FirmwareVersionFormat firmware_data{};
const auto result = Service::Set::GetFirmwareVersionImpl(
firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2);
if (result.IsError() || !CheckFirmwarePresence()) {
LOG_INFO(Frontend, "Installed firmware: No firmware available");
firmware_label->setVisible(false);
return;
}
firmware_label->setVisible(true);
const std::string display_version(firmware_data.display_version.data());
const std::string display_title(firmware_data.display_title.data());
LOG_INFO(Frontend, "Installed firmware: {}", display_title);
firmware_label->setText(QString::fromStdString(display_version));
firmware_label->setToolTip(QString::fromStdString(display_title));
}
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
u64* selected_title_id, u8* selected_content_record_type) { u64* selected_title_id, u8* selected_content_record_type) {
using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;

View File

@ -457,6 +457,7 @@ private:
bool CheckDarkMode(); bool CheckDarkMode();
bool CheckSystemArchiveDecryption(); bool CheckSystemArchiveDecryption();
bool CheckFirmwarePresence(); bool CheckFirmwarePresence();
void SetFirmwareVersion();
void ConfigureFilesystemProvider(const std::string& filepath); void ConfigureFilesystemProvider(const std::string& filepath);
/** /**
* Open (or not) the right confirm dialog based on current setting and game exit lock * Open (or not) the right confirm dialog based on current setting and game exit lock
@ -511,6 +512,7 @@ private:
QLabel* game_fps_label = nullptr; QLabel* game_fps_label = nullptr;
QLabel* emu_frametime_label = nullptr; QLabel* emu_frametime_label = nullptr;
QLabel* tas_label = nullptr; QLabel* tas_label = nullptr;
QLabel* firmware_label = nullptr;
QPushButton* gpu_accuracy_button = nullptr; QPushButton* gpu_accuracy_button = nullptr;
QPushButton* renderer_status_button = nullptr; QPushButton* renderer_status_button = nullptr;
QPushButton* dock_status_button = nullptr; QPushButton* dock_status_button = nullptr;