diff options
| -rw-r--r-- | src/core/hle/service/set/set_sys.cpp | 66 | ||||
| -rw-r--r-- | src/core/hle/service/set/set_sys.h | 24 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 39 | ||||
| -rw-r--r-- | src/yuzu/main.h | 2 |
4 files changed, 98 insertions, 33 deletions
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 19c667b42..f5edfdc8b 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp | |||
| @@ -19,19 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | namespace Service::Set { | 20 | namespace Service::Set { |
| 21 | 21 | ||
| 22 | namespace { | 22 | Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system, |
| 23 | constexpr u64 SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET = 0x05; | 23 | GetFirmwareVersionType type) { |
| 24 | |||
| 25 | enum class GetFirmwareVersionType { | ||
| 26 | Version1, | ||
| 27 | Version2, | ||
| 28 | }; | ||
| 29 | |||
| 30 | void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx, | ||
| 31 | GetFirmwareVersionType type) { | ||
| 32 | ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100, | ||
| 33 | "FirmwareVersion output buffer must be 0x100 bytes in size!"); | ||
| 34 | |||
| 35 | constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809; | 24 | constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809; |
| 36 | auto& fsc = system.GetFileSystemController(); | 25 | auto& fsc = system.GetFileSystemController(); |
| 37 | 26 | ||
| @@ -52,39 +41,34 @@ void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx, | |||
| 52 | FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId)); | 41 | FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId)); |
| 53 | } | 42 | } |
| 54 | 43 | ||
| 55 | const auto early_exit_failure = [&ctx](std::string_view desc, Result code) { | 44 | const auto early_exit_failure = [](std::string_view desc, Result code) { |
| 56 | LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).", | 45 | LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).", |
| 57 | desc); | 46 | desc); |
| 58 | IPC::ResponseBuilder rb{ctx, 2}; | 47 | return code; |
| 59 | rb.Push(code); | ||
| 60 | }; | 48 | }; |
| 61 | 49 | ||
| 62 | const auto ver_file = romfs->GetFile("file"); | 50 | const auto ver_file = romfs->GetFile("file"); |
| 63 | if (ver_file == nullptr) { | 51 | if (ver_file == nullptr) { |
| 64 | early_exit_failure("The system version archive didn't contain the file 'file'.", | 52 | return early_exit_failure("The system version archive didn't contain the file 'file'.", |
| 65 | FileSys::ERROR_INVALID_ARGUMENT); | 53 | FileSys::ERROR_INVALID_ARGUMENT); |
| 66 | return; | ||
| 67 | } | 54 | } |
| 68 | 55 | ||
| 69 | auto data = ver_file->ReadAllBytes(); | 56 | auto data = ver_file->ReadAllBytes(); |
| 70 | if (data.size() != 0x100) { | 57 | if (data.size() != sizeof(FirmwareVersionFormat)) { |
| 71 | early_exit_failure("The system version file 'file' was not the correct size.", | 58 | return early_exit_failure("The system version file 'file' was not the correct size.", |
| 72 | FileSys::ERROR_OUT_OF_BOUNDS); | 59 | FileSys::ERROR_OUT_OF_BOUNDS); |
| 73 | return; | ||
| 74 | } | 60 | } |
| 75 | 61 | ||
| 62 | std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat)); | ||
| 63 | |||
| 76 | // If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will | 64 | // If the command is GetFirmwareVersion (as opposed to GetFirmwareVersion2), hardware will |
| 77 | // zero out the REVISION_MINOR field. | 65 | // zero out the REVISION_MINOR field. |
| 78 | if (type == GetFirmwareVersionType::Version1) { | 66 | if (type == GetFirmwareVersionType::Version1) { |
| 79 | data[SYSTEM_VERSION_FILE_MINOR_REVISION_OFFSET] = 0; | 67 | out_firmware.revision_minor = 0; |
| 80 | } | 68 | } |
| 81 | 69 | ||
| 82 | ctx.WriteBuffer(data); | 70 | return ResultSuccess; |
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | } | 71 | } |
| 87 | } // Anonymous namespace | ||
| 88 | 72 | ||
| 89 | void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { | 73 | void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { |
| 90 | IPC::RequestParser rp{ctx}; | 74 | IPC::RequestParser rp{ctx}; |
| @@ -98,12 +82,32 @@ void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { | |||
| 98 | 82 | ||
| 99 | void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { | 83 | void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { |
| 100 | LOG_DEBUG(Service_SET, "called"); | 84 | LOG_DEBUG(Service_SET, "called"); |
| 101 | GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version1); | 85 | |
| 86 | FirmwareVersionFormat firmware_data{}; | ||
| 87 | const auto result = | ||
| 88 | GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version1); | ||
| 89 | |||
| 90 | if (result.IsSuccess()) { | ||
| 91 | ctx.WriteBuffer(firmware_data); | ||
| 92 | } | ||
| 93 | |||
| 94 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 95 | rb.Push(result); | ||
| 102 | } | 96 | } |
| 103 | 97 | ||
| 104 | void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { | 98 | void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { |
| 105 | LOG_DEBUG(Service_SET, "called"); | 99 | LOG_DEBUG(Service_SET, "called"); |
| 106 | GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version2); | 100 | |
| 101 | FirmwareVersionFormat firmware_data{}; | ||
| 102 | const auto result = | ||
| 103 | GetFirmwareVersionImpl(firmware_data, system, GetFirmwareVersionType::Version2); | ||
| 104 | |||
| 105 | if (result.IsSuccess()) { | ||
| 106 | ctx.WriteBuffer(firmware_data); | ||
| 107 | } | ||
| 108 | |||
| 109 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 110 | rb.Push(result); | ||
| 107 | } | 111 | } |
| 108 | 112 | ||
| 109 | void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { | 113 | void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index 93023c6dd..5f770fd32 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/uuid.h" | 6 | #include "common/uuid.h" |
| 7 | #include "core/hle/result.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | #include "core/hle/service/time/clock_types.h" | 9 | #include "core/hle/service/time/clock_types.h" |
| 9 | 10 | ||
| @@ -12,6 +13,29 @@ class System; | |||
| 12 | } | 13 | } |
| 13 | 14 | ||
| 14 | namespace Service::Set { | 15 | namespace Service::Set { |
| 16 | enum class LanguageCode : u64; | ||
| 17 | enum class GetFirmwareVersionType { | ||
| 18 | Version1, | ||
| 19 | Version2, | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct FirmwareVersionFormat { | ||
| 23 | u8 major; | ||
| 24 | u8 minor; | ||
| 25 | u8 micro; | ||
| 26 | INSERT_PADDING_BYTES(1); | ||
| 27 | u8 revision_major; | ||
| 28 | u8 revision_minor; | ||
| 29 | INSERT_PADDING_BYTES(2); | ||
| 30 | std::array<char, 0x20> platform; | ||
| 31 | std::array<u8, 0x40> version_hash; | ||
| 32 | std::array<char, 0x18> display_version; | ||
| 33 | std::array<char, 0x80> display_title; | ||
| 34 | }; | ||
| 35 | static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size"); | ||
| 36 | |||
| 37 | Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& system, | ||
| 38 | GetFirmwareVersionType type); | ||
| 15 | 39 | ||
| 16 | class SET_SYS final : public ServiceFramework<SET_SYS> { | 40 | class SET_SYS final : public ServiceFramework<SET_SYS> { |
| 17 | public: | 41 | public: |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f22db233b..1848ac89f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include "core/hle/service/am/applet_ae.h" | 47 | #include "core/hle/service/am/applet_ae.h" |
| 48 | #include "core/hle/service/am/applet_oe.h" | 48 | #include "core/hle/service/am/applet_oe.h" |
| 49 | #include "core/hle/service/am/applets/applets.h" | 49 | #include "core/hle/service/am/applets/applets.h" |
| 50 | #include "core/hle/service/set/set_sys.h" | ||
| 50 | #include "yuzu/multiplayer/state.h" | 51 | #include "yuzu/multiplayer/state.h" |
| 51 | #include "yuzu/util/controller_navigation.h" | 52 | #include "yuzu/util/controller_navigation.h" |
| 52 | 53 | ||
| @@ -1047,7 +1048,12 @@ void GMainWindow::InitializeWidgets() { | |||
| 1047 | statusBar()->addPermanentWidget(label); | 1048 | statusBar()->addPermanentWidget(label); |
| 1048 | } | 1049 | } |
| 1049 | 1050 | ||
| 1050 | // TODO (flTobi): Add the widget when multiplayer is fully implemented | 1051 | firmware_label = new QLabel(); |
| 1052 | firmware_label->setObjectName(QStringLiteral("FirmwareLabel")); | ||
| 1053 | firmware_label->setVisible(false); | ||
| 1054 | firmware_label->setFocusPolicy(Qt::NoFocus); | ||
| 1055 | statusBar()->addPermanentWidget(firmware_label); | ||
| 1056 | |||
| 1051 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); | 1057 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); |
| 1052 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); | 1058 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); |
| 1053 | 1059 | ||
| @@ -2161,6 +2167,10 @@ void GMainWindow::OnEmulationStopped() { | |||
| 2161 | emu_frametime_label->setVisible(false); | 2167 | emu_frametime_label->setVisible(false); |
| 2162 | renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); | 2168 | renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); |
| 2163 | 2169 | ||
| 2170 | if (!firmware_label->text().isEmpty()) { | ||
| 2171 | firmware_label->setVisible(true); | ||
| 2172 | } | ||
| 2173 | |||
| 2164 | current_game_path.clear(); | 2174 | current_game_path.clear(); |
| 2165 | 2175 | ||
| 2166 | // When closing the game, destroy the GLWindow to clear the context after the game is closed | 2176 | // When closing the game, destroy the GLWindow to clear the context after the game is closed |
| @@ -4586,6 +4596,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 4586 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); | 4596 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
| 4587 | game_fps_label->setVisible(true); | 4597 | game_fps_label->setVisible(true); |
| 4588 | emu_frametime_label->setVisible(true); | 4598 | emu_frametime_label->setVisible(true); |
| 4599 | firmware_label->setVisible(false); | ||
| 4589 | } | 4600 | } |
| 4590 | 4601 | ||
| 4591 | void GMainWindow::UpdateGPUAccuracyButton() { | 4602 | void GMainWindow::UpdateGPUAccuracyButton() { |
| @@ -4803,6 +4814,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 4803 | "games.")); | 4814 | "games.")); |
| 4804 | } | 4815 | } |
| 4805 | 4816 | ||
| 4817 | SetFirmwareVersion(); | ||
| 4818 | |||
| 4806 | if (behavior == ReinitializeKeyBehavior::Warning) { | 4819 | if (behavior == ReinitializeKeyBehavior::Warning) { |
| 4807 | game_list->PopulateAsync(UISettings::values.game_dirs); | 4820 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 4808 | } | 4821 | } |
| @@ -4830,7 +4843,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() { | |||
| 4830 | } | 4843 | } |
| 4831 | 4844 | ||
| 4832 | bool GMainWindow::CheckFirmwarePresence() { | 4845 | bool GMainWindow::CheckFirmwarePresence() { |
| 4833 | constexpr u64 MiiEditId = 0x0100000000001009ull; | 4846 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); |
| 4834 | 4847 | ||
| 4835 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4848 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4836 | if (!bis_system) { | 4849 | if (!bis_system) { |
| @@ -4845,6 +4858,28 @@ bool GMainWindow::CheckFirmwarePresence() { | |||
| 4845 | return true; | 4858 | return true; |
| 4846 | } | 4859 | } |
| 4847 | 4860 | ||
| 4861 | void GMainWindow::SetFirmwareVersion() { | ||
| 4862 | Service::Set::FirmwareVersionFormat firmware_data{}; | ||
| 4863 | const auto result = Service::Set::GetFirmwareVersionImpl( | ||
| 4864 | firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2); | ||
| 4865 | |||
| 4866 | if (result.IsError() || !CheckFirmwarePresence()) { | ||
| 4867 | LOG_INFO(Frontend, "Installed firmware: No firmware available"); | ||
| 4868 | firmware_label->setVisible(false); | ||
| 4869 | return; | ||
| 4870 | } | ||
| 4871 | |||
| 4872 | firmware_label->setVisible(true); | ||
| 4873 | |||
| 4874 | const std::string display_version(firmware_data.display_version.data()); | ||
| 4875 | const std::string display_title(firmware_data.display_title.data()); | ||
| 4876 | |||
| 4877 | LOG_INFO(Frontend, "Installed firmware: {}", display_title); | ||
| 4878 | |||
| 4879 | firmware_label->setText(QString::fromStdString(display_version)); | ||
| 4880 | firmware_label->setToolTip(QString::fromStdString(display_title)); | ||
| 4881 | } | ||
| 4882 | |||
| 4848 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, | 4883 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, |
| 4849 | u64* selected_title_id, u8* selected_content_record_type) { | 4884 | u64* selected_title_id, u8* selected_content_record_type) { |
| 4850 | using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; | 4885 | using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 49ee1e1d2..0c8b7606d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -457,6 +457,7 @@ private: | |||
| 457 | bool CheckDarkMode(); | 457 | bool CheckDarkMode(); |
| 458 | bool CheckSystemArchiveDecryption(); | 458 | bool CheckSystemArchiveDecryption(); |
| 459 | bool CheckFirmwarePresence(); | 459 | bool CheckFirmwarePresence(); |
| 460 | void SetFirmwareVersion(); | ||
| 460 | void ConfigureFilesystemProvider(const std::string& filepath); | 461 | void ConfigureFilesystemProvider(const std::string& filepath); |
| 461 | /** | 462 | /** |
| 462 | * Open (or not) the right confirm dialog based on current setting and game exit lock | 463 | * Open (or not) the right confirm dialog based on current setting and game exit lock |
| @@ -511,6 +512,7 @@ private: | |||
| 511 | QLabel* game_fps_label = nullptr; | 512 | QLabel* game_fps_label = nullptr; |
| 512 | QLabel* emu_frametime_label = nullptr; | 513 | QLabel* emu_frametime_label = nullptr; |
| 513 | QLabel* tas_label = nullptr; | 514 | QLabel* tas_label = nullptr; |
| 515 | QLabel* firmware_label = nullptr; | ||
| 514 | QPushButton* gpu_accuracy_button = nullptr; | 516 | QPushButton* gpu_accuracy_button = nullptr; |
| 515 | QPushButton* renderer_status_button = nullptr; | 517 | QPushButton* renderer_status_button = nullptr; |
| 516 | QPushButton* dock_status_button = nullptr; | 518 | QPushButton* dock_status_button = nullptr; |