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 defe45198..dcf68460a 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 | ||
| @@ -1048,7 +1049,12 @@ void GMainWindow::InitializeWidgets() { | |||
| 1048 | statusBar()->addPermanentWidget(label); | 1049 | statusBar()->addPermanentWidget(label); |
| 1049 | } | 1050 | } |
| 1050 | 1051 | ||
| 1051 | // TODO (flTobi): Add the widget when multiplayer is fully implemented | 1052 | firmware_label = new QLabel(); |
| 1053 | firmware_label->setObjectName(QStringLiteral("FirmwareLabel")); | ||
| 1054 | firmware_label->setVisible(false); | ||
| 1055 | firmware_label->setFocusPolicy(Qt::NoFocus); | ||
| 1056 | statusBar()->addPermanentWidget(firmware_label); | ||
| 1057 | |||
| 1052 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); | 1058 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); |
| 1053 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); | 1059 | statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); |
| 1054 | 1060 | ||
| @@ -2165,6 +2171,10 @@ void GMainWindow::OnEmulationStopped() { | |||
| 2165 | emu_frametime_label->setVisible(false); | 2171 | emu_frametime_label->setVisible(false); |
| 2166 | renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); | 2172 | renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); |
| 2167 | 2173 | ||
| 2174 | if (!firmware_label->text().isEmpty()) { | ||
| 2175 | firmware_label->setVisible(true); | ||
| 2176 | } | ||
| 2177 | |||
| 2168 | current_game_path.clear(); | 2178 | current_game_path.clear(); |
| 2169 | 2179 | ||
| 2170 | // When closing the game, destroy the GLWindow to clear the context after the game is closed | 2180 | // When closing the game, destroy the GLWindow to clear the context after the game is closed |
| @@ -4591,6 +4601,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 4591 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); | 4601 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
| 4592 | game_fps_label->setVisible(true); | 4602 | game_fps_label->setVisible(true); |
| 4593 | emu_frametime_label->setVisible(true); | 4603 | emu_frametime_label->setVisible(true); |
| 4604 | firmware_label->setVisible(false); | ||
| 4594 | } | 4605 | } |
| 4595 | 4606 | ||
| 4596 | void GMainWindow::UpdateGPUAccuracyButton() { | 4607 | void GMainWindow::UpdateGPUAccuracyButton() { |
| @@ -4810,6 +4821,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { | |||
| 4810 | "games.")); | 4821 | "games.")); |
| 4811 | } | 4822 | } |
| 4812 | 4823 | ||
| 4824 | SetFirmwareVersion(); | ||
| 4825 | |||
| 4813 | if (behavior == ReinitializeKeyBehavior::Warning) { | 4826 | if (behavior == ReinitializeKeyBehavior::Warning) { |
| 4814 | game_list->PopulateAsync(UISettings::values.game_dirs); | 4827 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 4815 | } | 4828 | } |
| @@ -4837,7 +4850,7 @@ bool GMainWindow::CheckSystemArchiveDecryption() { | |||
| 4837 | } | 4850 | } |
| 4838 | 4851 | ||
| 4839 | bool GMainWindow::CheckFirmwarePresence() { | 4852 | bool GMainWindow::CheckFirmwarePresence() { |
| 4840 | constexpr u64 MiiEditId = 0x0100000000001009ull; | 4853 | constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit); |
| 4841 | 4854 | ||
| 4842 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); | 4855 | auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); |
| 4843 | if (!bis_system) { | 4856 | if (!bis_system) { |
| @@ -4852,6 +4865,28 @@ bool GMainWindow::CheckFirmwarePresence() { | |||
| 4852 | return true; | 4865 | return true; |
| 4853 | } | 4866 | } |
| 4854 | 4867 | ||
| 4868 | void GMainWindow::SetFirmwareVersion() { | ||
| 4869 | Service::Set::FirmwareVersionFormat firmware_data{}; | ||
| 4870 | const auto result = Service::Set::GetFirmwareVersionImpl( | ||
| 4871 | firmware_data, *system, Service::Set::GetFirmwareVersionType::Version2); | ||
| 4872 | |||
| 4873 | if (result.IsError() || !CheckFirmwarePresence()) { | ||
| 4874 | LOG_INFO(Frontend, "Installed firmware: No firmware available"); | ||
| 4875 | firmware_label->setVisible(false); | ||
| 4876 | return; | ||
| 4877 | } | ||
| 4878 | |||
| 4879 | firmware_label->setVisible(true); | ||
| 4880 | |||
| 4881 | const std::string display_version(firmware_data.display_version.data()); | ||
| 4882 | const std::string display_title(firmware_data.display_title.data()); | ||
| 4883 | |||
| 4884 | LOG_INFO(Frontend, "Installed firmware: {}", display_title); | ||
| 4885 | |||
| 4886 | firmware_label->setText(QString::fromStdString(display_version)); | ||
| 4887 | firmware_label->setToolTip(QString::fromStdString(display_title)); | ||
| 4888 | } | ||
| 4889 | |||
| 4855 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, | 4890 | bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, |
| 4856 | u64* selected_title_id, u8* selected_content_record_type) { | 4891 | u64* selected_title_id, u8* selected_content_record_type) { |
| 4857 | using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; | 4892 | using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index c989c079d..e99d58995 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -458,6 +458,7 @@ private: | |||
| 458 | bool CheckDarkMode(); | 458 | bool CheckDarkMode(); |
| 459 | bool CheckSystemArchiveDecryption(); | 459 | bool CheckSystemArchiveDecryption(); |
| 460 | bool CheckFirmwarePresence(); | 460 | bool CheckFirmwarePresence(); |
| 461 | void SetFirmwareVersion(); | ||
| 461 | void ConfigureFilesystemProvider(const std::string& filepath); | 462 | void ConfigureFilesystemProvider(const std::string& filepath); |
| 462 | /** | 463 | /** |
| 463 | * Open (or not) the right confirm dialog based on current setting and game exit lock | 464 | * Open (or not) the right confirm dialog based on current setting and game exit lock |
| @@ -512,6 +513,7 @@ private: | |||
| 512 | QLabel* game_fps_label = nullptr; | 513 | QLabel* game_fps_label = nullptr; |
| 513 | QLabel* emu_frametime_label = nullptr; | 514 | QLabel* emu_frametime_label = nullptr; |
| 514 | QLabel* tas_label = nullptr; | 515 | QLabel* tas_label = nullptr; |
| 516 | QLabel* firmware_label = nullptr; | ||
| 515 | QPushButton* gpu_accuracy_button = nullptr; | 517 | QPushButton* gpu_accuracy_button = nullptr; |
| 516 | QPushButton* renderer_status_button = nullptr; | 518 | QPushButton* renderer_status_button = nullptr; |
| 517 | QPushButton* dock_status_button = nullptr; | 519 | QPushButton* dock_status_button = nullptr; |