diff options
71 files changed, 2019 insertions, 948 deletions
| @@ -40,7 +40,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f | |||
| 40 | 40 | ||
| 41 | The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements). | 41 | The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements). |
| 42 | 42 | ||
| 43 | For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/) | 43 | For a full list of games yuzu supports, please visit our [Compatibility page](https://yuzu-emu.org/game/). |
| 44 | 44 | ||
| 45 | Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more! | 45 | Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more! |
| 46 | 46 | ||
diff --git a/src/common/settings_common.cpp b/src/common/settings_common.cpp index dedf5ef90..137b65d5f 100644 --- a/src/common/settings_common.cpp +++ b/src/common/settings_common.cpp | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <functional> | ||
| 4 | #include <string> | 5 | #include <string> |
| 6 | #include <vector> | ||
| 5 | #include "common/settings_common.h" | 7 | #include "common/settings_common.h" |
| 6 | 8 | ||
| 7 | namespace Settings { | 9 | namespace Settings { |
diff --git a/src/common/settings_enums.h b/src/common/settings_enums.h index a1a29ebf6..e7cb59ea5 100644 --- a/src/common/settings_enums.h +++ b/src/common/settings_enums.h | |||
| @@ -12,8 +12,8 @@ namespace Settings { | |||
| 12 | 12 | ||
| 13 | template <typename T> | 13 | template <typename T> |
| 14 | struct EnumMetadata { | 14 | struct EnumMetadata { |
| 15 | static constexpr std::vector<std::pair<std::string, T>> Canonicalizations(); | 15 | static std::vector<std::pair<std::string, T>> Canonicalizations(); |
| 16 | static constexpr u32 Index(); | 16 | static u32 Index(); |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) | 19 | #define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__)) |
| @@ -66,11 +66,11 @@ struct EnumMetadata { | |||
| 66 | #define ENUM(NAME, ...) \ | 66 | #define ENUM(NAME, ...) \ |
| 67 | enum class NAME : u32 { __VA_ARGS__ }; \ | 67 | enum class NAME : u32 { __VA_ARGS__ }; \ |
| 68 | template <> \ | 68 | template <> \ |
| 69 | constexpr std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ | 69 | inline std::vector<std::pair<std::string, NAME>> EnumMetadata<NAME>::Canonicalizations() { \ |
| 70 | return {PAIR(NAME, __VA_ARGS__)}; \ | 70 | return {PAIR(NAME, __VA_ARGS__)}; \ |
| 71 | } \ | 71 | } \ |
| 72 | template <> \ | 72 | template <> \ |
| 73 | constexpr u32 EnumMetadata<NAME>::Index() { \ | 73 | inline u32 EnumMetadata<NAME>::Index() { \ |
| 74 | return __COUNTER__; \ | 74 | return __COUNTER__; \ |
| 75 | } | 75 | } |
| 76 | 76 | ||
| @@ -85,7 +85,7 @@ enum class AudioEngine : u32 { | |||
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | template <> | 87 | template <> |
| 88 | constexpr std::vector<std::pair<std::string, AudioEngine>> | 88 | inline std::vector<std::pair<std::string, AudioEngine>> |
| 89 | EnumMetadata<AudioEngine>::Canonicalizations() { | 89 | EnumMetadata<AudioEngine>::Canonicalizations() { |
| 90 | return { | 90 | return { |
| 91 | {"auto", AudioEngine::Auto}, | 91 | {"auto", AudioEngine::Auto}, |
| @@ -96,7 +96,7 @@ EnumMetadata<AudioEngine>::Canonicalizations() { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | template <> | 98 | template <> |
| 99 | constexpr u32 EnumMetadata<AudioEngine>::Index() { | 99 | inline u32 EnumMetadata<AudioEngine>::Index() { |
| 100 | // This is just a sufficiently large number that is more than the number of other enums declared | 100 | // This is just a sufficiently large number that is more than the number of other enums declared |
| 101 | // here | 101 | // here |
| 102 | return 100; | 102 | return 100; |
| @@ -147,7 +147,7 @@ ENUM(AntiAliasing, None, Fxaa, Smaa, MaxEnum); | |||
| 147 | ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); | 147 | ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch); |
| 148 | 148 | ||
| 149 | template <typename Type> | 149 | template <typename Type> |
| 150 | constexpr std::string CanonicalizeEnum(Type id) { | 150 | inline std::string CanonicalizeEnum(Type id) { |
| 151 | const auto group = EnumMetadata<Type>::Canonicalizations(); | 151 | const auto group = EnumMetadata<Type>::Canonicalizations(); |
| 152 | for (auto& [name, value] : group) { | 152 | for (auto& [name, value] : group) { |
| 153 | if (value == id) { | 153 | if (value == id) { |
| @@ -158,7 +158,7 @@ constexpr std::string CanonicalizeEnum(Type id) { | |||
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | template <typename Type> | 160 | template <typename Type> |
| 161 | constexpr Type ToEnum(const std::string& canonicalization) { | 161 | inline Type ToEnum(const std::string& canonicalization) { |
| 162 | const auto group = EnumMetadata<Type>::Canonicalizations(); | 162 | const auto group = EnumMetadata<Type>::Canonicalizations(); |
| 163 | for (auto& [name, value] : group) { | 163 | for (auto& [name, value] : group) { |
| 164 | if (name == canonicalization) { | 164 | if (name == canonicalization) { |
diff --git a/src/common/settings_setting.h b/src/common/settings_setting.h index a8beb06e9..e10843c73 100644 --- a/src/common/settings_setting.h +++ b/src/common/settings_setting.h | |||
| @@ -190,7 +190,7 @@ public: | |||
| 190 | } | 190 | } |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | [[nodiscard]] std::string constexpr Canonicalize() const override final { | 193 | [[nodiscard]] std::string Canonicalize() const override final { |
| 194 | if constexpr (std::is_enum_v<Type>) { | 194 | if constexpr (std::is_enum_v<Type>) { |
| 195 | return CanonicalizeEnum(this->GetValue()); | 195 | return CanonicalizeEnum(this->GetValue()); |
| 196 | } else { | 196 | } else { |
| @@ -256,11 +256,11 @@ public: | |||
| 256 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | 256 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded |
| 257 | * @param other_setting_ A second Setting to associate to this one in metadata | 257 | * @param other_setting_ A second Setting to associate to this one in metadata |
| 258 | */ | 258 | */ |
| 259 | template <typename T = BasicSetting> | ||
| 259 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, | 260 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name, |
| 260 | Category category_, u32 specialization_ = Specialization::Default, | 261 | Category category_, u32 specialization_ = Specialization::Default, |
| 261 | bool save_ = true, bool runtime_modifiable_ = false, | 262 | bool save_ = true, bool runtime_modifiable_ = false, |
| 262 | BasicSetting* other_setting_ = nullptr) | 263 | typename std::enable_if<!ranged, T*>::type other_setting_ = nullptr) |
| 263 | requires(!ranged) | ||
| 264 | : Setting<Type, false>{ | 264 | : Setting<Type, false>{ |
| 265 | linkage, default_val, name, category_, specialization_, | 265 | linkage, default_val, name, category_, specialization_, |
| 266 | save_, runtime_modifiable_, other_setting_} { | 266 | save_, runtime_modifiable_, other_setting_} { |
| @@ -282,12 +282,12 @@ public: | |||
| 282 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded | 282 | * @param runtime_modifiable_ Suggests whether this is modifiable while a guest is loaded |
| 283 | * @param other_setting_ A second Setting to associate to this one in metadata | 283 | * @param other_setting_ A second Setting to associate to this one in metadata |
| 284 | */ | 284 | */ |
| 285 | template <typename T = BasicSetting> | ||
| 285 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, | 286 | explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val, |
| 286 | const Type& max_val, const std::string& name, Category category_, | 287 | const Type& max_val, const std::string& name, Category category_, |
| 287 | u32 specialization_ = Specialization::Default, bool save_ = true, | 288 | u32 specialization_ = Specialization::Default, bool save_ = true, |
| 288 | bool runtime_modifiable_ = false, | 289 | bool runtime_modifiable_ = false, |
| 289 | BasicSetting* other_setting_ = nullptr) | 290 | typename std::enable_if<ranged, T*>::type other_setting_ = nullptr) |
| 290 | requires(ranged) | ||
| 291 | : Setting<Type, true>{linkage, default_val, min_val, | 291 | : Setting<Type, true>{linkage, default_val, min_val, |
| 292 | max_val, name, category_, | 292 | max_val, name, category_, |
| 293 | specialization_, save_, runtime_modifiable_, | 293 | specialization_, save_, runtime_modifiable_, |
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index ae7a3511b..aa4726cfa 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -35,7 +35,7 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) { | |||
| 35 | update_raw = std::move(update_raw_file); | 35 | update_raw = std::move(update_raw_file); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { | 38 | VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { |
| 39 | if (!updatable) { | 39 | if (!updatable) { |
| 40 | return file; | 40 | return file; |
| 41 | } | 41 | } |
| @@ -45,12 +45,11 @@ ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_titl | |||
| 45 | return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw); | 45 | return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const { | 48 | VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const { |
| 49 | auto nca = content_provider.GetEntry(title_id, type); | 49 | auto nca = content_provider.GetEntry(title_id, type); |
| 50 | 50 | ||
| 51 | if (nca == nullptr) { | 51 | if (nca == nullptr) { |
| 52 | // TODO: Find the right error code to use here | 52 | return nullptr; |
| 53 | return ResultUnknown; | ||
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | const PatchManager patch_manager{title_id, filesystem_controller, content_provider}; | 55 | const PatchManager patch_manager{title_id, filesystem_controller, content_provider}; |
| @@ -58,28 +57,20 @@ ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecor | |||
| 58 | return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type); | 57 | return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type); |
| 59 | } | 58 | } |
| 60 | 59 | ||
| 61 | ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex( | 60 | VirtualFile RomFSFactory::OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 62 | u64 title_id, u8 program_index, ContentRecordType type) const { | 61 | ContentRecordType type) const { |
| 63 | const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index); | 62 | const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index); |
| 64 | 63 | ||
| 65 | return OpenPatchedRomFS(res_title_id, type); | 64 | return OpenPatchedRomFS(res_title_id, type); |
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, | 67 | VirtualFile RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) const { |
| 69 | ContentRecordType type) const { | ||
| 70 | const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); | 68 | const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); |
| 71 | if (res == nullptr) { | 69 | if (res == nullptr) { |
| 72 | // TODO(DarkLordZach): Find the right error code to use here | 70 | return nullptr; |
| 73 | return ResultUnknown; | ||
| 74 | } | ||
| 75 | |||
| 76 | const auto romfs = res->GetRomFS(); | ||
| 77 | if (romfs == nullptr) { | ||
| 78 | // TODO(DarkLordZach): Find the right error code to use here | ||
| 79 | return ResultUnknown; | ||
| 80 | } | 71 | } |
| 81 | 72 | ||
| 82 | return romfs; | 73 | return res->GetRomFS(); |
| 83 | } | 74 | } |
| 84 | 75 | ||
| 85 | std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage, | 76 | std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage, |
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index 14936031f..7ec40d19d 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h | |||
| @@ -41,13 +41,11 @@ public: | |||
| 41 | ~RomFSFactory(); | 41 | ~RomFSFactory(); |
| 42 | 42 | ||
| 43 | void SetPackedUpdate(VirtualFile update_raw_file); | 43 | void SetPackedUpdate(VirtualFile update_raw_file); |
| 44 | [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const; | 44 | [[nodiscard]] VirtualFile OpenCurrentProcess(u64 current_process_title_id) const; |
| 45 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id, | 45 | [[nodiscard]] VirtualFile OpenPatchedRomFS(u64 title_id, ContentRecordType type) const; |
| 46 | ContentRecordType type) const; | 46 | [[nodiscard]] VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 47 | [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex( | 47 | ContentRecordType type) const; |
| 48 | u64 title_id, u8 program_index, ContentRecordType type) const; | 48 | [[nodiscard]] VirtualFile Open(u64 title_id, StorageId storage, ContentRecordType type) const; |
| 49 | [[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, | ||
| 50 | ContentRecordType type) const; | ||
| 51 | 49 | ||
| 52 | private: | 50 | private: |
| 53 | [[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage, | 51 | [[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage, |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 70b36f170..a4d060007 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -108,26 +108,16 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_director | |||
| 108 | 108 | ||
| 109 | SaveDataFactory::~SaveDataFactory() = default; | 109 | SaveDataFactory::~SaveDataFactory() = default; |
| 110 | 110 | ||
| 111 | ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, | 111 | VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const { |
| 112 | const SaveDataAttribute& meta) const { | ||
| 113 | PrintSaveDataAttributeWarnings(meta); | 112 | PrintSaveDataAttributeWarnings(meta); |
| 114 | 113 | ||
| 115 | const auto save_directory = | 114 | const auto save_directory = |
| 116 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 115 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
| 117 | 116 | ||
| 118 | auto out = dir->CreateDirectoryRelative(save_directory); | 117 | return dir->CreateDirectoryRelative(save_directory); |
| 119 | |||
| 120 | // Return an error if the save data doesn't actually exist. | ||
| 121 | if (out == nullptr) { | ||
| 122 | // TODO(DarkLordZach): Find out correct error code. | ||
| 123 | return ResultUnknown; | ||
| 124 | } | ||
| 125 | |||
| 126 | return out; | ||
| 127 | } | 118 | } |
| 128 | 119 | ||
| 129 | ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | 120 | VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { |
| 130 | const SaveDataAttribute& meta) const { | ||
| 131 | 121 | ||
| 132 | const auto save_directory = | 122 | const auto save_directory = |
| 133 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); | 123 | GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); |
| @@ -138,12 +128,6 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, | |||
| 138 | return Create(space, meta); | 128 | return Create(space, meta); |
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | // Return an error if the save data doesn't actually exist. | ||
| 142 | if (out == nullptr) { | ||
| 143 | // TODO(Subv): Find out correct error code. | ||
| 144 | return ResultUnknown; | ||
| 145 | } | ||
| 146 | |||
| 147 | return out; | 131 | return out; |
| 148 | } | 132 | } |
| 149 | 133 | ||
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index d3633ef03..45c7c81fb 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -89,8 +89,8 @@ public: | |||
| 89 | explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); | 89 | explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); |
| 90 | ~SaveDataFactory(); | 90 | ~SaveDataFactory(); |
| 91 | 91 | ||
| 92 | ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; | 92 | VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 93 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; | 93 | VirtualDir Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; |
| 94 | 94 | ||
| 95 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; | 95 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; |
| 96 | 96 | ||
diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index 1df022c9e..d5158cd64 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp | |||
| @@ -23,7 +23,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_) | |||
| 23 | 23 | ||
| 24 | SDMCFactory::~SDMCFactory() = default; | 24 | SDMCFactory::~SDMCFactory() = default; |
| 25 | 25 | ||
| 26 | ResultVal<VirtualDir> SDMCFactory::Open() const { | 26 | VirtualDir SDMCFactory::Open() const { |
| 27 | return sd_dir; | 27 | return sd_dir; |
| 28 | } | 28 | } |
| 29 | 29 | ||
diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 3aebfb25e..a445fdb16 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h | |||
| @@ -18,7 +18,7 @@ public: | |||
| 18 | explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); | 18 | explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); |
| 19 | ~SDMCFactory(); | 19 | ~SDMCFactory(); |
| 20 | 20 | ||
| 21 | ResultVal<VirtualDir> Open() const; | 21 | VirtualDir Open() const; |
| 22 | 22 | ||
| 23 | VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; | 23 | VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; |
| 24 | VirtualDir GetSDMCContentDirectory() const; | 24 | VirtualDir GetSDMCContentDirectory() const; |
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index 6b35f448c..00beb40dd 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h | |||
| @@ -289,6 +289,19 @@ enum class GyroscopeZeroDriftMode : u32 { | |||
| 289 | Tight = 2, | 289 | Tight = 2, |
| 290 | }; | 290 | }; |
| 291 | 291 | ||
| 292 | // This is nn::settings::system::TouchScreenMode | ||
| 293 | enum class TouchScreenMode : u32 { | ||
| 294 | Stylus = 0, | ||
| 295 | Standard = 1, | ||
| 296 | }; | ||
| 297 | |||
| 298 | // This is nn::hid::TouchScreenModeForNx | ||
| 299 | enum class TouchScreenModeForNx : u8 { | ||
| 300 | UseSystemSetting, | ||
| 301 | Finger, | ||
| 302 | Heat2, | ||
| 303 | }; | ||
| 304 | |||
| 292 | // This is nn::hid::NpadStyleTag | 305 | // This is nn::hid::NpadStyleTag |
| 293 | struct NpadStyleTag { | 306 | struct NpadStyleTag { |
| 294 | union { | 307 | union { |
| @@ -334,6 +347,14 @@ struct TouchState { | |||
| 334 | }; | 347 | }; |
| 335 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); | 348 | static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size"); |
| 336 | 349 | ||
| 350 | // This is nn::hid::TouchScreenConfigurationForNx | ||
| 351 | struct TouchScreenConfigurationForNx { | ||
| 352 | TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting}; | ||
| 353 | INSERT_PADDING_BYTES(0xF); | ||
| 354 | }; | ||
| 355 | static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10, | ||
| 356 | "TouchScreenConfigurationForNx is an invalid size"); | ||
| 357 | |||
| 337 | struct NpadColor { | 358 | struct NpadColor { |
| 338 | u8 r{}; | 359 | u8 r{}; |
| 339 | u8 g{}; | 360 | u8 g{}; |
| @@ -662,6 +683,11 @@ struct MouseState { | |||
| 662 | }; | 683 | }; |
| 663 | static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); | 684 | static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); |
| 664 | 685 | ||
| 686 | struct UniquePadId { | ||
| 687 | u64 id; | ||
| 688 | }; | ||
| 689 | static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size"); | ||
| 690 | |||
| 665 | /// Converts a NpadIdType to an array index. | 691 | /// Converts a NpadIdType to an array index. |
| 666 | constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { | 692 | constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) { |
| 667 | switch (npad_id_type) { | 693 | switch (npad_id_type) { |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 02b5cada4..9bfc85b34 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -768,7 +768,7 @@ Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size, | |||
| 768 | m_memory_block_slab_manager, num_allocator_blocks); | 768 | m_memory_block_slab_manager, num_allocator_blocks); |
| 769 | R_TRY(allocator_result); | 769 | R_TRY(allocator_result); |
| 770 | 770 | ||
| 771 | CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); | 771 | R_TRY(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); |
| 772 | 772 | ||
| 773 | // Apply the memory block update. | 773 | // Apply the memory block update. |
| 774 | m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages, | 774 | m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages, |
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 240f06689..92a1439eb 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -283,159 +283,6 @@ private: | |||
| 283 | u32 description_end; | 283 | u32 description_end; |
| 284 | }; | 284 | }; |
| 285 | 285 | ||
| 286 | /** | ||
| 287 | * This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it | ||
| 288 | * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying | ||
| 289 | * to access the inner value with operator* is undefined behavior and will assert with Unwrap(). | ||
| 290 | * Users of this class must be cognizant to check the status of the ResultVal with operator bool(), | ||
| 291 | * Code(), Succeeded() or Failed() prior to accessing the inner value. | ||
| 292 | * | ||
| 293 | * An example of how it could be used: | ||
| 294 | * \code | ||
| 295 | * ResultVal<int> Frobnicate(float strength) { | ||
| 296 | * if (strength < 0.f || strength > 1.0f) { | ||
| 297 | * // Can't frobnicate too weakly or too strongly | ||
| 298 | * return Result{ErrorModule::Common, 1}; | ||
| 299 | * } else { | ||
| 300 | * // Frobnicated! Give caller a cookie | ||
| 301 | * return 42; | ||
| 302 | * } | ||
| 303 | * } | ||
| 304 | * \endcode | ||
| 305 | * | ||
| 306 | * \code | ||
| 307 | * auto frob_result = Frobnicate(0.75f); | ||
| 308 | * if (frob_result) { | ||
| 309 | * // Frobbed ok | ||
| 310 | * printf("My cookie is %d\n", *frob_result); | ||
| 311 | * } else { | ||
| 312 | * printf("Guess I overdid it. :( Error code: %ux\n", frob_result.Code().raw); | ||
| 313 | * } | ||
| 314 | * \endcode | ||
| 315 | */ | ||
| 316 | template <typename T> | ||
| 317 | class ResultVal { | ||
| 318 | public: | ||
| 319 | constexpr ResultVal() : expected{} {} | ||
| 320 | |||
| 321 | constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {} | ||
| 322 | |||
| 323 | constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {} | ||
| 324 | |||
| 325 | template <typename U> | ||
| 326 | constexpr ResultVal(U&& val) : expected{std::forward<U>(val)} {} | ||
| 327 | |||
| 328 | template <typename... Args> | ||
| 329 | constexpr ResultVal(Args&&... args) : expected{std::in_place, std::forward<Args>(args)...} {} | ||
| 330 | |||
| 331 | ~ResultVal() = default; | ||
| 332 | |||
| 333 | constexpr ResultVal(const ResultVal&) = default; | ||
| 334 | constexpr ResultVal(ResultVal&&) = default; | ||
| 335 | |||
| 336 | ResultVal& operator=(const ResultVal&) = default; | ||
| 337 | ResultVal& operator=(ResultVal&&) = default; | ||
| 338 | |||
| 339 | [[nodiscard]] constexpr explicit operator bool() const noexcept { | ||
| 340 | return expected.has_value(); | ||
| 341 | } | ||
| 342 | |||
| 343 | [[nodiscard]] constexpr Result Code() const { | ||
| 344 | return expected.has_value() ? ResultSuccess : expected.error(); | ||
| 345 | } | ||
| 346 | |||
| 347 | [[nodiscard]] constexpr bool Succeeded() const { | ||
| 348 | return expected.has_value(); | ||
| 349 | } | ||
| 350 | |||
| 351 | [[nodiscard]] constexpr bool Failed() const { | ||
| 352 | return !expected.has_value(); | ||
| 353 | } | ||
| 354 | |||
| 355 | [[nodiscard]] constexpr T* operator->() { | ||
| 356 | return std::addressof(expected.value()); | ||
| 357 | } | ||
| 358 | |||
| 359 | [[nodiscard]] constexpr const T* operator->() const { | ||
| 360 | return std::addressof(expected.value()); | ||
| 361 | } | ||
| 362 | |||
| 363 | [[nodiscard]] constexpr T& operator*() & { | ||
| 364 | return *expected; | ||
| 365 | } | ||
| 366 | |||
| 367 | [[nodiscard]] constexpr const T& operator*() const& { | ||
| 368 | return *expected; | ||
| 369 | } | ||
| 370 | |||
| 371 | [[nodiscard]] constexpr T&& operator*() && { | ||
| 372 | return *expected; | ||
| 373 | } | ||
| 374 | |||
| 375 | [[nodiscard]] constexpr const T&& operator*() const&& { | ||
| 376 | return *expected; | ||
| 377 | } | ||
| 378 | |||
| 379 | [[nodiscard]] constexpr T& Unwrap() & { | ||
| 380 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 381 | return expected.value(); | ||
| 382 | } | ||
| 383 | |||
| 384 | [[nodiscard]] constexpr const T& Unwrap() const& { | ||
| 385 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 386 | return expected.value(); | ||
| 387 | } | ||
| 388 | |||
| 389 | [[nodiscard]] constexpr T&& Unwrap() && { | ||
| 390 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 391 | return std::move(expected.value()); | ||
| 392 | } | ||
| 393 | |||
| 394 | [[nodiscard]] constexpr const T&& Unwrap() const&& { | ||
| 395 | ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal"); | ||
| 396 | return std::move(expected.value()); | ||
| 397 | } | ||
| 398 | |||
| 399 | template <typename U> | ||
| 400 | [[nodiscard]] constexpr T ValueOr(U&& v) const& { | ||
| 401 | return expected.value_or(v); | ||
| 402 | } | ||
| 403 | |||
| 404 | template <typename U> | ||
| 405 | [[nodiscard]] constexpr T ValueOr(U&& v) && { | ||
| 406 | return expected.value_or(v); | ||
| 407 | } | ||
| 408 | |||
| 409 | private: | ||
| 410 | // TODO (Morph): Replace this with C++23 std::expected. | ||
| 411 | Common::Expected<T, Result> expected; | ||
| 412 | }; | ||
| 413 | |||
| 414 | /** | ||
| 415 | * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps | ||
| 416 | * the contained value and assigns it to `target`, which can be either an l-value expression or a | ||
| 417 | * variable declaration. If it fails the return code is returned from the current function. Thus it | ||
| 418 | * can be used to cascade errors out, achieving something akin to exception handling. | ||
| 419 | */ | ||
| 420 | #define CASCADE_RESULT(target, source) \ | ||
| 421 | auto CONCAT2(check_result_L, __LINE__) = source; \ | ||
| 422 | if (CONCAT2(check_result_L, __LINE__).Failed()) { \ | ||
| 423 | return CONCAT2(check_result_L, __LINE__).Code(); \ | ||
| 424 | } \ | ||
| 425 | target = std::move(*CONCAT2(check_result_L, __LINE__)) | ||
| 426 | |||
| 427 | /** | ||
| 428 | * Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if | ||
| 429 | * non-success, or discarded otherwise. | ||
| 430 | */ | ||
| 431 | #define CASCADE_CODE(source) \ | ||
| 432 | do { \ | ||
| 433 | auto CONCAT2(check_result_L, __LINE__) = source; \ | ||
| 434 | if (CONCAT2(check_result_L, __LINE__).IsError()) { \ | ||
| 435 | return CONCAT2(check_result_L, __LINE__); \ | ||
| 436 | } \ | ||
| 437 | } while (false) | ||
| 438 | |||
| 439 | #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) | 286 | #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) |
| 440 | #define R_FAILED(res) (static_cast<Result>(res).IsFailure()) | 287 | #define R_FAILED(res) (static_cast<Result>(res).IsFailure()) |
| 441 | 288 | ||
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 2632cd3ef..b971401e6 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -765,15 +765,16 @@ Result Module::Interface::InitializeApplicationInfoBase() { | |||
| 765 | // TODO(ogniK): This should be changed to reflect the target process for when we have multiple | 765 | // TODO(ogniK): This should be changed to reflect the target process for when we have multiple |
| 766 | // processes emulated. As we don't actually have pid support we should assume we're just using | 766 | // processes emulated. As we don't actually have pid support we should assume we're just using |
| 767 | // our own process | 767 | // our own process |
| 768 | const auto launch_property = | 768 | Glue::ApplicationLaunchProperty launch_property{}; |
| 769 | system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID()); | 769 | const auto result = system.GetARPManager().GetLaunchProperty( |
| 770 | &launch_property, system.GetApplicationProcessProgramID()); | ||
| 770 | 771 | ||
| 771 | if (launch_property.Failed()) { | 772 | if (result != ResultSuccess) { |
| 772 | LOG_ERROR(Service_ACC, "Failed to get launch property"); | 773 | LOG_ERROR(Service_ACC, "Failed to get launch property"); |
| 773 | return Account::ResultInvalidApplication; | 774 | return Account::ResultInvalidApplication; |
| 774 | } | 775 | } |
| 775 | 776 | ||
| 776 | switch (launch_property->base_game_storage_id) { | 777 | switch (launch_property.base_game_storage_id) { |
| 777 | case FileSys::StorageId::GameCard: | 778 | case FileSys::StorageId::GameCard: |
| 778 | application_info.application_type = ApplicationType::GameCard; | 779 | application_info.application_type = ApplicationType::GameCard; |
| 779 | break; | 780 | break; |
| @@ -785,7 +786,7 @@ Result Module::Interface::InitializeApplicationInfoBase() { | |||
| 785 | break; | 786 | break; |
| 786 | default: | 787 | default: |
| 787 | LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", | 788 | LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", |
| 788 | launch_property->base_game_storage_id); | 789 | launch_property.base_game_storage_id); |
| 789 | return Account::ResultInvalidApplication; | 790 | return Account::ResultInvalidApplication; |
| 790 | } | 791 | } |
| 791 | 792 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4f400d341..8d057b3a8 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1317,6 +1317,50 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | |||
| 1317 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); | 1317 | rb.PushIpcInterface<IStorage>(system, std::move(memory)); |
| 1318 | } | 1318 | } |
| 1319 | 1319 | ||
| 1320 | ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) | ||
| 1321 | : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { | ||
| 1322 | static const FunctionInfo functions[] = { | ||
| 1323 | {0, nullptr, "PopInData"}, | ||
| 1324 | {1, nullptr, "PushOutData"}, | ||
| 1325 | {2, nullptr, "PopInteractiveInData"}, | ||
| 1326 | {3, nullptr, "PushInteractiveOutData"}, | ||
| 1327 | {5, nullptr, "GetPopInDataEvent"}, | ||
| 1328 | {6, nullptr, "GetPopInteractiveInDataEvent"}, | ||
| 1329 | {10, nullptr, "ExitProcessAndReturn"}, | ||
| 1330 | {11, nullptr, "GetLibraryAppletInfo"}, | ||
| 1331 | {12, nullptr, "GetMainAppletIdentityInfo"}, | ||
| 1332 | {13, nullptr, "CanUseApplicationCore"}, | ||
| 1333 | {14, nullptr, "GetCallerAppletIdentityInfo"}, | ||
| 1334 | {15, nullptr, "GetMainAppletApplicationControlProperty"}, | ||
| 1335 | {16, nullptr, "GetMainAppletStorageId"}, | ||
| 1336 | {17, nullptr, "GetCallerAppletIdentityInfoStack"}, | ||
| 1337 | {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, | ||
| 1338 | {19, nullptr, "GetDesirableKeyboardLayout"}, | ||
| 1339 | {20, nullptr, "PopExtraStorage"}, | ||
| 1340 | {25, nullptr, "GetPopExtraStorageEvent"}, | ||
| 1341 | {30, nullptr, "UnpopInData"}, | ||
| 1342 | {31, nullptr, "UnpopExtraStorage"}, | ||
| 1343 | {40, nullptr, "GetIndirectLayerProducerHandle"}, | ||
| 1344 | {50, nullptr, "ReportVisibleError"}, | ||
| 1345 | {51, nullptr, "ReportVisibleErrorWithErrorContext"}, | ||
| 1346 | {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, | ||
| 1347 | {70, nullptr, "GetCurrentApplicationId"}, | ||
| 1348 | {80, nullptr, "RequestExitToSelf"}, | ||
| 1349 | {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, | ||
| 1350 | {100, nullptr, "CreateGameMovieTrimmer"}, | ||
| 1351 | {101, nullptr, "ReserveResourceForMovieOperation"}, | ||
| 1352 | {102, nullptr, "UnreserveResourceForMovieOperation"}, | ||
| 1353 | {110, nullptr, "GetMainAppletAvailableUsers"}, | ||
| 1354 | {120, nullptr, "GetLaunchStorageInfoForDebug"}, | ||
| 1355 | {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, | ||
| 1356 | {140, nullptr, "SetApplicationMemoryReservation"}, | ||
| 1357 | {150, nullptr, "ShouldSetGpuTimeSliceManually"}, | ||
| 1358 | }; | ||
| 1359 | RegisterHandlers(functions); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; | ||
| 1363 | |||
| 1320 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | 1364 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) |
| 1321 | : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, | 1365 | : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, |
| 1322 | "IApplicationFunctions"} { | 1366 | "IApplicationFunctions"} { |
| @@ -1534,11 +1578,13 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) { | |||
| 1534 | attribute.title_id = system.GetApplicationProcessProgramID(); | 1578 | attribute.title_id = system.GetApplicationProcessProgramID(); |
| 1535 | attribute.user_id = user_id; | 1579 | attribute.user_id = user_id; |
| 1536 | attribute.type = FileSys::SaveDataType::SaveData; | 1580 | attribute.type = FileSys::SaveDataType::SaveData; |
| 1581 | |||
| 1582 | FileSys::VirtualDir save_data{}; | ||
| 1537 | const auto res = system.GetFileSystemController().CreateSaveData( | 1583 | const auto res = system.GetFileSystemController().CreateSaveData( |
| 1538 | FileSys::SaveDataSpaceId::NandUser, attribute); | 1584 | &save_data, FileSys::SaveDataSpaceId::NandUser, attribute); |
| 1539 | 1585 | ||
| 1540 | IPC::ResponseBuilder rb{ctx, 4}; | 1586 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1541 | rb.Push(res.Code()); | 1587 | rb.Push(res); |
| 1542 | rb.Push<u64>(0); | 1588 | rb.Push<u64>(0); |
| 1543 | } | 1589 | } |
| 1544 | 1590 | ||
| @@ -1623,26 +1669,30 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) { | |||
| 1623 | auto app_man = ns_am2->GetApplicationManagerInterface(); | 1669 | auto app_man = ns_am2->GetApplicationManagerInterface(); |
| 1624 | 1670 | ||
| 1625 | // Get desired application language | 1671 | // Get desired application language |
| 1626 | const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages); | 1672 | u8 desired_language{}; |
| 1627 | if (res_lang.Failed()) { | 1673 | const auto res_lang = |
| 1674 | app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages); | ||
| 1675 | if (res_lang != ResultSuccess) { | ||
| 1628 | IPC::ResponseBuilder rb{ctx, 2}; | 1676 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1629 | rb.Push(res_lang.Code()); | 1677 | rb.Push(res_lang); |
| 1630 | return; | 1678 | return; |
| 1631 | } | 1679 | } |
| 1632 | 1680 | ||
| 1633 | // Convert to settings language code. | 1681 | // Convert to settings language code. |
| 1634 | const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang); | 1682 | u64 language_code{}; |
| 1635 | if (res_code.Failed()) { | 1683 | const auto res_code = |
| 1684 | app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language); | ||
| 1685 | if (res_code != ResultSuccess) { | ||
| 1636 | IPC::ResponseBuilder rb{ctx, 2}; | 1686 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1637 | rb.Push(res_code.Code()); | 1687 | rb.Push(res_code); |
| 1638 | return; | 1688 | return; |
| 1639 | } | 1689 | } |
| 1640 | 1690 | ||
| 1641 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code); | 1691 | LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); |
| 1642 | 1692 | ||
| 1643 | IPC::ResponseBuilder rb{ctx, 4}; | 1693 | IPC::ResponseBuilder rb{ctx, 4}; |
| 1644 | rb.Push(ResultSuccess); | 1694 | rb.Push(ResultSuccess); |
| 1645 | rb.Push(*res_code); | 1695 | rb.Push(language_code); |
| 1646 | } | 1696 | } |
| 1647 | 1697 | ||
| 1648 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { | 1698 | void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index d4fd163da..d68998f04 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -22,30 +22,6 @@ class Nvnflinger; | |||
| 22 | 22 | ||
| 23 | namespace Service::AM { | 23 | namespace Service::AM { |
| 24 | 24 | ||
| 25 | // This is nn::settings::Language | ||
| 26 | enum SystemLanguage { | ||
| 27 | Japanese = 0, | ||
| 28 | English = 1, // en-US | ||
| 29 | French = 2, | ||
| 30 | German = 3, | ||
| 31 | Italian = 4, | ||
| 32 | Spanish = 5, | ||
| 33 | Chinese = 6, | ||
| 34 | Korean = 7, | ||
| 35 | Dutch = 8, | ||
| 36 | Portuguese = 9, | ||
| 37 | Russian = 10, | ||
| 38 | Taiwanese = 11, | ||
| 39 | BritishEnglish = 12, // en-GB | ||
| 40 | CanadianFrench = 13, | ||
| 41 | LatinAmericanSpanish = 14, // es-419 | ||
| 42 | // 4.0.0+ | ||
| 43 | SimplifiedChinese = 15, | ||
| 44 | TraditionalChinese = 16, | ||
| 45 | // 10.1.0+ | ||
| 46 | BrazilianPortuguese = 17, | ||
| 47 | }; | ||
| 48 | |||
| 49 | class AppletMessageQueue { | 25 | class AppletMessageQueue { |
| 50 | public: | 26 | public: |
| 51 | // This is nn::am::AppletMessage | 27 | // This is nn::am::AppletMessage |
| @@ -314,6 +290,12 @@ private: | |||
| 314 | void CreateHandleStorage(HLERequestContext& ctx); | 290 | void CreateHandleStorage(HLERequestContext& ctx); |
| 315 | }; | 291 | }; |
| 316 | 292 | ||
| 293 | class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { | ||
| 294 | public: | ||
| 295 | explicit ILibraryAppletSelfAccessor(Core::System& system_); | ||
| 296 | ~ILibraryAppletSelfAccessor() override; | ||
| 297 | }; | ||
| 298 | |||
| 317 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | 299 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { |
| 318 | public: | 300 | public: |
| 319 | explicit IApplicationFunctions(Core::System& system_); | 301 | explicit IApplicationFunctions(Core::System& system_); |
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 2764f7ceb..ee9d99a54 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp | |||
| @@ -26,8 +26,10 @@ public: | |||
| 26 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, | 26 | {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, |
| 27 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, | 27 | {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, |
| 28 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, | 28 | {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, |
| 29 | {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"}, | 29 | {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, |
| 30 | {21, nullptr, "GetAppletCommonFunctions"}, | 30 | {21, nullptr, "GetAppletCommonFunctions"}, |
| 31 | {22, nullptr, "GetHomeMenuFunctions"}, | ||
| 32 | {23, nullptr, "GetGlobalStateController"}, | ||
| 31 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, | 33 | {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, |
| 32 | }; | 34 | }; |
| 33 | // clang-format on | 35 | // clang-format on |
| @@ -100,12 +102,12 @@ private: | |||
| 100 | rb.PushIpcInterface<ILibraryAppletCreator>(system); | 102 | rb.PushIpcInterface<ILibraryAppletCreator>(system); |
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | void GetApplicationFunctions(HLERequestContext& ctx) { | 105 | void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { |
| 104 | LOG_DEBUG(Service_AM, "called"); | 106 | LOG_DEBUG(Service_AM, "called"); |
| 105 | 107 | ||
| 106 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 108 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 107 | rb.Push(ResultSuccess); | 109 | rb.Push(ResultSuccess); |
| 108 | rb.PushIpcInterface<IApplicationFunctions>(system); | 110 | rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); |
| 109 | } | 111 | } |
| 110 | 112 | ||
| 111 | Nvnflinger::Nvnflinger& nvnflinger; | 113 | Nvnflinger::Nvnflinger& nvnflinger; |
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 7ad93be6b..66dd64fd1 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp | |||
| @@ -22,13 +22,13 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { | |||
| 22 | {9, nullptr, "GetAudioOutputMode"}, | 22 | {9, nullptr, "GetAudioOutputMode"}, |
| 23 | {10, nullptr, "SetAudioOutputMode"}, | 23 | {10, nullptr, "SetAudioOutputMode"}, |
| 24 | {11, nullptr, "SetForceMutePolicy"}, | 24 | {11, nullptr, "SetForceMutePolicy"}, |
| 25 | {12, nullptr, "GetForceMutePolicy"}, | 25 | {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, |
| 26 | {13, nullptr, "GetOutputModeSetting"}, | 26 | {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, |
| 27 | {14, nullptr, "SetOutputModeSetting"}, | 27 | {14, nullptr, "SetOutputModeSetting"}, |
| 28 | {15, nullptr, "SetOutputTarget"}, | 28 | {15, nullptr, "SetOutputTarget"}, |
| 29 | {16, nullptr, "SetInputTargetForceEnabled"}, | 29 | {16, nullptr, "SetInputTargetForceEnabled"}, |
| 30 | {17, nullptr, "SetHeadphoneOutputLevelMode"}, | 30 | {17, nullptr, "SetHeadphoneOutputLevelMode"}, |
| 31 | {18, nullptr, "GetHeadphoneOutputLevelMode"}, | 31 | {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, |
| 32 | {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, | 32 | {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, |
| 33 | {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, | 33 | {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, |
| 34 | {21, nullptr, "GetAudioOutputTargetForPlayReport"}, | 34 | {21, nullptr, "GetAudioOutputTargetForPlayReport"}, |
| @@ -41,7 +41,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { | |||
| 41 | {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, | 41 | {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, |
| 42 | {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, | 42 | {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, |
| 43 | {30, nullptr, "SetSpeakerAutoMuteEnabled"}, | 43 | {30, nullptr, "SetSpeakerAutoMuteEnabled"}, |
| 44 | {31, nullptr, "IsSpeakerAutoMuteEnabled"}, | 44 | {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, |
| 45 | {32, nullptr, "GetActiveOutputTarget"}, | 45 | {32, nullptr, "GetActiveOutputTarget"}, |
| 46 | {33, nullptr, "GetTargetDeviceInfo"}, | 46 | {33, nullptr, "GetTargetDeviceInfo"}, |
| 47 | {34, nullptr, "AcquireTargetNotification"}, | 47 | {34, nullptr, "AcquireTargetNotification"}, |
| @@ -96,4 +96,42 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) { | |||
| 96 | rb.Push(target_max_volume); | 96 | rb.Push(target_max_volume); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { | ||
| 100 | LOG_WARNING(Audio, "(STUBBED) called"); | ||
| 101 | |||
| 102 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 103 | rb.Push(ResultSuccess); | ||
| 104 | rb.PushEnum(ForceMutePolicy::Disable); | ||
| 105 | } | ||
| 106 | |||
| 107 | void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { | ||
| 108 | IPC::RequestParser rp{ctx}; | ||
| 109 | const auto value = rp.Pop<u32>(); | ||
| 110 | |||
| 111 | LOG_WARNING(Audio, "(STUBBED) called, value={}", value); | ||
| 112 | |||
| 113 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 114 | rb.Push(ResultSuccess); | ||
| 115 | rb.PushEnum(AudioOutputMode::PcmAuto); | ||
| 116 | } | ||
| 117 | |||
| 118 | void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { | ||
| 119 | LOG_WARNING(Audio, "(STUBBED) called"); | ||
| 120 | |||
| 121 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 122 | rb.Push(ResultSuccess); | ||
| 123 | rb.PushEnum(HeadphoneOutputLevelMode::Normal); | ||
| 124 | } | ||
| 125 | |||
| 126 | void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { | ||
| 127 | const bool is_speaker_auto_mute_enabled = false; | ||
| 128 | |||
| 129 | LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", | ||
| 130 | is_speaker_auto_mute_enabled); | ||
| 131 | |||
| 132 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 133 | rb.Push(ResultSuccess); | ||
| 134 | rb.Push<u8>(is_speaker_auto_mute_enabled); | ||
| 135 | } | ||
| 136 | |||
| 99 | } // namespace Service::Audio | 137 | } // namespace Service::Audio |
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index 8e31ac237..d57abb383 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h | |||
| @@ -17,8 +17,30 @@ public: | |||
| 17 | ~AudCtl() override; | 17 | ~AudCtl() override; |
| 18 | 18 | ||
| 19 | private: | 19 | private: |
| 20 | enum class AudioOutputMode { | ||
| 21 | Invalid, | ||
| 22 | Pcm1ch, | ||
| 23 | Pcm2ch, | ||
| 24 | Pcm6ch, | ||
| 25 | PcmAuto, | ||
| 26 | }; | ||
| 27 | |||
| 28 | enum class ForceMutePolicy { | ||
| 29 | Disable, | ||
| 30 | SpeakerMuteOnHeadphoneUnplugged, | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum class HeadphoneOutputLevelMode { | ||
| 34 | Normal, | ||
| 35 | HighPower, | ||
| 36 | }; | ||
| 37 | |||
| 20 | void GetTargetVolumeMin(HLERequestContext& ctx); | 38 | void GetTargetVolumeMin(HLERequestContext& ctx); |
| 21 | void GetTargetVolumeMax(HLERequestContext& ctx); | 39 | void GetTargetVolumeMax(HLERequestContext& ctx); |
| 40 | void GetForceMutePolicy(HLERequestContext& ctx); | ||
| 41 | void GetOutputModeSetting(HLERequestContext& ctx); | ||
| 42 | void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); | ||
| 43 | void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); | ||
| 22 | }; | 44 | }; |
| 23 | 45 | ||
| 24 | } // namespace Service::Audio | 46 | } // namespace Service::Audio |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index dfcdd3ada..ac465d5a9 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -57,8 +57,8 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size | |||
| 57 | return FileSys::ERROR_PATH_NOT_FOUND; | 57 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | const auto entry_type = GetEntryType(path); | 60 | FileSys::EntryType entry_type{}; |
| 61 | if (entry_type.Code() == ResultSuccess) { | 61 | if (GetEntryType(&entry_type, path) == ResultSuccess) { |
| 62 | return FileSys::ERROR_PATH_ALREADY_EXISTS; | 62 | return FileSys::ERROR_PATH_ALREADY_EXISTS; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| @@ -210,8 +210,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, | |||
| 210 | return ResultUnknown; | 210 | return ResultUnknown; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_, | 213 | Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, |
| 214 | FileSys::Mode mode) const { | 214 | const std::string& path_, FileSys::Mode mode) const { |
| 215 | const std::string path(Common::FS::SanitizePath(path_)); | 215 | const std::string path(Common::FS::SanitizePath(path_)); |
| 216 | std::string_view npath = path; | 216 | std::string_view npath = path; |
| 217 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { | 217 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { |
| @@ -224,50 +224,68 @@ ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std:: | |||
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | if (mode == FileSys::Mode::Append) { | 226 | if (mode == FileSys::Mode::Append) { |
| 227 | return std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); | 227 | *out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); |
| 228 | } else { | ||
| 229 | *out_file = file; | ||
| 228 | } | 230 | } |
| 229 | 231 | ||
| 230 | return file; | 232 | return ResultSuccess; |
| 231 | } | 233 | } |
| 232 | 234 | ||
| 233 | ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) { | 235 | Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_directory, |
| 236 | const std::string& path_) { | ||
| 234 | std::string path(Common::FS::SanitizePath(path_)); | 237 | std::string path(Common::FS::SanitizePath(path_)); |
| 235 | auto dir = GetDirectoryRelativeWrapped(backing, path); | 238 | auto dir = GetDirectoryRelativeWrapped(backing, path); |
| 236 | if (dir == nullptr) { | 239 | if (dir == nullptr) { |
| 237 | // TODO(DarkLordZach): Find a better error code for this | 240 | // TODO(DarkLordZach): Find a better error code for this |
| 238 | return FileSys::ERROR_PATH_NOT_FOUND; | 241 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 239 | } | 242 | } |
| 240 | return dir; | 243 | *out_directory = dir; |
| 244 | return ResultSuccess; | ||
| 241 | } | 245 | } |
| 242 | 246 | ||
| 243 | ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( | 247 | Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, |
| 244 | const std::string& path_) const { | 248 | const std::string& path_) const { |
| 245 | std::string path(Common::FS::SanitizePath(path_)); | 249 | std::string path(Common::FS::SanitizePath(path_)); |
| 246 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 250 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 247 | if (dir == nullptr) | 251 | if (dir == nullptr) { |
| 248 | return FileSys::ERROR_PATH_NOT_FOUND; | 252 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 253 | } | ||
| 254 | |||
| 249 | auto filename = Common::FS::GetFilename(path); | 255 | auto filename = Common::FS::GetFilename(path); |
| 250 | // TODO(Subv): Some games use the '/' path, find out what this means. | 256 | // TODO(Subv): Some games use the '/' path, find out what this means. |
| 251 | if (filename.empty()) | 257 | if (filename.empty()) { |
| 252 | return FileSys::EntryType::Directory; | 258 | *out_entry_type = FileSys::EntryType::Directory; |
| 259 | return ResultSuccess; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (dir->GetFile(filename) != nullptr) { | ||
| 263 | *out_entry_type = FileSys::EntryType::File; | ||
| 264 | return ResultSuccess; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (dir->GetSubdirectory(filename) != nullptr) { | ||
| 268 | *out_entry_type = FileSys::EntryType::Directory; | ||
| 269 | return ResultSuccess; | ||
| 270 | } | ||
| 253 | 271 | ||
| 254 | if (dir->GetFile(filename) != nullptr) | ||
| 255 | return FileSys::EntryType::File; | ||
| 256 | if (dir->GetSubdirectory(filename) != nullptr) | ||
| 257 | return FileSys::EntryType::Directory; | ||
| 258 | return FileSys::ERROR_PATH_NOT_FOUND; | 272 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 259 | } | 273 | } |
| 260 | 274 | ||
| 261 | ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw( | 275 | Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( |
| 262 | const std::string& path) const { | 276 | FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const { |
| 263 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 277 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 264 | if (dir == nullptr) { | 278 | if (dir == nullptr) { |
| 265 | return FileSys::ERROR_PATH_NOT_FOUND; | 279 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 266 | } | 280 | } |
| 267 | if (GetEntryType(path).Failed()) { | 281 | |
| 282 | FileSys::EntryType entry_type; | ||
| 283 | if (GetEntryType(&entry_type, path) != ResultSuccess) { | ||
| 268 | return FileSys::ERROR_PATH_NOT_FOUND; | 284 | return FileSys::ERROR_PATH_NOT_FOUND; |
| 269 | } | 285 | } |
| 270 | return dir->GetFileTimeStamp(Common::FS::GetFilename(path)); | 286 | |
| 287 | *out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path)); | ||
| 288 | return ResultSuccess; | ||
| 271 | } | 289 | } |
| 272 | 290 | ||
| 273 | FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} | 291 | FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} |
| @@ -310,57 +328,54 @@ void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) { | |||
| 310 | romfs_factory->SetPackedUpdate(std::move(update_raw)); | 328 | romfs_factory->SetPackedUpdate(std::move(update_raw)); |
| 311 | } | 329 | } |
| 312 | 330 | ||
| 313 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() const { | 331 | FileSys::VirtualFile FileSystemController::OpenRomFSCurrentProcess() const { |
| 314 | LOG_TRACE(Service_FS, "Opening RomFS for current process"); | 332 | LOG_TRACE(Service_FS, "Opening RomFS for current process"); |
| 315 | 333 | ||
| 316 | if (romfs_factory == nullptr) { | 334 | if (romfs_factory == nullptr) { |
| 317 | // TODO(bunnei): Find a better error code for this | 335 | return nullptr; |
| 318 | return ResultUnknown; | ||
| 319 | } | 336 | } |
| 320 | 337 | ||
| 321 | return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); | 338 | return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); |
| 322 | } | 339 | } |
| 323 | 340 | ||
| 324 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS( | 341 | FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id, |
| 325 | u64 title_id, FileSys::ContentRecordType type) const { | 342 | FileSys::ContentRecordType type) const { |
| 326 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id); | 343 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id); |
| 327 | 344 | ||
| 328 | if (romfs_factory == nullptr) { | 345 | if (romfs_factory == nullptr) { |
| 329 | // TODO: Find a better error code for this | 346 | return nullptr; |
| 330 | return ResultUnknown; | ||
| 331 | } | 347 | } |
| 332 | 348 | ||
| 333 | return romfs_factory->OpenPatchedRomFS(title_id, type); | 349 | return romfs_factory->OpenPatchedRomFS(title_id, type); |
| 334 | } | 350 | } |
| 335 | 351 | ||
| 336 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFSWithProgramIndex( | 352 | FileSys::VirtualFile FileSystemController::OpenPatchedRomFSWithProgramIndex( |
| 337 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const { | 353 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const { |
| 338 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id, | 354 | LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id, |
| 339 | program_index); | 355 | program_index); |
| 340 | 356 | ||
| 341 | if (romfs_factory == nullptr) { | 357 | if (romfs_factory == nullptr) { |
| 342 | // TODO: Find a better error code for this | 358 | return nullptr; |
| 343 | return ResultUnknown; | ||
| 344 | } | 359 | } |
| 345 | 360 | ||
| 346 | return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type); | 361 | return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type); |
| 347 | } | 362 | } |
| 348 | 363 | ||
| 349 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS( | 364 | FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id, |
| 350 | u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const { | 365 | FileSys::ContentRecordType type) const { |
| 351 | LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", | 366 | LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", |
| 352 | title_id, storage_id, type); | 367 | title_id, storage_id, type); |
| 353 | 368 | ||
| 354 | if (romfs_factory == nullptr) { | 369 | if (romfs_factory == nullptr) { |
| 355 | // TODO(bunnei): Find a better error code for this | 370 | return nullptr; |
| 356 | return ResultUnknown; | ||
| 357 | } | 371 | } |
| 358 | 372 | ||
| 359 | return romfs_factory->Open(title_id, storage_id, type); | 373 | return romfs_factory->Open(title_id, storage_id, type); |
| 360 | } | 374 | } |
| 361 | 375 | ||
| 362 | ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | 376 | Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data, |
| 363 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const { | 377 | FileSys::SaveDataSpaceId space, |
| 378 | const FileSys::SaveDataAttribute& save_struct) const { | ||
| 364 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space, | 379 | LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space, |
| 365 | save_struct.DebugInfo()); | 380 | save_struct.DebugInfo()); |
| 366 | 381 | ||
| @@ -368,11 +383,18 @@ ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData( | |||
| 368 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 383 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 369 | } | 384 | } |
| 370 | 385 | ||
| 371 | return save_data_factory->Create(space, save_struct); | 386 | auto save_data = save_data_factory->Create(space, save_struct); |
| 387 | if (save_data == nullptr) { | ||
| 388 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 389 | } | ||
| 390 | |||
| 391 | *out_save_data = save_data; | ||
| 392 | return ResultSuccess; | ||
| 372 | } | 393 | } |
| 373 | 394 | ||
| 374 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( | 395 | Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data, |
| 375 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const { | 396 | FileSys::SaveDataSpaceId space, |
| 397 | const FileSys::SaveDataAttribute& attribute) const { | ||
| 376 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space, | 398 | LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space, |
| 377 | attribute.DebugInfo()); | 399 | attribute.DebugInfo()); |
| 378 | 400 | ||
| @@ -380,32 +402,50 @@ ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData( | |||
| 380 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 402 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 381 | } | 403 | } |
| 382 | 404 | ||
| 383 | return save_data_factory->Open(space, attribute); | 405 | auto save_data = save_data_factory->Open(space, attribute); |
| 406 | if (save_data == nullptr) { | ||
| 407 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 408 | } | ||
| 409 | |||
| 410 | *out_save_data = save_data; | ||
| 411 | return ResultSuccess; | ||
| 384 | } | 412 | } |
| 385 | 413 | ||
| 386 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace( | 414 | Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, |
| 387 | FileSys::SaveDataSpaceId space) const { | 415 | FileSys::SaveDataSpaceId space) const { |
| 388 | LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); | 416 | LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); |
| 389 | 417 | ||
| 390 | if (save_data_factory == nullptr) { | 418 | if (save_data_factory == nullptr) { |
| 391 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 419 | return FileSys::ERROR_ENTITY_NOT_FOUND; |
| 392 | } | 420 | } |
| 393 | 421 | ||
| 394 | return save_data_factory->GetSaveDataSpaceDirectory(space); | 422 | auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space); |
| 423 | if (save_data_space == nullptr) { | ||
| 424 | return FileSys::ERROR_ENTITY_NOT_FOUND; | ||
| 425 | } | ||
| 426 | |||
| 427 | *out_save_data_space = save_data_space; | ||
| 428 | return ResultSuccess; | ||
| 395 | } | 429 | } |
| 396 | 430 | ||
| 397 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const { | 431 | Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const { |
| 398 | LOG_TRACE(Service_FS, "Opening SDMC"); | 432 | LOG_TRACE(Service_FS, "Opening SDMC"); |
| 399 | 433 | ||
| 400 | if (sdmc_factory == nullptr) { | 434 | if (sdmc_factory == nullptr) { |
| 401 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | 435 | return FileSys::ERROR_SD_CARD_NOT_FOUND; |
| 402 | } | 436 | } |
| 403 | 437 | ||
| 404 | return sdmc_factory->Open(); | 438 | auto sdmc = sdmc_factory->Open(); |
| 439 | if (sdmc == nullptr) { | ||
| 440 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | ||
| 441 | } | ||
| 442 | |||
| 443 | *out_sdmc = sdmc; | ||
| 444 | return ResultSuccess; | ||
| 405 | } | 445 | } |
| 406 | 446 | ||
| 407 | ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition( | 447 | Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_partition, |
| 408 | FileSys::BisPartitionId id) const { | 448 | FileSys::BisPartitionId id) const { |
| 409 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); | 449 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); |
| 410 | 450 | ||
| 411 | if (bis_factory == nullptr) { | 451 | if (bis_factory == nullptr) { |
| @@ -417,11 +457,12 @@ ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition( | |||
| 417 | return FileSys::ERROR_INVALID_ARGUMENT; | 457 | return FileSys::ERROR_INVALID_ARGUMENT; |
| 418 | } | 458 | } |
| 419 | 459 | ||
| 420 | return part; | 460 | *out_bis_partition = part; |
| 461 | return ResultSuccess; | ||
| 421 | } | 462 | } |
| 422 | 463 | ||
| 423 | ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage( | 464 | Result FileSystemController::OpenBISPartitionStorage( |
| 424 | FileSys::BisPartitionId id) const { | 465 | FileSys::VirtualFile* out_bis_partition_storage, FileSys::BisPartitionId id) const { |
| 425 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); | 466 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); |
| 426 | 467 | ||
| 427 | if (bis_factory == nullptr) { | 468 | if (bis_factory == nullptr) { |
| @@ -433,7 +474,8 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage( | |||
| 433 | return FileSys::ERROR_INVALID_ARGUMENT; | 474 | return FileSys::ERROR_INVALID_ARGUMENT; |
| 434 | } | 475 | } |
| 435 | 476 | ||
| 436 | return part; | 477 | *out_bis_partition_storage = part; |
| 478 | return ResultSuccess; | ||
| 437 | } | 479 | } |
| 438 | 480 | ||
| 439 | u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const { | 481 | u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const { |
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index a5c1c9d3e..fd991f976 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -64,21 +64,24 @@ public: | |||
| 64 | Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); | 64 | Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); |
| 65 | 65 | ||
| 66 | void SetPackedUpdate(FileSys::VirtualFile update_raw); | 66 | void SetPackedUpdate(FileSys::VirtualFile update_raw); |
| 67 | ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const; | 67 | FileSys::VirtualFile OpenRomFSCurrentProcess() const; |
| 68 | ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id, | 68 | FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const; |
| 69 | FileSys::ContentRecordType type) const; | 69 | FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, |
| 70 | ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex( | 70 | FileSys::ContentRecordType type) const; |
| 71 | u64 title_id, u8 program_index, FileSys::ContentRecordType type) const; | 71 | FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id, |
| 72 | ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id, | 72 | FileSys::ContentRecordType type) const; |
| 73 | FileSys::ContentRecordType type) const; | 73 | |
| 74 | ResultVal<FileSys::VirtualDir> CreateSaveData( | 74 | Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, |
| 75 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; | 75 | const FileSys::SaveDataAttribute& save_struct) const; |
| 76 | ResultVal<FileSys::VirtualDir> OpenSaveData( | 76 | Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, |
| 77 | FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const; | 77 | const FileSys::SaveDataAttribute& save_struct) const; |
| 78 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const; | 78 | Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, |
| 79 | ResultVal<FileSys::VirtualDir> OpenSDMC() const; | 79 | FileSys::SaveDataSpaceId space) const; |
| 80 | ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const; | 80 | Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const; |
| 81 | ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const; | 81 | Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition, |
| 82 | FileSys::BisPartitionId id) const; | ||
| 83 | Result OpenBISPartitionStorage(FileSys::VirtualFile* out_bis_partition_storage, | ||
| 84 | FileSys::BisPartitionId id) const; | ||
| 82 | 85 | ||
| 83 | u64 GetFreeSpaceSize(FileSys::StorageId id) const; | 86 | u64 GetFreeSpaceSize(FileSys::StorageId id) const; |
| 84 | u64 GetTotalSpaceSize(FileSys::StorageId id) const; | 87 | u64 GetTotalSpaceSize(FileSys::StorageId id) const; |
| @@ -224,26 +227,28 @@ public: | |||
| 224 | * @param mode Mode to open the file with | 227 | * @param mode Mode to open the file with |
| 225 | * @return Opened file, or error code | 228 | * @return Opened file, or error code |
| 226 | */ | 229 | */ |
| 227 | ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const; | 230 | Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, |
| 231 | FileSys::Mode mode) const; | ||
| 228 | 232 | ||
| 229 | /** | 233 | /** |
| 230 | * Open a directory specified by its path | 234 | * Open a directory specified by its path |
| 231 | * @param path Path relative to the archive | 235 | * @param path Path relative to the archive |
| 232 | * @return Opened directory, or error code | 236 | * @return Opened directory, or error code |
| 233 | */ | 237 | */ |
| 234 | ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path); | 238 | Result OpenDirectory(FileSys::VirtualDir* out_directory, const std::string& path); |
| 235 | 239 | ||
| 236 | /** | 240 | /** |
| 237 | * Get the type of the specified path | 241 | * Get the type of the specified path |
| 238 | * @return The type of the specified path or error code | 242 | * @return The type of the specified path or error code |
| 239 | */ | 243 | */ |
| 240 | ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const; | 244 | Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const; |
| 241 | 245 | ||
| 242 | /** | 246 | /** |
| 243 | * Get the timestamp of the specified path | 247 | * Get the timestamp of the specified path |
| 244 | * @return The timestamp of the specified path or error code | 248 | * @return The timestamp of the specified path or error code |
| 245 | */ | 249 | */ |
| 246 | ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const; | 250 | Result GetFileTimeStampRaw(FileSys::FileTimeStampRaw* out_time_stamp_raw, |
| 251 | const std::string& path) const; | ||
| 247 | 252 | ||
| 248 | private: | 253 | private: |
| 249 | FileSys::VirtualDir backing; | 254 | FileSys::VirtualDir backing; |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 427dbc8b3..423a814cb 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -419,14 +419,15 @@ public: | |||
| 419 | 419 | ||
| 420 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); | 420 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); |
| 421 | 421 | ||
| 422 | auto result = backend.OpenFile(name, mode); | 422 | FileSys::VirtualFile vfs_file{}; |
| 423 | if (result.Failed()) { | 423 | auto result = backend.OpenFile(&vfs_file, name, mode); |
| 424 | if (result != ResultSuccess) { | ||
| 424 | IPC::ResponseBuilder rb{ctx, 2}; | 425 | IPC::ResponseBuilder rb{ctx, 2}; |
| 425 | rb.Push(result.Code()); | 426 | rb.Push(result); |
| 426 | return; | 427 | return; |
| 427 | } | 428 | } |
| 428 | 429 | ||
| 429 | auto file = std::make_shared<IFile>(system, result.Unwrap()); | 430 | auto file = std::make_shared<IFile>(system, vfs_file); |
| 430 | 431 | ||
| 431 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 432 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 432 | rb.Push(ResultSuccess); | 433 | rb.Push(ResultSuccess); |
| @@ -444,14 +445,15 @@ public: | |||
| 444 | 445 | ||
| 445 | LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags); | 446 | LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags); |
| 446 | 447 | ||
| 447 | auto result = backend.OpenDirectory(name); | 448 | FileSys::VirtualDir vfs_dir{}; |
| 448 | if (result.Failed()) { | 449 | auto result = backend.OpenDirectory(&vfs_dir, name); |
| 450 | if (result != ResultSuccess) { | ||
| 449 | IPC::ResponseBuilder rb{ctx, 2}; | 451 | IPC::ResponseBuilder rb{ctx, 2}; |
| 450 | rb.Push(result.Code()); | 452 | rb.Push(result); |
| 451 | return; | 453 | return; |
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | auto directory = std::make_shared<IDirectory>(system, result.Unwrap()); | 456 | auto directory = std::make_shared<IDirectory>(system, vfs_dir); |
| 455 | 457 | ||
| 456 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 458 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 457 | rb.Push(ResultSuccess); | 459 | rb.Push(ResultSuccess); |
| @@ -464,16 +466,17 @@ public: | |||
| 464 | 466 | ||
| 465 | LOG_DEBUG(Service_FS, "called. file={}", name); | 467 | LOG_DEBUG(Service_FS, "called. file={}", name); |
| 466 | 468 | ||
| 467 | auto result = backend.GetEntryType(name); | 469 | FileSys::EntryType vfs_entry_type{}; |
| 468 | if (result.Failed()) { | 470 | auto result = backend.GetEntryType(&vfs_entry_type, name); |
| 471 | if (result != ResultSuccess) { | ||
| 469 | IPC::ResponseBuilder rb{ctx, 2}; | 472 | IPC::ResponseBuilder rb{ctx, 2}; |
| 470 | rb.Push(result.Code()); | 473 | rb.Push(result); |
| 471 | return; | 474 | return; |
| 472 | } | 475 | } |
| 473 | 476 | ||
| 474 | IPC::ResponseBuilder rb{ctx, 3}; | 477 | IPC::ResponseBuilder rb{ctx, 3}; |
| 475 | rb.Push(ResultSuccess); | 478 | rb.Push(ResultSuccess); |
| 476 | rb.Push<u32>(static_cast<u32>(*result)); | 479 | rb.Push<u32>(static_cast<u32>(vfs_entry_type)); |
| 477 | } | 480 | } |
| 478 | 481 | ||
| 479 | void Commit(HLERequestContext& ctx) { | 482 | void Commit(HLERequestContext& ctx) { |
| @@ -505,16 +508,17 @@ public: | |||
| 505 | 508 | ||
| 506 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); | 509 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); |
| 507 | 510 | ||
| 508 | auto result = backend.GetFileTimeStampRaw(name); | 511 | FileSys::FileTimeStampRaw vfs_timestamp{}; |
| 509 | if (result.Failed()) { | 512 | auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); |
| 513 | if (result != ResultSuccess) { | ||
| 510 | IPC::ResponseBuilder rb{ctx, 2}; | 514 | IPC::ResponseBuilder rb{ctx, 2}; |
| 511 | rb.Push(result.Code()); | 515 | rb.Push(result); |
| 512 | return; | 516 | return; |
| 513 | } | 517 | } |
| 514 | 518 | ||
| 515 | IPC::ResponseBuilder rb{ctx, 10}; | 519 | IPC::ResponseBuilder rb{ctx, 10}; |
| 516 | rb.Push(ResultSuccess); | 520 | rb.Push(ResultSuccess); |
| 517 | rb.PushRaw(*result); | 521 | rb.PushRaw(vfs_timestamp); |
| 518 | } | 522 | } |
| 519 | 523 | ||
| 520 | private: | 524 | private: |
| @@ -572,14 +576,15 @@ private: | |||
| 572 | } | 576 | } |
| 573 | 577 | ||
| 574 | void FindAllSaves(FileSys::SaveDataSpaceId space) { | 578 | void FindAllSaves(FileSys::SaveDataSpaceId space) { |
| 575 | const auto save_root = fsc.OpenSaveDataSpace(space); | 579 | FileSys::VirtualDir save_root{}; |
| 580 | const auto result = fsc.OpenSaveDataSpace(&save_root, space); | ||
| 576 | 581 | ||
| 577 | if (save_root.Failed() || *save_root == nullptr) { | 582 | if (result != ResultSuccess || save_root == nullptr) { |
| 578 | LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); | 583 | LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); |
| 579 | return; | 584 | return; |
| 580 | } | 585 | } |
| 581 | 586 | ||
| 582 | for (const auto& type : (*save_root)->GetSubdirectories()) { | 587 | for (const auto& type : save_root->GetSubdirectories()) { |
| 583 | if (type->GetName() == "save") { | 588 | if (type->GetName() == "save") { |
| 584 | for (const auto& save_id : type->GetSubdirectories()) { | 589 | for (const auto& save_id : type->GetSubdirectories()) { |
| 585 | for (const auto& user_id : save_id->GetSubdirectories()) { | 590 | for (const auto& user_id : save_id->GetSubdirectories()) { |
| @@ -837,9 +842,11 @@ void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { | |||
| 837 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { | 842 | void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { |
| 838 | LOG_DEBUG(Service_FS, "called"); | 843 | LOG_DEBUG(Service_FS, "called"); |
| 839 | 844 | ||
| 840 | auto filesystem = | 845 | FileSys::VirtualDir sdmc_dir{}; |
| 841 | std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(), | 846 | fsc.OpenSDMC(&sdmc_dir); |
| 842 | SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); | 847 | |
| 848 | auto filesystem = std::make_shared<IFileSystem>( | ||
| 849 | system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); | ||
| 843 | 850 | ||
| 844 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 851 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 845 | rb.Push(ResultSuccess); | 852 | rb.Push(ResultSuccess); |
| @@ -856,7 +863,8 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 856 | LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), | 863 | LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), |
| 857 | uid[1], uid[0]); | 864 | uid[1], uid[0]); |
| 858 | 865 | ||
| 859 | fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct); | 866 | FileSys::VirtualDir save_data_dir{}; |
| 867 | fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct); | ||
| 860 | 868 | ||
| 861 | IPC::ResponseBuilder rb{ctx, 2}; | 869 | IPC::ResponseBuilder rb{ctx, 2}; |
| 862 | rb.Push(ResultSuccess); | 870 | rb.Push(ResultSuccess); |
| @@ -874,8 +882,9 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 874 | 882 | ||
| 875 | LOG_INFO(Service_FS, "called."); | 883 | LOG_INFO(Service_FS, "called."); |
| 876 | 884 | ||
| 877 | auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute); | 885 | FileSys::VirtualDir dir{}; |
| 878 | if (dir.Failed()) { | 886 | auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute); |
| 887 | if (result != ResultSuccess) { | ||
| 879 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | 888 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; |
| 880 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 889 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); |
| 881 | return; | 890 | return; |
| @@ -899,8 +908,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 899 | ASSERT(false); | 908 | ASSERT(false); |
| 900 | } | 909 | } |
| 901 | 910 | ||
| 902 | auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()), | 911 | auto filesystem = |
| 903 | SizeGetter::FromStorageId(fsc, id)); | 912 | std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id)); |
| 904 | 913 | ||
| 905 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 914 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 906 | rb.Push(ResultSuccess); | 915 | rb.Push(ResultSuccess); |
| @@ -970,7 +979,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { | |||
| 970 | 979 | ||
| 971 | if (!romfs) { | 980 | if (!romfs) { |
| 972 | auto current_romfs = fsc.OpenRomFSCurrentProcess(); | 981 | auto current_romfs = fsc.OpenRomFSCurrentProcess(); |
| 973 | if (current_romfs.Failed()) { | 982 | if (!current_romfs) { |
| 974 | // TODO (bunnei): Find the right error code to use here | 983 | // TODO (bunnei): Find the right error code to use here |
| 975 | LOG_CRITICAL(Service_FS, "no file system interface available!"); | 984 | LOG_CRITICAL(Service_FS, "no file system interface available!"); |
| 976 | IPC::ResponseBuilder rb{ctx, 2}; | 985 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -978,7 +987,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { | |||
| 978 | return; | 987 | return; |
| 979 | } | 988 | } |
| 980 | 989 | ||
| 981 | romfs = current_romfs.Unwrap(); | 990 | romfs = current_romfs; |
| 982 | } | 991 | } |
| 983 | 992 | ||
| 984 | auto storage = std::make_shared<IStorage>(system, romfs); | 993 | auto storage = std::make_shared<IStorage>(system, romfs); |
| @@ -999,7 +1008,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { | |||
| 999 | 1008 | ||
| 1000 | auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); | 1009 | auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); |
| 1001 | 1010 | ||
| 1002 | if (data.Failed()) { | 1011 | if (!data) { |
| 1003 | const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); | 1012 | const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); |
| 1004 | 1013 | ||
| 1005 | if (archive != nullptr) { | 1014 | if (archive != nullptr) { |
| @@ -1021,7 +1030,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { | |||
| 1021 | const FileSys::PatchManager pm{title_id, fsc, content_provider}; | 1030 | const FileSys::PatchManager pm{title_id, fsc, content_provider}; |
| 1022 | 1031 | ||
| 1023 | auto storage = std::make_shared<IStorage>( | 1032 | auto storage = std::make_shared<IStorage>( |
| 1024 | system, pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); | 1033 | system, pm.PatchRomFS(std::move(data), 0, FileSys::ContentRecordType::Data)); |
| 1025 | 1034 | ||
| 1026 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1035 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1027 | rb.Push(ResultSuccess); | 1036 | rb.Push(ResultSuccess); |
| @@ -1051,7 +1060,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { | |||
| 1051 | fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, | 1060 | fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, |
| 1052 | FileSys::ContentRecordType::Program); | 1061 | FileSys::ContentRecordType::Program); |
| 1053 | 1062 | ||
| 1054 | if (patched_romfs.Failed()) { | 1063 | if (!patched_romfs) { |
| 1055 | // TODO: Find the right error code to use here | 1064 | // TODO: Find the right error code to use here |
| 1056 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); | 1065 | LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); |
| 1057 | 1066 | ||
| @@ -1060,7 +1069,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { | |||
| 1060 | return; | 1069 | return; |
| 1061 | } | 1070 | } |
| 1062 | 1071 | ||
| 1063 | auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs.Unwrap())); | 1072 | auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs)); |
| 1064 | 1073 | ||
| 1065 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1074 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1066 | rb.Push(ResultSuccess); | 1075 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index ed6fcb5f6..6f1151b03 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp | |||
| @@ -65,18 +65,19 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) { | |||
| 65 | return; | 65 | return; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | const auto res = manager.GetLaunchProperty(*title_id); | 68 | ApplicationLaunchProperty launch_property{}; |
| 69 | const auto res = manager.GetLaunchProperty(&launch_property, *title_id); | ||
| 69 | 70 | ||
| 70 | if (res.Failed()) { | 71 | if (res != ResultSuccess) { |
| 71 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); | 72 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); |
| 72 | IPC::ResponseBuilder rb{ctx, 2}; | 73 | IPC::ResponseBuilder rb{ctx, 2}; |
| 73 | rb.Push(res.Code()); | 74 | rb.Push(res); |
| 74 | return; | 75 | return; |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | IPC::ResponseBuilder rb{ctx, 6}; | 78 | IPC::ResponseBuilder rb{ctx, 6}; |
| 78 | rb.Push(ResultSuccess); | 79 | rb.Push(ResultSuccess); |
| 79 | rb.PushRaw(*res); | 80 | rb.PushRaw(launch_property); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { | 83 | void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { |
| @@ -85,18 +86,19 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx | |||
| 85 | 86 | ||
| 86 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); | 87 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); |
| 87 | 88 | ||
| 88 | const auto res = manager.GetLaunchProperty(title_id); | 89 | ApplicationLaunchProperty launch_property{}; |
| 90 | const auto res = manager.GetLaunchProperty(&launch_property, title_id); | ||
| 89 | 91 | ||
| 90 | if (res.Failed()) { | 92 | if (res != ResultSuccess) { |
| 91 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); | 93 | LOG_ERROR(Service_ARP, "Failed to get launch property!"); |
| 92 | IPC::ResponseBuilder rb{ctx, 2}; | 94 | IPC::ResponseBuilder rb{ctx, 2}; |
| 93 | rb.Push(res.Code()); | 95 | rb.Push(res); |
| 94 | return; | 96 | return; |
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | IPC::ResponseBuilder rb{ctx, 6}; | 99 | IPC::ResponseBuilder rb{ctx, 6}; |
| 98 | rb.Push(ResultSuccess); | 100 | rb.Push(ResultSuccess); |
| 99 | rb.PushRaw(*res); | 101 | rb.PushRaw(launch_property); |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { | 104 | void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { |
| @@ -113,16 +115,17 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { | |||
| 113 | return; | 115 | return; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | const auto res = manager.GetControlProperty(*title_id); | 118 | std::vector<u8> nacp_data; |
| 119 | const auto res = manager.GetControlProperty(&nacp_data, *title_id); | ||
| 117 | 120 | ||
| 118 | if (res.Failed()) { | 121 | if (res != ResultSuccess) { |
| 119 | LOG_ERROR(Service_ARP, "Failed to get control property!"); | 122 | LOG_ERROR(Service_ARP, "Failed to get control property!"); |
| 120 | IPC::ResponseBuilder rb{ctx, 2}; | 123 | IPC::ResponseBuilder rb{ctx, 2}; |
| 121 | rb.Push(res.Code()); | 124 | rb.Push(res); |
| 122 | return; | 125 | return; |
| 123 | } | 126 | } |
| 124 | 127 | ||
| 125 | ctx.WriteBuffer(*res); | 128 | ctx.WriteBuffer(nacp_data); |
| 126 | 129 | ||
| 127 | IPC::ResponseBuilder rb{ctx, 2}; | 130 | IPC::ResponseBuilder rb{ctx, 2}; |
| 128 | rb.Push(ResultSuccess); | 131 | rb.Push(ResultSuccess); |
| @@ -134,16 +137,17 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct | |||
| 134 | 137 | ||
| 135 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); | 138 | LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); |
| 136 | 139 | ||
| 137 | const auto res = manager.GetControlProperty(title_id); | 140 | std::vector<u8> nacp_data; |
| 141 | const auto res = manager.GetControlProperty(&nacp_data, title_id); | ||
| 138 | 142 | ||
| 139 | if (res.Failed()) { | 143 | if (res != ResultSuccess) { |
| 140 | LOG_ERROR(Service_ARP, "Failed to get control property!"); | 144 | LOG_ERROR(Service_ARP, "Failed to get control property!"); |
| 141 | IPC::ResponseBuilder rb{ctx, 2}; | 145 | IPC::ResponseBuilder rb{ctx, 2}; |
| 142 | rb.Push(res.Code()); | 146 | rb.Push(res); |
| 143 | return; | 147 | return; |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | ctx.WriteBuffer(*res); | 150 | ctx.WriteBuffer(nacp_data); |
| 147 | 151 | ||
| 148 | IPC::ResponseBuilder rb{ctx, 2}; | 152 | IPC::ResponseBuilder rb{ctx, 2}; |
| 149 | rb.Push(ResultSuccess); | 153 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/glue/glue_manager.cpp b/src/core/hle/service/glue/glue_manager.cpp index 4bf67921b..22f001704 100644 --- a/src/core/hle/service/glue/glue_manager.cpp +++ b/src/core/hle/service/glue/glue_manager.cpp | |||
| @@ -15,7 +15,8 @@ ARPManager::ARPManager() = default; | |||
| 15 | 15 | ||
| 16 | ARPManager::~ARPManager() = default; | 16 | ARPManager::~ARPManager() = default; |
| 17 | 17 | ||
| 18 | ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const { | 18 | Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, |
| 19 | u64 title_id) const { | ||
| 19 | if (title_id == 0) { | 20 | if (title_id == 0) { |
| 20 | return Glue::ResultInvalidProcessId; | 21 | return Glue::ResultInvalidProcessId; |
| 21 | } | 22 | } |
| @@ -25,10 +26,11 @@ ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) | |||
| 25 | return Glue::ResultProcessIdNotRegistered; | 26 | return Glue::ResultProcessIdNotRegistered; |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | return iter->second.launch; | 29 | *out_launch_property = iter->second.launch; |
| 30 | return ResultSuccess; | ||
| 29 | } | 31 | } |
| 30 | 32 | ||
| 31 | ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { | 33 | Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const { |
| 32 | if (title_id == 0) { | 34 | if (title_id == 0) { |
| 33 | return Glue::ResultInvalidProcessId; | 35 | return Glue::ResultInvalidProcessId; |
| 34 | } | 36 | } |
| @@ -38,7 +40,8 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { | |||
| 38 | return Glue::ResultProcessIdNotRegistered; | 40 | return Glue::ResultProcessIdNotRegistered; |
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | return iter->second.control; | 43 | *out_control_property = iter->second.control; |
| 44 | return ResultSuccess; | ||
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, | 47 | Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, |
diff --git a/src/core/hle/service/glue/glue_manager.h b/src/core/hle/service/glue/glue_manager.h index 1cf53d9d9..216aa34c1 100644 --- a/src/core/hle/service/glue/glue_manager.h +++ b/src/core/hle/service/glue/glue_manager.h | |||
| @@ -32,12 +32,12 @@ public: | |||
| 32 | // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was | 32 | // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was |
| 33 | // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or | 33 | // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or |
| 34 | // ResultInvalidProcessId if the title ID is 0. | 34 | // ResultInvalidProcessId if the title ID is 0. |
| 35 | ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const; | 35 | Result GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, u64 title_id) const; |
| 36 | 36 | ||
| 37 | // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to | 37 | // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to |
| 38 | // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered | 38 | // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered |
| 39 | // if it was never registered or ResultInvalidProcessId if the title ID is 0. | 39 | // if it was never registered or ResultInvalidProcessId if the title ID is 0. |
| 40 | ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const; | 40 | Result GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const; |
| 41 | 41 | ||
| 42 | // Adds a new entry to the internal database with the provided parameters, returning | 42 | // Adds a new entry to the internal database with the provided parameters, returning |
| 43 | // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate | 43 | // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index e57a3a80e..dd00921fd 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -16,22 +16,6 @@ class EmulatedConsole; | |||
| 16 | namespace Service::HID { | 16 | namespace Service::HID { |
| 17 | class Controller_Touchscreen final : public ControllerBase { | 17 | class Controller_Touchscreen final : public ControllerBase { |
| 18 | public: | 18 | public: |
| 19 | // This is nn::hid::TouchScreenModeForNx | ||
| 20 | enum class TouchScreenModeForNx : u8 { | ||
| 21 | UseSystemSetting, | ||
| 22 | Finger, | ||
| 23 | Heat2, | ||
| 24 | }; | ||
| 25 | |||
| 26 | // This is nn::hid::TouchScreenConfigurationForNx | ||
| 27 | struct TouchScreenConfigurationForNx { | ||
| 28 | TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting}; | ||
| 29 | INSERT_PADDING_BYTES_NOINIT(0x7); | ||
| 30 | INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved | ||
| 31 | }; | ||
| 32 | static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, | ||
| 33 | "TouchScreenConfigurationForNx is an invalid size"); | ||
| 34 | |||
| 35 | explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); | 19 | explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_); |
| 36 | ~Controller_Touchscreen() override; | 20 | ~Controller_Touchscreen() override; |
| 37 | 21 | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 2bf1d8a27..fd466db7b 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -2368,7 +2368,7 @@ void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) { | |||
| 2368 | 2368 | ||
| 2369 | void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) { | 2369 | void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) { |
| 2370 | IPC::RequestParser rp{ctx}; | 2370 | IPC::RequestParser rp{ctx}; |
| 2371 | const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()}; | 2371 | const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()}; |
| 2372 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 2372 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 2373 | 2373 | ||
| 2374 | LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}", | 2374 | LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}", |
| @@ -2543,7 +2543,8 @@ public: | |||
| 2543 | 2543 | ||
| 2544 | class HidSys final : public ServiceFramework<HidSys> { | 2544 | class HidSys final : public ServiceFramework<HidSys> { |
| 2545 | public: | 2545 | public: |
| 2546 | explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} { | 2546 | explicit HidSys(Core::System& system_) |
| 2547 | : ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} { | ||
| 2547 | // clang-format off | 2548 | // clang-format off |
| 2548 | static const FunctionInfo functions[] = { | 2549 | static const FunctionInfo functions[] = { |
| 2549 | {31, nullptr, "SendKeyboardLockKeyEvent"}, | 2550 | {31, nullptr, "SendKeyboardLockKeyEvent"}, |
| @@ -2568,7 +2569,7 @@ public: | |||
| 2568 | {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"}, | 2569 | {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"}, |
| 2569 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, | 2570 | {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, |
| 2570 | {305, nullptr, "DisableAssigningSingleOnSlSrPress"}, | 2571 | {305, nullptr, "DisableAssigningSingleOnSlSrPress"}, |
| 2571 | {306, nullptr, "GetLastActiveNpad"}, | 2572 | {306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"}, |
| 2572 | {307, nullptr, "GetNpadSystemExtStyle"}, | 2573 | {307, nullptr, "GetNpadSystemExtStyle"}, |
| 2573 | {308, nullptr, "ApplyNpadSystemCommonPolicyFull"}, | 2574 | {308, nullptr, "ApplyNpadSystemCommonPolicyFull"}, |
| 2574 | {309, nullptr, "GetNpadFullKeyGripColor"}, | 2575 | {309, nullptr, "GetNpadFullKeyGripColor"}, |
| @@ -2624,7 +2625,7 @@ public: | |||
| 2624 | {700, nullptr, "ActivateUniquePad"}, | 2625 | {700, nullptr, "ActivateUniquePad"}, |
| 2625 | {702, nullptr, "AcquireUniquePadConnectionEventHandle"}, | 2626 | {702, nullptr, "AcquireUniquePadConnectionEventHandle"}, |
| 2626 | {703, nullptr, "GetUniquePadIds"}, | 2627 | {703, nullptr, "GetUniquePadIds"}, |
| 2627 | {751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"}, | 2628 | {751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"}, |
| 2628 | {800, nullptr, "ListSixAxisSensorHandles"}, | 2629 | {800, nullptr, "ListSixAxisSensorHandles"}, |
| 2629 | {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"}, | 2630 | {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"}, |
| 2630 | {802, nullptr, "ResetSixAxisSensorCalibrationValues"}, | 2631 | {802, nullptr, "ResetSixAxisSensorCalibrationValues"}, |
| @@ -2650,7 +2651,7 @@ public: | |||
| 2650 | {830, nullptr, "SetNotificationLedPattern"}, | 2651 | {830, nullptr, "SetNotificationLedPattern"}, |
| 2651 | {831, nullptr, "SetNotificationLedPatternWithTimeout"}, | 2652 | {831, nullptr, "SetNotificationLedPatternWithTimeout"}, |
| 2652 | {832, nullptr, "PrepareHidsForNotificationWake"}, | 2653 | {832, nullptr, "PrepareHidsForNotificationWake"}, |
| 2653 | {850, nullptr, "IsUsbFullKeyControllerEnabled"}, | 2654 | {850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"}, |
| 2654 | {851, nullptr, "EnableUsbFullKeyController"}, | 2655 | {851, nullptr, "EnableUsbFullKeyController"}, |
| 2655 | {852, nullptr, "IsUsbConnected"}, | 2656 | {852, nullptr, "IsUsbConnected"}, |
| 2656 | {870, nullptr, "IsHandheldButtonPressedOnConsoleMode"}, | 2657 | {870, nullptr, "IsHandheldButtonPressedOnConsoleMode"}, |
| @@ -2682,7 +2683,7 @@ public: | |||
| 2682 | {1150, nullptr, "SetTouchScreenMagnification"}, | 2683 | {1150, nullptr, "SetTouchScreenMagnification"}, |
| 2683 | {1151, nullptr, "GetTouchScreenFirmwareVersion"}, | 2684 | {1151, nullptr, "GetTouchScreenFirmwareVersion"}, |
| 2684 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, | 2685 | {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, |
| 2685 | {1153, nullptr, "GetTouchScreenDefaultConfiguration"}, | 2686 | {1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, |
| 2686 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, | 2687 | {1154, nullptr, "IsFirmwareAvailableForNotification"}, |
| 2687 | {1155, nullptr, "SetForceHandheldStyleVibration"}, | 2688 | {1155, nullptr, "SetForceHandheldStyleVibration"}, |
| 2688 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, | 2689 | {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, |
| @@ -2749,6 +2750,8 @@ public: | |||
| 2749 | // clang-format on | 2750 | // clang-format on |
| 2750 | 2751 | ||
| 2751 | RegisterHandlers(functions); | 2752 | RegisterHandlers(functions); |
| 2753 | |||
| 2754 | joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent"); | ||
| 2752 | } | 2755 | } |
| 2753 | 2756 | ||
| 2754 | private: | 2757 | private: |
| @@ -2760,17 +2763,66 @@ private: | |||
| 2760 | rb.Push(ResultSuccess); | 2763 | rb.Push(ResultSuccess); |
| 2761 | } | 2764 | } |
| 2762 | 2765 | ||
| 2766 | void GetLastActiveNpad(HLERequestContext& ctx) { | ||
| 2767 | LOG_DEBUG(Service_HID, "(STUBBED) called"); | ||
| 2768 | |||
| 2769 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2770 | rb.Push(ResultSuccess); | ||
| 2771 | rb.PushEnum(Core::HID::NpadIdType::Handheld); | ||
| 2772 | } | ||
| 2773 | |||
| 2763 | void GetUniquePadsFromNpad(HLERequestContext& ctx) { | 2774 | void GetUniquePadsFromNpad(HLERequestContext& ctx) { |
| 2764 | IPC::RequestParser rp{ctx}; | 2775 | IPC::RequestParser rp{ctx}; |
| 2765 | const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()}; | 2776 | const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()}; |
| 2766 | 2777 | ||
| 2767 | const s64 total_entries = 0; | ||
| 2768 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type); | 2778 | LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type); |
| 2769 | 2779 | ||
| 2780 | const std::vector<Core::HID::UniquePadId> unique_pads{}; | ||
| 2781 | |||
| 2782 | ctx.WriteBuffer(unique_pads); | ||
| 2783 | |||
| 2770 | IPC::ResponseBuilder rb{ctx, 3}; | 2784 | IPC::ResponseBuilder rb{ctx, 3}; |
| 2771 | rb.Push(ResultSuccess); | 2785 | rb.Push(ResultSuccess); |
| 2772 | rb.Push(total_entries); | 2786 | rb.Push(static_cast<u32>(unique_pads.size())); |
| 2773 | } | 2787 | } |
| 2788 | |||
| 2789 | void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) { | ||
| 2790 | LOG_INFO(Service_AM, "called"); | ||
| 2791 | |||
| 2792 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 2793 | rb.Push(ResultSuccess); | ||
| 2794 | rb.PushCopyObjects(joy_detach_event->GetReadableEvent()); | ||
| 2795 | } | ||
| 2796 | |||
| 2797 | void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) { | ||
| 2798 | const bool is_enabled = false; | ||
| 2799 | |||
| 2800 | LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled); | ||
| 2801 | |||
| 2802 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 2803 | rb.Push(ResultSuccess); | ||
| 2804 | rb.Push(is_enabled); | ||
| 2805 | } | ||
| 2806 | |||
| 2807 | void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) { | ||
| 2808 | LOG_WARNING(Service_HID, "(STUBBED) called"); | ||
| 2809 | |||
| 2810 | Core::HID::TouchScreenConfigurationForNx touchscreen_config{ | ||
| 2811 | .mode = Core::HID::TouchScreenModeForNx::Finger, | ||
| 2812 | }; | ||
| 2813 | |||
| 2814 | if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 && | ||
| 2815 | touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) { | ||
| 2816 | touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting; | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 2820 | rb.Push(ResultSuccess); | ||
| 2821 | rb.PushRaw(touchscreen_config); | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | Kernel::KEvent* joy_detach_event; | ||
| 2825 | KernelHelpers::ServiceContext service_context; | ||
| 2774 | }; | 2826 | }; |
| 2775 | 2827 | ||
| 2776 | void LoopProcess(Core::System& system) { | 2828 | void LoopProcess(Core::System& system) { |
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 055c0a2db..c73035c77 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -357,7 +357,8 @@ public: | |||
| 357 | return ResultSuccess; | 357 | return ResultSuccess; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) { | 360 | Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr, |
| 361 | u64 size) { | ||
| 361 | auto& page_table{process->GetPageTable()}; | 362 | auto& page_table{process->GetPageTable()}; |
| 362 | VAddr addr{}; | 363 | VAddr addr{}; |
| 363 | 364 | ||
| @@ -372,20 +373,21 @@ public: | |||
| 372 | R_TRY(result); | 373 | R_TRY(result); |
| 373 | 374 | ||
| 374 | if (ValidateRegionForMap(page_table, addr, size)) { | 375 | if (ValidateRegionForMap(page_table, addr, size)) { |
| 375 | return addr; | 376 | *out_map_location = addr; |
| 377 | return ResultSuccess; | ||
| 376 | } | 378 | } |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 379 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; | 381 | return ERROR_INSUFFICIENT_ADDRESS_SPACE; |
| 380 | } | 382 | } |
| 381 | 383 | ||
| 382 | ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size, | 384 | Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr, |
| 383 | VAddr bss_addr, std::size_t bss_size, std::size_t size) { | 385 | std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) { |
| 384 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { | 386 | for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { |
| 385 | auto& page_table{process->GetPageTable()}; | 387 | auto& page_table{process->GetPageTable()}; |
| 386 | VAddr addr{}; | 388 | VAddr addr{}; |
| 387 | 389 | ||
| 388 | CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size)); | 390 | R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size)); |
| 389 | 391 | ||
| 390 | if (bss_size) { | 392 | if (bss_size) { |
| 391 | auto block_guard = detail::ScopeExit([&] { | 393 | auto block_guard = detail::ScopeExit([&] { |
| @@ -411,7 +413,8 @@ public: | |||
| 411 | } | 413 | } |
| 412 | 414 | ||
| 413 | if (ValidateRegionForMap(page_table, addr, size)) { | 415 | if (ValidateRegionForMap(page_table, addr, size)) { |
| 414 | return addr; | 416 | *out_map_location = addr; |
| 417 | return ResultSuccess; | ||
| 415 | } | 418 | } |
| 416 | } | 419 | } |
| 417 | 420 | ||
| @@ -437,9 +440,9 @@ public: | |||
| 437 | CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, | 440 | CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, |
| 438 | nro_header.segment_headers[DATA_INDEX].memory_size); | 441 | nro_header.segment_headers[DATA_INDEX].memory_size); |
| 439 | 442 | ||
| 440 | CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( | 443 | R_TRY(process->GetPageTable().SetProcessMemoryPermission( |
| 441 | text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); | 444 | text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); |
| 442 | CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( | 445 | R_TRY(process->GetPageTable().SetProcessMemoryPermission( |
| 443 | ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); | 446 | ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); |
| 444 | 447 | ||
| 445 | return process->GetPageTable().SetProcessMemoryPermission( | 448 | return process->GetPageTable().SetProcessMemoryPermission( |
| @@ -542,31 +545,32 @@ public: | |||
| 542 | } | 545 | } |
| 543 | 546 | ||
| 544 | // Map memory for the NRO | 547 | // Map memory for the NRO |
| 545 | const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size, | 548 | VAddr map_location{}; |
| 546 | bss_address, bss_size, nro_size + bss_size)}; | 549 | const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address, |
| 547 | if (map_result.Failed()) { | 550 | nro_size, bss_address, bss_size, nro_size + bss_size)}; |
| 551 | if (map_result != ResultSuccess) { | ||
| 548 | IPC::ResponseBuilder rb{ctx, 2}; | 552 | IPC::ResponseBuilder rb{ctx, 2}; |
| 549 | rb.Push(map_result.Code()); | 553 | rb.Push(map_result); |
| 550 | } | 554 | } |
| 551 | 555 | ||
| 552 | // Load the NRO into the mapped memory | 556 | // Load the NRO into the mapped memory |
| 553 | if (const auto result{ | 557 | if (const auto result{ |
| 554 | LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)}; | 558 | LoadNro(system.ApplicationProcess(), header, nro_address, map_location)}; |
| 555 | result.IsError()) { | 559 | result.IsError()) { |
| 556 | IPC::ResponseBuilder rb{ctx, 2}; | 560 | IPC::ResponseBuilder rb{ctx, 2}; |
| 557 | rb.Push(map_result.Code()); | 561 | rb.Push(result); |
| 558 | } | 562 | } |
| 559 | 563 | ||
| 560 | // Track the loaded NRO | 564 | // Track the loaded NRO |
| 561 | nro.insert_or_assign(*map_result, | 565 | nro.insert_or_assign(map_location, |
| 562 | NROInfo{hash, *map_result, nro_size, bss_address, bss_size, | 566 | NROInfo{hash, map_location, nro_size, bss_address, bss_size, |
| 563 | header.segment_headers[TEXT_INDEX].memory_size, | 567 | header.segment_headers[TEXT_INDEX].memory_size, |
| 564 | header.segment_headers[RO_INDEX].memory_size, | 568 | header.segment_headers[RO_INDEX].memory_size, |
| 565 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); | 569 | header.segment_headers[DATA_INDEX].memory_size, nro_address}); |
| 566 | 570 | ||
| 567 | IPC::ResponseBuilder rb{ctx, 4}; | 571 | IPC::ResponseBuilder rb{ctx, 4}; |
| 568 | rb.Push(ResultSuccess); | 572 | rb.Push(ResultSuccess); |
| 569 | rb.Push(*map_result); | 573 | rb.Push(map_location); |
| 570 | } | 574 | } |
| 571 | 575 | ||
| 572 | Result UnmapNro(const NROInfo& info) { | 576 | Result UnmapNro(const NROInfo& info) { |
| @@ -574,19 +578,19 @@ public: | |||
| 574 | auto& page_table{system.ApplicationProcess()->GetPageTable()}; | 578 | auto& page_table{system.ApplicationProcess()->GetPageTable()}; |
| 575 | 579 | ||
| 576 | if (info.bss_size != 0) { | 580 | if (info.bss_size != 0) { |
| 577 | CASCADE_CODE(page_table.UnmapCodeMemory( | 581 | R_TRY(page_table.UnmapCodeMemory( |
| 578 | info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, | 582 | info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, |
| 579 | info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 583 | info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 580 | } | 584 | } |
| 581 | 585 | ||
| 582 | CASCADE_CODE(page_table.UnmapCodeMemory( | 586 | R_TRY(page_table.UnmapCodeMemory( |
| 583 | info.nro_address + info.text_size + info.ro_size, | 587 | info.nro_address + info.text_size + info.ro_size, |
| 584 | info.src_addr + info.text_size + info.ro_size, info.data_size, | 588 | info.src_addr + info.text_size + info.ro_size, info.data_size, |
| 585 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 589 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 586 | CASCADE_CODE(page_table.UnmapCodeMemory( | 590 | R_TRY(page_table.UnmapCodeMemory( |
| 587 | info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, | 591 | info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, |
| 588 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 592 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 589 | CASCADE_CODE(page_table.UnmapCodeMemory( | 593 | R_TRY(page_table.UnmapCodeMemory( |
| 590 | info.nro_address, info.src_addr, info.text_size, | 594 | info.nro_address, info.src_addr, info.text_size, |
| 591 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); | 595 | Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); |
| 592 | return ResultSuccess; | 596 | return ResultSuccess; |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 5c7adf97d..65c11a2f3 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -101,20 +101,14 @@ private: | |||
| 101 | 101 | ||
| 102 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 102 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 103 | 103 | ||
| 104 | const auto result{manager.GetDefault(source_flag)}; | 104 | const auto default_miis{manager.GetDefault(source_flag)}; |
| 105 | if (result.Failed()) { | 105 | if (default_miis.size() > 0) { |
| 106 | IPC::ResponseBuilder rb{ctx, 2}; | 106 | ctx.WriteBuffer(SerializeArray(default_miis)); |
| 107 | rb.Push(result.Code()); | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (result->size() > 0) { | ||
| 112 | ctx.WriteBuffer(SerializeArray(*result)); | ||
| 113 | } | 107 | } |
| 114 | 108 | ||
| 115 | IPC::ResponseBuilder rb{ctx, 3}; | 109 | IPC::ResponseBuilder rb{ctx, 3}; |
| 116 | rb.Push(ResultSuccess); | 110 | rb.Push(ResultSuccess); |
| 117 | rb.Push<u32>(static_cast<u32>(result->size())); | 111 | rb.Push<u32>(static_cast<u32>(default_miis.size())); |
| 118 | } | 112 | } |
| 119 | 113 | ||
| 120 | void Get1(HLERequestContext& ctx) { | 114 | void Get1(HLERequestContext& ctx) { |
| @@ -123,15 +117,10 @@ private: | |||
| 123 | 117 | ||
| 124 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 118 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 125 | 119 | ||
| 126 | const auto result{manager.GetDefault(source_flag)}; | 120 | const auto default_miis{manager.GetDefault(source_flag)}; |
| 127 | if (result.Failed()) { | ||
| 128 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 129 | rb.Push(result.Code()); | ||
| 130 | return; | ||
| 131 | } | ||
| 132 | 121 | ||
| 133 | std::vector<CharInfo> values; | 122 | std::vector<CharInfo> values; |
| 134 | for (const auto& element : *result) { | 123 | for (const auto& element : default_miis) { |
| 135 | values.emplace_back(element.info); | 124 | values.emplace_back(element.info); |
| 136 | } | 125 | } |
| 137 | 126 | ||
| @@ -139,7 +128,7 @@ private: | |||
| 139 | 128 | ||
| 140 | IPC::ResponseBuilder rb{ctx, 3}; | 129 | IPC::ResponseBuilder rb{ctx, 3}; |
| 141 | rb.Push(ResultSuccess); | 130 | rb.Push(ResultSuccess); |
| 142 | rb.Push<u32>(static_cast<u32>(result->size())); | 131 | rb.Push<u32>(static_cast<u32>(default_miis.size())); |
| 143 | } | 132 | } |
| 144 | 133 | ||
| 145 | void UpdateLatest(HLERequestContext& ctx) { | 134 | void UpdateLatest(HLERequestContext& ctx) { |
| @@ -149,16 +138,17 @@ private: | |||
| 149 | 138 | ||
| 150 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); | 139 | LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); |
| 151 | 140 | ||
| 152 | const auto result{manager.UpdateLatest(info, source_flag)}; | 141 | CharInfo new_char_info{}; |
| 153 | if (result.Failed()) { | 142 | const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)}; |
| 143 | if (result != ResultSuccess) { | ||
| 154 | IPC::ResponseBuilder rb{ctx, 2}; | 144 | IPC::ResponseBuilder rb{ctx, 2}; |
| 155 | rb.Push(result.Code()); | 145 | rb.Push(result); |
| 156 | return; | 146 | return; |
| 157 | } | 147 | } |
| 158 | 148 | ||
| 159 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; | 149 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; |
| 160 | rb.Push(ResultSuccess); | 150 | rb.Push(ResultSuccess); |
| 161 | rb.PushRaw<CharInfo>(*result); | 151 | rb.PushRaw<CharInfo>(new_char_info); |
| 162 | } | 152 | } |
| 163 | 153 | ||
| 164 | void BuildRandom(HLERequestContext& ctx) { | 154 | void BuildRandom(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp index c920650f5..46125d473 100644 --- a/src/core/hle/service/mii/mii_manager.cpp +++ b/src/core/hle/service/mii/mii_manager.cpp | |||
| @@ -409,8 +409,7 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const { | |||
| 409 | return static_cast<u32>(count); | 409 | return static_cast<u32>(count); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | ResultVal<CharInfo> MiiManager::UpdateLatest([[maybe_unused]] const CharInfo& info, | 412 | Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) { |
| 413 | SourceFlag source_flag) { | ||
| 414 | if ((source_flag & SourceFlag::Database) == SourceFlag::None) { | 413 | if ((source_flag & SourceFlag::Database) == SourceFlag::None) { |
| 415 | return ERROR_CANNOT_FIND_ENTRY; | 414 | return ERROR_CANNOT_FIND_ENTRY; |
| 416 | } | 415 | } |
| @@ -672,7 +671,7 @@ bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const { | |||
| 672 | return is_valid; | 671 | return is_valid; |
| 673 | } | 672 | } |
| 674 | 673 | ||
| 675 | ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) { | 674 | std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { |
| 676 | std::vector<MiiInfoElement> result; | 675 | std::vector<MiiInfoElement> result; |
| 677 | 676 | ||
| 678 | if ((source_flag & SourceFlag::Default) == SourceFlag::None) { | 677 | if ((source_flag & SourceFlag::Default) == SourceFlag::None) { |
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h index 5525fcd1c..45c2be3c8 100644 --- a/src/core/hle/service/mii/mii_manager.h +++ b/src/core/hle/service/mii/mii_manager.h | |||
| @@ -19,12 +19,12 @@ public: | |||
| 19 | bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); | 19 | bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); |
| 20 | bool IsFullDatabase() const; | 20 | bool IsFullDatabase() const; |
| 21 | u32 GetCount(SourceFlag source_flag) const; | 21 | u32 GetCount(SourceFlag source_flag) const; |
| 22 | ResultVal<CharInfo> UpdateLatest(const CharInfo& info, SourceFlag source_flag); | 22 | Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag); |
| 23 | CharInfo BuildRandom(Age age, Gender gender, Race race); | 23 | CharInfo BuildRandom(Age age, Gender gender, Race race); |
| 24 | CharInfo BuildDefault(std::size_t index); | 24 | CharInfo BuildDefault(std::size_t index); |
| 25 | CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; | 25 | CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; |
| 26 | bool ValidateV3Info(const Ver3StoreData& mii_v3) const; | 26 | bool ValidateV3Info(const Ver3StoreData& mii_v3) const; |
| 27 | ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); | 27 | std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag); |
| 28 | Result GetIndex(const CharInfo& info, u32& index); | 28 | Result GetIndex(const CharInfo& info, u32& index); |
| 29 | 29 | ||
| 30 | // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData | 30 | // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 91c5a2182..6e0baf0be 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -392,19 +392,20 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte | |||
| 392 | IPC::RequestParser rp{ctx}; | 392 | IPC::RequestParser rp{ctx}; |
| 393 | const auto supported_languages = rp.Pop<u32>(); | 393 | const auto supported_languages = rp.Pop<u32>(); |
| 394 | 394 | ||
| 395 | const auto res = GetApplicationDesiredLanguage(supported_languages); | 395 | u8 desired_language{}; |
| 396 | if (res.Succeeded()) { | 396 | const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); |
| 397 | if (res == ResultSuccess) { | ||
| 397 | IPC::ResponseBuilder rb{ctx, 3}; | 398 | IPC::ResponseBuilder rb{ctx, 3}; |
| 398 | rb.Push(ResultSuccess); | 399 | rb.Push(ResultSuccess); |
| 399 | rb.Push<u32>(*res); | 400 | rb.Push<u32>(desired_language); |
| 400 | } else { | 401 | } else { |
| 401 | IPC::ResponseBuilder rb{ctx, 2}; | 402 | IPC::ResponseBuilder rb{ctx, 2}; |
| 402 | rb.Push(res.Code()); | 403 | rb.Push(res); |
| 403 | } | 404 | } |
| 404 | } | 405 | } |
| 405 | 406 | ||
| 406 | ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | 407 | Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language, |
| 407 | const u32 supported_languages) { | 408 | const u32 supported_languages) { |
| 408 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); | 409 | LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); |
| 409 | 410 | ||
| 410 | // Get language code from settings | 411 | // Get language code from settings |
| @@ -430,7 +431,8 @@ ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( | |||
| 430 | for (const auto lang : *priority_list) { | 431 | for (const auto lang : *priority_list) { |
| 431 | const auto supported_flag = GetSupportedLanguageFlag(lang); | 432 | const auto supported_flag = GetSupportedLanguageFlag(lang); |
| 432 | if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { | 433 | if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { |
| 433 | return static_cast<u8>(lang); | 434 | *out_desired_language = static_cast<u8>(lang); |
| 435 | return ResultSuccess; | ||
| 434 | } | 436 | } |
| 435 | } | 437 | } |
| 436 | 438 | ||
| @@ -444,19 +446,20 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( | |||
| 444 | IPC::RequestParser rp{ctx}; | 446 | IPC::RequestParser rp{ctx}; |
| 445 | const auto application_language = rp.Pop<u8>(); | 447 | const auto application_language = rp.Pop<u8>(); |
| 446 | 448 | ||
| 447 | const auto res = ConvertApplicationLanguageToLanguageCode(application_language); | 449 | u64 language_code{}; |
| 448 | if (res.Succeeded()) { | 450 | const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language); |
| 451 | if (res == ResultSuccess) { | ||
| 449 | IPC::ResponseBuilder rb{ctx, 4}; | 452 | IPC::ResponseBuilder rb{ctx, 4}; |
| 450 | rb.Push(ResultSuccess); | 453 | rb.Push(ResultSuccess); |
| 451 | rb.Push(*res); | 454 | rb.Push(language_code); |
| 452 | } else { | 455 | } else { |
| 453 | IPC::ResponseBuilder rb{ctx, 2}; | 456 | IPC::ResponseBuilder rb{ctx, 2}; |
| 454 | rb.Push(res.Code()); | 457 | rb.Push(res); |
| 455 | } | 458 | } |
| 456 | } | 459 | } |
| 457 | 460 | ||
| 458 | ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( | 461 | Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( |
| 459 | u8 application_language) { | 462 | u64* out_language_code, u8 application_language) { |
| 460 | const auto language_code = | 463 | const auto language_code = |
| 461 | ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); | 464 | ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); |
| 462 | if (language_code == std::nullopt) { | 465 | if (language_code == std::nullopt) { |
| @@ -464,7 +467,8 @@ ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguag | |||
| 464 | return Service::NS::ResultApplicationLanguageNotFound; | 467 | return Service::NS::ResultApplicationLanguageNotFound; |
| 465 | } | 468 | } |
| 466 | 469 | ||
| 467 | return static_cast<u64>(*language_code); | 470 | *out_language_code = static_cast<u64>(*language_code); |
| 471 | return ResultSuccess; | ||
| 468 | } | 472 | } |
| 469 | 473 | ||
| 470 | IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) | 474 | IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) |
| @@ -618,12 +622,13 @@ void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequ | |||
| 618 | static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); | 622 | static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); |
| 619 | 623 | ||
| 620 | IPC::RequestParser rp{ctx}; | 624 | IPC::RequestParser rp{ctx}; |
| 625 | std::vector<u8> nacp_data{}; | ||
| 621 | const auto parameters{rp.PopRaw<RequestParameters>()}; | 626 | const auto parameters{rp.PopRaw<RequestParameters>()}; |
| 622 | const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)}; | 627 | const auto result = |
| 623 | const auto result = nacp_data ? ResultSuccess : ResultUnknown; | 628 | system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); |
| 624 | 629 | ||
| 625 | if (nacp_data) { | 630 | if (result == ResultSuccess) { |
| 626 | ctx.WriteBuffer(nacp_data->data(), nacp_data->size()); | 631 | ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); |
| 627 | } | 632 | } |
| 628 | 633 | ||
| 629 | IPC::ResponseBuilder rb{ctx, 2}; | 634 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index 203388e1f..175dad780 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h | |||
| @@ -28,8 +28,9 @@ public: | |||
| 28 | explicit IApplicationManagerInterface(Core::System& system_); | 28 | explicit IApplicationManagerInterface(Core::System& system_); |
| 29 | ~IApplicationManagerInterface() override; | 29 | ~IApplicationManagerInterface() override; |
| 30 | 30 | ||
| 31 | ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); | 31 | Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); |
| 32 | ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language); | 32 | Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code, |
| 33 | u8 application_language); | ||
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | void GetApplicationControlData(HLERequestContext& ctx); | 36 | void GetApplicationControlData(HLERequestContext& ctx); |
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index b16f9933f..dc6917d5d 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp | |||
| @@ -449,6 +449,7 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, | |||
| 449 | case NativeWindowScalingMode::ScaleToWindow: | 449 | case NativeWindowScalingMode::ScaleToWindow: |
| 450 | case NativeWindowScalingMode::ScaleCrop: | 450 | case NativeWindowScalingMode::ScaleCrop: |
| 451 | case NativeWindowScalingMode::NoScaleCrop: | 451 | case NativeWindowScalingMode::NoScaleCrop: |
| 452 | case NativeWindowScalingMode::PreserveAspectRatio: | ||
| 452 | break; | 453 | break; |
| 453 | default: | 454 | default: |
| 454 | LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode); | 455 | LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode); |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 5f55cd31e..21f31f7a0 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -183,7 +183,7 @@ std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) { | |||
| 183 | return layer->GetBinderId(); | 183 | return layer->GetBinderId(); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) { | 186 | Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { |
| 187 | const auto lock_guard = Lock(); | 187 | const auto lock_guard = Lock(); |
| 188 | auto* const display = FindDisplay(display_id); | 188 | auto* const display = FindDisplay(display_id); |
| 189 | 189 | ||
| @@ -191,7 +191,7 @@ ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) { | |||
| 191 | return VI::ResultNotFound; | 191 | return VI::ResultNotFound; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | return display->GetVSyncEvent(); | 194 | return display->GetVSyncEvent(out_vsync_event); |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { | 197 | VI::Display* Nvnflinger::FindDisplay(u64 display_id) { |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index ef236303a..f478c2bc6 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -82,7 +82,7 @@ public: | |||
| 82 | /// | 82 | /// |
| 83 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. | 83 | /// If an invalid display ID is provided, then VI::ResultNotFound is returned. |
| 84 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. | 84 | /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. |
| 85 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id); | 85 | [[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); |
| 86 | 86 | ||
| 87 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when | 87 | /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when |
| 88 | /// finished. | 88 | /// finished. |
diff --git a/src/core/hle/service/nvnflinger/window.h b/src/core/hle/service/nvnflinger/window.h index 61cca5b01..36d6cde3d 100644 --- a/src/core/hle/service/nvnflinger/window.h +++ b/src/core/hle/service/nvnflinger/window.h | |||
| @@ -41,6 +41,7 @@ enum class NativeWindowScalingMode : s32 { | |||
| 41 | ScaleToWindow = 1, | 41 | ScaleToWindow = 1, |
| 42 | ScaleCrop = 2, | 42 | ScaleCrop = 2, |
| 43 | NoScaleCrop = 3, | 43 | NoScaleCrop = 3, |
| 44 | PreserveAspectRatio = 4, | ||
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | /// Transform parameter for QueueBuffer | 47 | /// Transform parameter for QueueBuffer |
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp index 14ba67b4c..889f27c31 100644 --- a/src/core/hle/service/olsc/olsc.cpp +++ b/src/core/hle/service/olsc/olsc.cpp | |||
| @@ -8,15 +8,16 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::OLSC { | 9 | namespace Service::OLSC { |
| 10 | 10 | ||
| 11 | class OLSC final : public ServiceFramework<OLSC> { | 11 | class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> { |
| 12 | public: | 12 | public: |
| 13 | explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} { | 13 | explicit IOlscServiceForApplication(Core::System& system_) |
| 14 | : ServiceFramework{system_, "olsc:u"} { | ||
| 14 | // clang-format off | 15 | // clang-format off |
| 15 | static const FunctionInfo functions[] = { | 16 | static const FunctionInfo functions[] = { |
| 16 | {0, &OLSC::Initialize, "Initialize"}, | 17 | {0, &IOlscServiceForApplication::Initialize, "Initialize"}, |
| 17 | {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, | 18 | {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, |
| 18 | {13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"}, | 19 | {13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"}, |
| 19 | {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, | 20 | {14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, |
| 20 | {15, nullptr, "SetCustomData"}, | 21 | {15, nullptr, "SetCustomData"}, |
| 21 | {16, nullptr, "DeleteSaveDataBackupSetting"}, | 22 | {16, nullptr, "DeleteSaveDataBackupSetting"}, |
| 22 | {18, nullptr, "GetSaveDataBackupInfoCache"}, | 23 | {18, nullptr, "GetSaveDataBackupInfoCache"}, |
| @@ -72,10 +73,155 @@ private: | |||
| 72 | bool initialized{}; | 73 | bool initialized{}; |
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| 76 | class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> { | ||
| 77 | public: | ||
| 78 | explicit INativeHandleHolder(Core::System& system_) | ||
| 79 | : ServiceFramework{system_, "INativeHandleHolder"} { | ||
| 80 | // clang-format off | ||
| 81 | static const FunctionInfo functions[] = { | ||
| 82 | {0, nullptr, "GetNativeHandle"}, | ||
| 83 | }; | ||
| 84 | // clang-format on | ||
| 85 | |||
| 86 | RegisterHandlers(functions); | ||
| 87 | } | ||
| 88 | }; | ||
| 89 | |||
| 90 | class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> { | ||
| 91 | public: | ||
| 92 | explicit ITransferTaskListController(Core::System& system_) | ||
| 93 | : ServiceFramework{system_, "ITransferTaskListController"} { | ||
| 94 | // clang-format off | ||
| 95 | static const FunctionInfo functions[] = { | ||
| 96 | {0, nullptr, "Unknown0"}, | ||
| 97 | {1, nullptr, "Unknown1"}, | ||
| 98 | {2, nullptr, "Unknown2"}, | ||
| 99 | {3, nullptr, "Unknown3"}, | ||
| 100 | {4, nullptr, "Unknown4"}, | ||
| 101 | {5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"}, | ||
| 102 | {6, nullptr, "Unknown6"}, | ||
| 103 | {7, nullptr, "Unknown7"}, | ||
| 104 | {8, nullptr, "GetRemoteStorageController"}, | ||
| 105 | {9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"}, | ||
| 106 | {10, nullptr, "Unknown10"}, | ||
| 107 | {11, nullptr, "Unknown11"}, | ||
| 108 | {12, nullptr, "Unknown12"}, | ||
| 109 | {13, nullptr, "Unknown13"}, | ||
| 110 | {14, nullptr, "Unknown14"}, | ||
| 111 | {15, nullptr, "Unknown15"}, | ||
| 112 | {16, nullptr, "Unknown16"}, | ||
| 113 | {17, nullptr, "Unknown17"}, | ||
| 114 | {18, nullptr, "Unknown18"}, | ||
| 115 | {19, nullptr, "Unknown19"}, | ||
| 116 | {20, nullptr, "Unknown20"}, | ||
| 117 | {21, nullptr, "Unknown21"}, | ||
| 118 | {22, nullptr, "Unknown22"}, | ||
| 119 | {23, nullptr, "Unknown23"}, | ||
| 120 | {24, nullptr, "Unknown24"}, | ||
| 121 | {25, nullptr, "Unknown25"}, | ||
| 122 | }; | ||
| 123 | // clang-format on | ||
| 124 | |||
| 125 | RegisterHandlers(functions); | ||
| 126 | } | ||
| 127 | |||
| 128 | private: | ||
| 129 | void GetNativeHandleHolder(HLERequestContext& ctx) { | ||
| 130 | LOG_INFO(Service_OLSC, "called"); | ||
| 131 | |||
| 132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 133 | rb.Push(ResultSuccess); | ||
| 134 | rb.PushIpcInterface<INativeHandleHolder>(system); | ||
| 135 | } | ||
| 136 | }; | ||
| 137 | |||
| 138 | class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> { | ||
| 139 | public: | ||
| 140 | explicit IOlscServiceForSystemService(Core::System& system_) | ||
| 141 | : ServiceFramework{system_, "olsc:s"} { | ||
| 142 | // clang-format off | ||
| 143 | static const FunctionInfo functions[] = { | ||
| 144 | {0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"}, | ||
| 145 | {1, nullptr, "OpenRemoteStorageController"}, | ||
| 146 | {2, nullptr, "OpenDaemonController"}, | ||
| 147 | {10, nullptr, "Unknown10"}, | ||
| 148 | {11, nullptr, "Unknown11"}, | ||
| 149 | {12, nullptr, "Unknown12"}, | ||
| 150 | {13, nullptr, "Unknown13"}, | ||
| 151 | {100, nullptr, "ListLastTransferTaskErrorInfo"}, | ||
| 152 | {101, nullptr, "GetLastErrorInfoCount"}, | ||
| 153 | {102, nullptr, "RemoveLastErrorInfoOld"}, | ||
| 154 | {103, nullptr, "GetLastErrorInfo"}, | ||
| 155 | {104, nullptr, "GetLastErrorEventHolder"}, | ||
| 156 | {105, nullptr, "GetLastTransferTaskErrorInfo"}, | ||
| 157 | {200, nullptr, "GetDataTransferPolicyInfo"}, | ||
| 158 | {201, nullptr, "RemoveDataTransferPolicyInfo"}, | ||
| 159 | {202, nullptr, "UpdateDataTransferPolicyOld"}, | ||
| 160 | {203, nullptr, "UpdateDataTransferPolicy"}, | ||
| 161 | {204, nullptr, "CleanupDataTransferPolicyInfo"}, | ||
| 162 | {205, nullptr, "RequestDataTransferPolicy"}, | ||
| 163 | {300, nullptr, "GetAutoTransferSeriesInfo"}, | ||
| 164 | {301, nullptr, "UpdateAutoTransferSeriesInfo"}, | ||
| 165 | {400, nullptr, "CleanupSaveDataArchiveInfoType1"}, | ||
| 166 | {900, nullptr, "CleanupTransferTask"}, | ||
| 167 | {902, nullptr, "CleanupSeriesInfoType0"}, | ||
| 168 | {903, nullptr, "CleanupSaveDataArchiveInfoType0"}, | ||
| 169 | {904, nullptr, "CleanupApplicationAutoTransferSetting"}, | ||
| 170 | {905, nullptr, "CleanupErrorHistory"}, | ||
| 171 | {906, nullptr, "SetLastError"}, | ||
| 172 | {907, nullptr, "AddSaveDataArchiveInfoType0"}, | ||
| 173 | {908, nullptr, "RemoveSeriesInfoType0"}, | ||
| 174 | {909, nullptr, "GetSeriesInfoType0"}, | ||
| 175 | {910, nullptr, "RemoveLastErrorInfo"}, | ||
| 176 | {911, nullptr, "CleanupSeriesInfoType1"}, | ||
| 177 | {912, nullptr, "RemoveSeriesInfoType1"}, | ||
| 178 | {913, nullptr, "GetSeriesInfoType1"}, | ||
| 179 | {1000, nullptr, "UpdateIssueOld"}, | ||
| 180 | {1010, nullptr, "Unknown1010"}, | ||
| 181 | {1011, nullptr, "ListIssueInfoOld"}, | ||
| 182 | {1012, nullptr, "GetIssueOld"}, | ||
| 183 | {1013, nullptr, "GetIssue2Old"}, | ||
| 184 | {1014, nullptr, "GetIssue3Old"}, | ||
| 185 | {1020, nullptr, "RepairIssueOld"}, | ||
| 186 | {1021, nullptr, "RepairIssueWithUserIdOld"}, | ||
| 187 | {1022, nullptr, "RepairIssue2Old"}, | ||
| 188 | {1023, nullptr, "RepairIssue3Old"}, | ||
| 189 | {1024, nullptr, "Unknown1024"}, | ||
| 190 | {1100, nullptr, "UpdateIssue"}, | ||
| 191 | {1110, nullptr, "Unknown1110"}, | ||
| 192 | {1111, nullptr, "ListIssueInfo"}, | ||
| 193 | {1112, nullptr, "GetIssue"}, | ||
| 194 | {1113, nullptr, "GetIssue2"}, | ||
| 195 | {1114, nullptr, "GetIssue3"}, | ||
| 196 | {1120, nullptr, "RepairIssue"}, | ||
| 197 | {1121, nullptr, "RepairIssueWithUserId"}, | ||
| 198 | {1122, nullptr, "RepairIssue2"}, | ||
| 199 | {1123, nullptr, "RepairIssue3"}, | ||
| 200 | {1124, nullptr, "Unknown1124"}, | ||
| 201 | }; | ||
| 202 | // clang-format on | ||
| 203 | |||
| 204 | RegisterHandlers(functions); | ||
| 205 | } | ||
| 206 | |||
| 207 | private: | ||
| 208 | void OpenTransferTaskListController(HLERequestContext& ctx) { | ||
| 209 | LOG_INFO(Service_OLSC, "called"); | ||
| 210 | |||
| 211 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 212 | rb.Push(ResultSuccess); | ||
| 213 | rb.PushIpcInterface<ITransferTaskListController>(system); | ||
| 214 | } | ||
| 215 | }; | ||
| 216 | |||
| 75 | void LoopProcess(Core::System& system) { | 217 | void LoopProcess(Core::System& system) { |
| 76 | auto server_manager = std::make_unique<ServerManager>(system); | 218 | auto server_manager = std::make_unique<ServerManager>(system); |
| 77 | 219 | ||
| 78 | server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system)); | 220 | server_manager->RegisterNamedService("olsc:u", |
| 221 | std::make_shared<IOlscServiceForApplication>(system)); | ||
| 222 | server_manager->RegisterNamedService("olsc:s", | ||
| 223 | std::make_shared<IOlscServiceForSystemService>(system)); | ||
| 224 | |||
| 79 | ServerManager::RunServer(std::move(server_manager)); | 225 | ServerManager::RunServer(std::move(server_manager)); |
| 80 | } | 226 | } |
| 81 | 227 | ||
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp index f966c5c8b..5db1703d1 100644 --- a/src/core/hle/service/pctl/pctl_module.cpp +++ b/src/core/hle/service/pctl/pctl_module.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "core/file_sys/control_metadata.h" | 6 | #include "core/file_sys/control_metadata.h" |
| 7 | #include "core/file_sys/patch_manager.h" | 7 | #include "core/file_sys/patch_manager.h" |
| 8 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 9 | #include "core/hle/service/kernel_helpers.h" | ||
| 9 | #include "core/hle/service/pctl/pctl.h" | 10 | #include "core/hle/service/pctl/pctl.h" |
| 10 | #include "core/hle/service/pctl/pctl_module.h" | 11 | #include "core/hle/service/pctl/pctl_module.h" |
| 11 | #include "core/hle/service/server_manager.h" | 12 | #include "core/hle/service/server_manager.h" |
| @@ -24,7 +25,8 @@ constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; | |||
| 24 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { | 25 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { |
| 25 | public: | 26 | public: |
| 26 | explicit IParentalControlService(Core::System& system_, Capability capability_) | 27 | explicit IParentalControlService(Core::System& system_, Capability capability_) |
| 27 | : ServiceFramework{system_, "IParentalControlService"}, capability{capability_} { | 28 | : ServiceFramework{system_, "IParentalControlService"}, capability{capability_}, |
| 29 | service_context{system_, "IParentalControlService"} { | ||
| 28 | // clang-format off | 30 | // clang-format off |
| 29 | static const FunctionInfo functions[] = { | 31 | static const FunctionInfo functions[] = { |
| 30 | {1, &IParentalControlService::Initialize, "Initialize"}, | 32 | {1, &IParentalControlService::Initialize, "Initialize"}, |
| @@ -33,7 +35,7 @@ public: | |||
| 33 | {1003, nullptr, "ConfirmResumeApplicationPermission"}, | 35 | {1003, nullptr, "ConfirmResumeApplicationPermission"}, |
| 34 | {1004, nullptr, "ConfirmSnsPostPermission"}, | 36 | {1004, nullptr, "ConfirmSnsPostPermission"}, |
| 35 | {1005, nullptr, "ConfirmSystemSettingsPermission"}, | 37 | {1005, nullptr, "ConfirmSystemSettingsPermission"}, |
| 36 | {1006, nullptr, "IsRestrictionTemporaryUnlocked"}, | 38 | {1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"}, |
| 37 | {1007, nullptr, "RevertRestrictionTemporaryUnlocked"}, | 39 | {1007, nullptr, "RevertRestrictionTemporaryUnlocked"}, |
| 38 | {1008, nullptr, "EnterRestrictedSystemSettings"}, | 40 | {1008, nullptr, "EnterRestrictedSystemSettings"}, |
| 39 | {1009, nullptr, "LeaveRestrictedSystemSettings"}, | 41 | {1009, nullptr, "LeaveRestrictedSystemSettings"}, |
| @@ -47,14 +49,14 @@ public: | |||
| 47 | {1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"}, | 49 | {1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"}, |
| 48 | {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, | 50 | {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, |
| 49 | {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, | 51 | {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, |
| 50 | {1032, nullptr, "GetSafetyLevel"}, | 52 | {1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"}, |
| 51 | {1033, nullptr, "SetSafetyLevel"}, | 53 | {1033, nullptr, "SetSafetyLevel"}, |
| 52 | {1034, nullptr, "GetSafetyLevelSettings"}, | 54 | {1034, nullptr, "GetSafetyLevelSettings"}, |
| 53 | {1035, nullptr, "GetCurrentSettings"}, | 55 | {1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"}, |
| 54 | {1036, nullptr, "SetCustomSafetyLevelSettings"}, | 56 | {1036, nullptr, "SetCustomSafetyLevelSettings"}, |
| 55 | {1037, nullptr, "GetDefaultRatingOrganization"}, | 57 | {1037, nullptr, "GetDefaultRatingOrganization"}, |
| 56 | {1038, nullptr, "SetDefaultRatingOrganization"}, | 58 | {1038, nullptr, "SetDefaultRatingOrganization"}, |
| 57 | {1039, nullptr, "GetFreeCommunicationApplicationListCount"}, | 59 | {1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"}, |
| 58 | {1042, nullptr, "AddToFreeCommunicationApplicationList"}, | 60 | {1042, nullptr, "AddToFreeCommunicationApplicationList"}, |
| 59 | {1043, nullptr, "DeleteSettings"}, | 61 | {1043, nullptr, "DeleteSettings"}, |
| 60 | {1044, nullptr, "GetFreeCommunicationApplicationList"}, | 62 | {1044, nullptr, "GetFreeCommunicationApplicationList"}, |
| @@ -76,7 +78,7 @@ public: | |||
| 76 | {1206, nullptr, "GetPinCodeLength"}, | 78 | {1206, nullptr, "GetPinCodeLength"}, |
| 77 | {1207, nullptr, "GetPinCodeChangedEvent"}, | 79 | {1207, nullptr, "GetPinCodeChangedEvent"}, |
| 78 | {1208, nullptr, "GetPinCode"}, | 80 | {1208, nullptr, "GetPinCode"}, |
| 79 | {1403, nullptr, "IsPairingActive"}, | 81 | {1403, &IParentalControlService::IsPairingActive, "IsPairingActive"}, |
| 80 | {1406, nullptr, "GetSettingsLastUpdated"}, | 82 | {1406, nullptr, "GetSettingsLastUpdated"}, |
| 81 | {1411, nullptr, "GetPairingAccountInfo"}, | 83 | {1411, nullptr, "GetPairingAccountInfo"}, |
| 82 | {1421, nullptr, "GetAccountNickname"}, | 84 | {1421, nullptr, "GetAccountNickname"}, |
| @@ -84,18 +86,18 @@ public: | |||
| 84 | {1425, nullptr, "RequestPostEvents"}, | 86 | {1425, nullptr, "RequestPostEvents"}, |
| 85 | {1426, nullptr, "GetPostEventInterval"}, | 87 | {1426, nullptr, "GetPostEventInterval"}, |
| 86 | {1427, nullptr, "SetPostEventInterval"}, | 88 | {1427, nullptr, "SetPostEventInterval"}, |
| 87 | {1432, nullptr, "GetSynchronizationEvent"}, | 89 | {1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"}, |
| 88 | {1451, nullptr, "StartPlayTimer"}, | 90 | {1451, nullptr, "StartPlayTimer"}, |
| 89 | {1452, nullptr, "StopPlayTimer"}, | 91 | {1452, nullptr, "StopPlayTimer"}, |
| 90 | {1453, nullptr, "IsPlayTimerEnabled"}, | 92 | {1453, nullptr, "IsPlayTimerEnabled"}, |
| 91 | {1454, nullptr, "GetPlayTimerRemainingTime"}, | 93 | {1454, nullptr, "GetPlayTimerRemainingTime"}, |
| 92 | {1455, nullptr, "IsRestrictedByPlayTimer"}, | 94 | {1455, nullptr, "IsRestrictedByPlayTimer"}, |
| 93 | {1456, nullptr, "GetPlayTimerSettings"}, | 95 | {1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"}, |
| 94 | {1457, nullptr, "GetPlayTimerEventToRequestSuspension"}, | 96 | {1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"}, |
| 95 | {1458, nullptr, "IsPlayTimerAlarmDisabled"}, | 97 | {1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"}, |
| 96 | {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, | 98 | {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, |
| 97 | {1472, nullptr, "CancelNetworkRequest"}, | 99 | {1472, nullptr, "CancelNetworkRequest"}, |
| 98 | {1473, nullptr, "GetUnlinkedEvent"}, | 100 | {1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"}, |
| 99 | {1474, nullptr, "ClearUnlinkedEvent"}, | 101 | {1474, nullptr, "ClearUnlinkedEvent"}, |
| 100 | {1601, nullptr, "DisableAllFeatures"}, | 102 | {1601, nullptr, "DisableAllFeatures"}, |
| 101 | {1602, nullptr, "PostEnableAllFeatures"}, | 103 | {1602, nullptr, "PostEnableAllFeatures"}, |
| @@ -131,6 +133,12 @@ public: | |||
| 131 | }; | 133 | }; |
| 132 | // clang-format on | 134 | // clang-format on |
| 133 | RegisterHandlers(functions); | 135 | RegisterHandlers(functions); |
| 136 | |||
| 137 | synchronization_event = | ||
| 138 | service_context.CreateEvent("IParentalControlService::SynchronizationEvent"); | ||
| 139 | unlinked_event = service_context.CreateEvent("IParentalControlService::UnlinkedEvent"); | ||
| 140 | request_suspension_event = | ||
| 141 | service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent"); | ||
| 134 | } | 142 | } |
| 135 | 143 | ||
| 136 | private: | 144 | private: |
| @@ -228,6 +236,17 @@ private: | |||
| 228 | states.free_communication = true; | 236 | states.free_communication = true; |
| 229 | } | 237 | } |
| 230 | 238 | ||
| 239 | void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) { | ||
| 240 | const bool is_temporary_unlocked = false; | ||
| 241 | |||
| 242 | LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}", | ||
| 243 | is_temporary_unlocked); | ||
| 244 | |||
| 245 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 246 | rb.Push(ResultSuccess); | ||
| 247 | rb.Push<u8>(is_temporary_unlocked); | ||
| 248 | } | ||
| 249 | |||
| 231 | void ConfirmStereoVisionPermission(HLERequestContext& ctx) { | 250 | void ConfirmStereoVisionPermission(HLERequestContext& ctx) { |
| 232 | LOG_DEBUG(Service_PCTL, "called"); | 251 | LOG_DEBUG(Service_PCTL, "called"); |
| 233 | states.stereo_vision = true; | 252 | states.stereo_vision = true; |
| @@ -268,6 +287,34 @@ private: | |||
| 268 | rb.Push(pin_code[0] != '\0'); | 287 | rb.Push(pin_code[0] != '\0'); |
| 269 | } | 288 | } |
| 270 | 289 | ||
| 290 | void GetSafetyLevel(HLERequestContext& ctx) { | ||
| 291 | const u32 safety_level = 0; | ||
| 292 | |||
| 293 | LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", safety_level); | ||
| 294 | |||
| 295 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 296 | rb.Push(ResultSuccess); | ||
| 297 | rb.Push(safety_level); | ||
| 298 | } | ||
| 299 | |||
| 300 | void GetCurrentSettings(HLERequestContext& ctx) { | ||
| 301 | LOG_INFO(Service_PCTL, "called"); | ||
| 302 | |||
| 303 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 304 | rb.Push(ResultSuccess); | ||
| 305 | rb.PushRaw(restriction_settings); | ||
| 306 | } | ||
| 307 | |||
| 308 | void GetFreeCommunicationApplicationListCount(HLERequestContext& ctx) { | ||
| 309 | const u32 count = 4; | ||
| 310 | |||
| 311 | LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", count); | ||
| 312 | |||
| 313 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 314 | rb.Push(ResultSuccess); | ||
| 315 | rb.Push(count); | ||
| 316 | } | ||
| 317 | |||
| 271 | void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) { | 318 | void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) { |
| 272 | LOG_DEBUG(Service_PCTL, "called"); | 319 | LOG_DEBUG(Service_PCTL, "called"); |
| 273 | 320 | ||
| @@ -300,6 +347,61 @@ private: | |||
| 300 | } | 347 | } |
| 301 | } | 348 | } |
| 302 | 349 | ||
| 350 | void IsPairingActive(HLERequestContext& ctx) { | ||
| 351 | const bool is_pairing_active = false; | ||
| 352 | |||
| 353 | LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active); | ||
| 354 | |||
| 355 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 356 | rb.Push(ResultSuccess); | ||
| 357 | rb.Push<u8>(is_pairing_active); | ||
| 358 | } | ||
| 359 | |||
| 360 | void GetSynchronizationEvent(HLERequestContext& ctx) { | ||
| 361 | LOG_INFO(Service_PCTL, "called"); | ||
| 362 | |||
| 363 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 364 | rb.Push(ResultSuccess); | ||
| 365 | rb.PushCopyObjects(synchronization_event->GetReadableEvent()); | ||
| 366 | } | ||
| 367 | |||
| 368 | void GetPlayTimerSettings(HLERequestContext& ctx) { | ||
| 369 | LOG_WARNING(Service_PCTL, "(STUBBED) called"); | ||
| 370 | |||
| 371 | const PlayTimerSettings timer_settings{}; | ||
| 372 | |||
| 373 | IPC::ResponseBuilder rb{ctx, 15}; | ||
| 374 | rb.Push(ResultSuccess); | ||
| 375 | rb.PushRaw(timer_settings); | ||
| 376 | } | ||
| 377 | |||
| 378 | void GetPlayTimerEventToRequestSuspension(HLERequestContext& ctx) { | ||
| 379 | LOG_INFO(Service_PCTL, "called"); | ||
| 380 | |||
| 381 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 382 | rb.Push(ResultSuccess); | ||
| 383 | rb.PushCopyObjects(request_suspension_event->GetReadableEvent()); | ||
| 384 | } | ||
| 385 | |||
| 386 | void IsPlayTimerAlarmDisabled(HLERequestContext& ctx) { | ||
| 387 | const bool is_play_timer_alarm_disabled = false; | ||
| 388 | |||
| 389 | LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}", | ||
| 390 | is_play_timer_alarm_disabled); | ||
| 391 | |||
| 392 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 393 | rb.Push(ResultSuccess); | ||
| 394 | rb.Push<u8>(is_play_timer_alarm_disabled); | ||
| 395 | } | ||
| 396 | |||
| 397 | void GetUnlinkedEvent(HLERequestContext& ctx) { | ||
| 398 | LOG_INFO(Service_PCTL, "called"); | ||
| 399 | |||
| 400 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 401 | rb.Push(ResultSuccess); | ||
| 402 | rb.PushCopyObjects(unlinked_event->GetReadableEvent()); | ||
| 403 | } | ||
| 404 | |||
| 303 | void SetStereoVisionRestriction(HLERequestContext& ctx) { | 405 | void SetStereoVisionRestriction(HLERequestContext& ctx) { |
| 304 | IPC::RequestParser rp{ctx}; | 406 | IPC::RequestParser rp{ctx}; |
| 305 | const auto can_use = rp.Pop<bool>(); | 407 | const auto can_use = rp.Pop<bool>(); |
| @@ -364,10 +466,30 @@ private: | |||
| 364 | bool disabled{}; | 466 | bool disabled{}; |
| 365 | }; | 467 | }; |
| 366 | 468 | ||
| 469 | // This is nn::pctl::RestrictionSettings | ||
| 470 | struct RestrictionSettings { | ||
| 471 | u8 rating_age; | ||
| 472 | bool sns_post_restriction; | ||
| 473 | bool free_communication_restriction; | ||
| 474 | }; | ||
| 475 | static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size."); | ||
| 476 | |||
| 477 | // This is nn::pctl::PlayTimerSettings | ||
| 478 | struct PlayTimerSettings { | ||
| 479 | std::array<u32, 13> settings; | ||
| 480 | }; | ||
| 481 | static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size."); | ||
| 482 | |||
| 367 | States states{}; | 483 | States states{}; |
| 368 | ParentalControlSettings settings{}; | 484 | ParentalControlSettings settings{}; |
| 485 | RestrictionSettings restriction_settings{}; | ||
| 369 | std::array<char, 8> pin_code{}; | 486 | std::array<char, 8> pin_code{}; |
| 370 | Capability capability{}; | 487 | Capability capability{}; |
| 488 | |||
| 489 | Kernel::KEvent* synchronization_event; | ||
| 490 | Kernel::KEvent* unlinked_event; | ||
| 491 | Kernel::KEvent* request_suspension_event; | ||
| 492 | KernelHelpers::ServiceContext service_context; | ||
| 371 | }; | 493 | }; |
| 372 | 494 | ||
| 373 | void Module::Interface::CreateService(HLERequestContext& ctx) { | 495 | void Module::Interface::CreateService(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index d1e99b184..e2e399534 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp | |||
| @@ -102,16 +102,17 @@ Result ServerManager::RegisterNamedService(const std::string& service_name, | |||
| 102 | m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); | 102 | m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); |
| 103 | 103 | ||
| 104 | // Get the registered port. | 104 | // Get the registered port. |
| 105 | auto port = m_system.ServiceManager().GetServicePort(service_name); | 105 | Kernel::KPort* port{}; |
| 106 | ASSERT(port.Succeeded()); | 106 | ASSERT( |
| 107 | R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name))); | ||
| 107 | 108 | ||
| 108 | // Open a new reference to the server port. | 109 | // Open a new reference to the server port. |
| 109 | (*port)->GetServerPort().Open(); | 110 | port->GetServerPort().Open(); |
| 110 | 111 | ||
| 111 | // Begin tracking the server port. | 112 | // Begin tracking the server port. |
| 112 | { | 113 | { |
| 113 | std::scoped_lock ll{m_list_mutex}; | 114 | std::scoped_lock ll{m_list_mutex}; |
| 114 | m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler)); | 115 | m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | // Signal the wakeup event. | 118 | // Signal the wakeup event. |
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 83f888c54..2082b8ef7 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -11,66 +11,6 @@ | |||
| 11 | 11 | ||
| 12 | namespace Service::Set { | 12 | namespace Service::Set { |
| 13 | namespace { | 13 | namespace { |
| 14 | constexpr std::array<LanguageCode, 18> available_language_codes = {{ | ||
| 15 | LanguageCode::JA, | ||
| 16 | LanguageCode::EN_US, | ||
| 17 | LanguageCode::FR, | ||
| 18 | LanguageCode::DE, | ||
| 19 | LanguageCode::IT, | ||
| 20 | LanguageCode::ES, | ||
| 21 | LanguageCode::ZH_CN, | ||
| 22 | LanguageCode::KO, | ||
| 23 | LanguageCode::NL, | ||
| 24 | LanguageCode::PT, | ||
| 25 | LanguageCode::RU, | ||
| 26 | LanguageCode::ZH_TW, | ||
| 27 | LanguageCode::EN_GB, | ||
| 28 | LanguageCode::FR_CA, | ||
| 29 | LanguageCode::ES_419, | ||
| 30 | LanguageCode::ZH_HANS, | ||
| 31 | LanguageCode::ZH_HANT, | ||
| 32 | LanguageCode::PT_BR, | ||
| 33 | }}; | ||
| 34 | |||
| 35 | enum class KeyboardLayout : u64 { | ||
| 36 | Japanese = 0, | ||
| 37 | EnglishUs = 1, | ||
| 38 | EnglishUsInternational = 2, | ||
| 39 | EnglishUk = 3, | ||
| 40 | French = 4, | ||
| 41 | FrenchCa = 5, | ||
| 42 | Spanish = 6, | ||
| 43 | SpanishLatin = 7, | ||
| 44 | German = 8, | ||
| 45 | Italian = 9, | ||
| 46 | Portuguese = 10, | ||
| 47 | Russian = 11, | ||
| 48 | Korean = 12, | ||
| 49 | ChineseSimplified = 13, | ||
| 50 | ChineseTraditional = 14, | ||
| 51 | }; | ||
| 52 | |||
| 53 | constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{ | ||
| 54 | {LanguageCode::JA, KeyboardLayout::Japanese}, | ||
| 55 | {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, | ||
| 56 | {LanguageCode::FR, KeyboardLayout::French}, | ||
| 57 | {LanguageCode::DE, KeyboardLayout::German}, | ||
| 58 | {LanguageCode::IT, KeyboardLayout::Italian}, | ||
| 59 | {LanguageCode::ES, KeyboardLayout::Spanish}, | ||
| 60 | {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, | ||
| 61 | {LanguageCode::KO, KeyboardLayout::Korean}, | ||
| 62 | {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, | ||
| 63 | {LanguageCode::PT, KeyboardLayout::Portuguese}, | ||
| 64 | {LanguageCode::RU, KeyboardLayout::Russian}, | ||
| 65 | {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, | ||
| 66 | {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, | ||
| 67 | {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, | ||
| 68 | {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, | ||
| 69 | {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, | ||
| 70 | {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, | ||
| 71 | {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, | ||
| 72 | }}; | ||
| 73 | |||
| 74 | constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; | 14 | constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; |
| 75 | constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; | 15 | constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; |
| 76 | 16 | ||
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h index 7fd3a7654..b61a3560d 100644 --- a/src/core/hle/service/set/set.h +++ b/src/core/hle/service/set/set.h | |||
| @@ -32,6 +32,67 @@ enum class LanguageCode : u64 { | |||
| 32 | ZH_HANT = 0x00746E61482D687A, | 32 | ZH_HANT = 0x00746E61482D687A, |
| 33 | PT_BR = 0x00000052422D7470, | 33 | PT_BR = 0x00000052422D7470, |
| 34 | }; | 34 | }; |
| 35 | |||
| 36 | enum class KeyboardLayout : u64 { | ||
| 37 | Japanese = 0, | ||
| 38 | EnglishUs = 1, | ||
| 39 | EnglishUsInternational = 2, | ||
| 40 | EnglishUk = 3, | ||
| 41 | French = 4, | ||
| 42 | FrenchCa = 5, | ||
| 43 | Spanish = 6, | ||
| 44 | SpanishLatin = 7, | ||
| 45 | German = 8, | ||
| 46 | Italian = 9, | ||
| 47 | Portuguese = 10, | ||
| 48 | Russian = 11, | ||
| 49 | Korean = 12, | ||
| 50 | ChineseSimplified = 13, | ||
| 51 | ChineseTraditional = 14, | ||
| 52 | }; | ||
| 53 | |||
| 54 | constexpr std::array<LanguageCode, 18> available_language_codes = {{ | ||
| 55 | LanguageCode::JA, | ||
| 56 | LanguageCode::EN_US, | ||
| 57 | LanguageCode::FR, | ||
| 58 | LanguageCode::DE, | ||
| 59 | LanguageCode::IT, | ||
| 60 | LanguageCode::ES, | ||
| 61 | LanguageCode::ZH_CN, | ||
| 62 | LanguageCode::KO, | ||
| 63 | LanguageCode::NL, | ||
| 64 | LanguageCode::PT, | ||
| 65 | LanguageCode::RU, | ||
| 66 | LanguageCode::ZH_TW, | ||
| 67 | LanguageCode::EN_GB, | ||
| 68 | LanguageCode::FR_CA, | ||
| 69 | LanguageCode::ES_419, | ||
| 70 | LanguageCode::ZH_HANS, | ||
| 71 | LanguageCode::ZH_HANT, | ||
| 72 | LanguageCode::PT_BR, | ||
| 73 | }}; | ||
| 74 | |||
| 75 | static constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{ | ||
| 76 | {LanguageCode::JA, KeyboardLayout::Japanese}, | ||
| 77 | {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, | ||
| 78 | {LanguageCode::FR, KeyboardLayout::French}, | ||
| 79 | {LanguageCode::DE, KeyboardLayout::German}, | ||
| 80 | {LanguageCode::IT, KeyboardLayout::Italian}, | ||
| 81 | {LanguageCode::ES, KeyboardLayout::Spanish}, | ||
| 82 | {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, | ||
| 83 | {LanguageCode::KO, KeyboardLayout::Korean}, | ||
| 84 | {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, | ||
| 85 | {LanguageCode::PT, KeyboardLayout::Portuguese}, | ||
| 86 | {LanguageCode::RU, KeyboardLayout::Russian}, | ||
| 87 | {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, | ||
| 88 | {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, | ||
| 89 | {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, | ||
| 90 | {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, | ||
| 91 | {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, | ||
| 92 | {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, | ||
| 93 | {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, | ||
| 94 | }}; | ||
| 95 | |||
| 35 | LanguageCode GetLanguageCodeFromIndex(std::size_t idx); | 96 | LanguageCode GetLanguageCodeFromIndex(std::size_t idx); |
| 36 | 97 | ||
| 37 | class SET final : public ServiceFramework<SET> { | 98 | class SET final : public ServiceFramework<SET> { |
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 2e38d1cfc..165b97dad 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp | |||
| @@ -4,10 +4,12 @@ | |||
| 4 | #include "common/assert.h" | 4 | #include "common/assert.h" |
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
| 7 | #include "common/string_util.h" | ||
| 7 | #include "core/file_sys/errors.h" | 8 | #include "core/file_sys/errors.h" |
| 8 | #include "core/file_sys/system_archive/system_version.h" | 9 | #include "core/file_sys/system_archive/system_version.h" |
| 9 | #include "core/hle/service/filesystem/filesystem.h" | 10 | #include "core/hle/service/filesystem/filesystem.h" |
| 10 | #include "core/hle/service/ipc_helpers.h" | 11 | #include "core/hle/service/ipc_helpers.h" |
| 12 | #include "core/hle/service/set/set.h" | ||
| 11 | #include "core/hle/service/set/set_sys.h" | 13 | #include "core/hle/service/set/set_sys.h" |
| 12 | 14 | ||
| 13 | namespace Service::Set { | 15 | namespace Service::Set { |
| @@ -73,6 +75,16 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type) | |||
| 73 | } | 75 | } |
| 74 | } // Anonymous namespace | 76 | } // Anonymous namespace |
| 75 | 77 | ||
| 78 | void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { | ||
| 79 | IPC::RequestParser rp{ctx}; | ||
| 80 | language_code_setting = rp.PopEnum<LanguageCode>(); | ||
| 81 | |||
| 82 | LOG_INFO(Service_SET, "called, language_code={}", language_code_setting); | ||
| 83 | |||
| 84 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(ResultSuccess); | ||
| 86 | } | ||
| 87 | |||
| 76 | void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { | 88 | void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { |
| 77 | LOG_DEBUG(Service_SET, "called"); | 89 | LOG_DEBUG(Service_SET, "called"); |
| 78 | GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1); | 90 | GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1); |
| @@ -83,21 +95,113 @@ void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { | |||
| 83 | GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2); | 95 | GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2); |
| 84 | } | 96 | } |
| 85 | 97 | ||
| 98 | void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { | ||
| 99 | LOG_INFO(Service_SET, "called"); | ||
| 100 | |||
| 101 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 102 | rb.Push(ResultSuccess); | ||
| 103 | rb.PushRaw(account_settings); | ||
| 104 | } | ||
| 105 | |||
| 106 | void SET_SYS::SetAccountSettings(HLERequestContext& ctx) { | ||
| 107 | IPC::RequestParser rp{ctx}; | ||
| 108 | account_settings = rp.PopRaw<AccountSettings>(); | ||
| 109 | |||
| 110 | LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags); | ||
| 111 | |||
| 112 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 113 | rb.Push(ResultSuccess); | ||
| 114 | } | ||
| 115 | |||
| 116 | void SET_SYS::GetEulaVersions(HLERequestContext& ctx) { | ||
| 117 | LOG_INFO(Service_SET, "called"); | ||
| 118 | |||
| 119 | ctx.WriteBuffer(eula_versions); | ||
| 120 | |||
| 121 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 122 | rb.Push(ResultSuccess); | ||
| 123 | rb.Push(static_cast<u32>(eula_versions.size())); | ||
| 124 | } | ||
| 125 | |||
| 126 | void SET_SYS::SetEulaVersions(HLERequestContext& ctx) { | ||
| 127 | const auto elements = ctx.GetReadBufferNumElements<EulaVersion>(); | ||
| 128 | const auto buffer_data = ctx.ReadBuffer(); | ||
| 129 | |||
| 130 | LOG_INFO(Service_SET, "called, elements={}", elements); | ||
| 131 | |||
| 132 | eula_versions.resize(elements); | ||
| 133 | for (std::size_t index = 0; index < elements; index++) { | ||
| 134 | const std::size_t start_index = index * sizeof(EulaVersion); | ||
| 135 | memcpy(eula_versions.data() + start_index, buffer_data.data() + start_index, | ||
| 136 | sizeof(EulaVersion)); | ||
| 137 | } | ||
| 138 | |||
| 139 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 140 | rb.Push(ResultSuccess); | ||
| 141 | } | ||
| 142 | |||
| 86 | void SET_SYS::GetColorSetId(HLERequestContext& ctx) { | 143 | void SET_SYS::GetColorSetId(HLERequestContext& ctx) { |
| 87 | LOG_DEBUG(Service_SET, "called"); | 144 | LOG_DEBUG(Service_SET, "called"); |
| 88 | 145 | ||
| 89 | IPC::ResponseBuilder rb{ctx, 3}; | 146 | IPC::ResponseBuilder rb{ctx, 3}; |
| 90 | |||
| 91 | rb.Push(ResultSuccess); | 147 | rb.Push(ResultSuccess); |
| 92 | rb.PushEnum(color_set); | 148 | rb.PushEnum(color_set); |
| 93 | } | 149 | } |
| 94 | 150 | ||
| 95 | void SET_SYS::SetColorSetId(HLERequestContext& ctx) { | 151 | void SET_SYS::SetColorSetId(HLERequestContext& ctx) { |
| 96 | LOG_DEBUG(Service_SET, "called"); | ||
| 97 | |||
| 98 | IPC::RequestParser rp{ctx}; | 152 | IPC::RequestParser rp{ctx}; |
| 99 | color_set = rp.PopEnum<ColorSet>(); | 153 | color_set = rp.PopEnum<ColorSet>(); |
| 100 | 154 | ||
| 155 | LOG_DEBUG(Service_SET, "called, color_set={}", color_set); | ||
| 156 | |||
| 157 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 158 | rb.Push(ResultSuccess); | ||
| 159 | } | ||
| 160 | |||
| 161 | void SET_SYS::GetNotificationSettings(HLERequestContext& ctx) { | ||
| 162 | LOG_INFO(Service_SET, "called"); | ||
| 163 | |||
| 164 | IPC::ResponseBuilder rb{ctx, 8}; | ||
| 165 | rb.Push(ResultSuccess); | ||
| 166 | rb.PushRaw(notification_settings); | ||
| 167 | } | ||
| 168 | |||
| 169 | void SET_SYS::SetNotificationSettings(HLERequestContext& ctx) { | ||
| 170 | IPC::RequestParser rp{ctx}; | ||
| 171 | notification_settings = rp.PopRaw<NotificationSettings>(); | ||
| 172 | |||
| 173 | LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}", | ||
| 174 | notification_settings.flags.raw, notification_settings.volume, | ||
| 175 | notification_settings.start_time.hour, notification_settings.start_time.minute, | ||
| 176 | notification_settings.stop_time.hour, notification_settings.stop_time.minute); | ||
| 177 | |||
| 178 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 179 | rb.Push(ResultSuccess); | ||
| 180 | } | ||
| 181 | |||
| 182 | void SET_SYS::GetAccountNotificationSettings(HLERequestContext& ctx) { | ||
| 183 | LOG_INFO(Service_SET, "called"); | ||
| 184 | |||
| 185 | ctx.WriteBuffer(account_notifications); | ||
| 186 | |||
| 187 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 188 | rb.Push(ResultSuccess); | ||
| 189 | rb.Push(static_cast<u32>(account_notifications.size())); | ||
| 190 | } | ||
| 191 | |||
| 192 | void SET_SYS::SetAccountNotificationSettings(HLERequestContext& ctx) { | ||
| 193 | const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>(); | ||
| 194 | const auto buffer_data = ctx.ReadBuffer(); | ||
| 195 | |||
| 196 | LOG_INFO(Service_SET, "called, elements={}", elements); | ||
| 197 | |||
| 198 | account_notifications.resize(elements); | ||
| 199 | for (std::size_t index = 0; index < elements; index++) { | ||
| 200 | const std::size_t start_index = index * sizeof(AccountNotificationSettings); | ||
| 201 | memcpy(account_notifications.data() + start_index, buffer_data.data() + start_index, | ||
| 202 | sizeof(AccountNotificationSettings)); | ||
| 203 | } | ||
| 204 | |||
| 101 | IPC::ResponseBuilder rb{ctx, 2}; | 205 | IPC::ResponseBuilder rb{ctx, 2}; |
| 102 | rb.Push(ResultSuccess); | 206 | rb.Push(ResultSuccess); |
| 103 | } | 207 | } |
| @@ -177,17 +281,218 @@ void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) { | |||
| 177 | rb.Push(response); | 281 | rb.Push(response); |
| 178 | } | 282 | } |
| 179 | 283 | ||
| 284 | void SET_SYS::GetTvSettings(HLERequestContext& ctx) { | ||
| 285 | LOG_INFO(Service_SET, "called"); | ||
| 286 | |||
| 287 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 288 | rb.Push(ResultSuccess); | ||
| 289 | rb.PushRaw(tv_settings); | ||
| 290 | } | ||
| 291 | |||
| 292 | void SET_SYS::SetTvSettings(HLERequestContext& ctx) { | ||
| 293 | IPC::RequestParser rp{ctx}; | ||
| 294 | tv_settings = rp.PopRaw<TvSettings>(); | ||
| 295 | |||
| 296 | LOG_INFO(Service_SET, | ||
| 297 | "called, flags={}, cmu_mode={}, constrast_ratio={}, hdmi_content_type={}, " | ||
| 298 | "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", | ||
| 299 | tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.constrast_ratio, | ||
| 300 | tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama, | ||
| 301 | tv_settings.tv_resolution, tv_settings.tv_underscan); | ||
| 302 | |||
| 303 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 304 | rb.Push(ResultSuccess); | ||
| 305 | } | ||
| 306 | |||
| 307 | void SET_SYS::GetQuestFlag(HLERequestContext& ctx) { | ||
| 308 | LOG_WARNING(Service_SET, "(STUBBED) called"); | ||
| 309 | |||
| 310 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 311 | rb.Push(ResultSuccess); | ||
| 312 | rb.PushEnum(QuestFlag::Retail); | ||
| 313 | } | ||
| 314 | |||
| 315 | void SET_SYS::SetRegionCode(HLERequestContext& ctx) { | ||
| 316 | IPC::RequestParser rp{ctx}; | ||
| 317 | region_code = rp.PopEnum<RegionCode>(); | ||
| 318 | |||
| 319 | LOG_INFO(Service_SET, "called, region_code={}", region_code); | ||
| 320 | |||
| 321 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 322 | rb.Push(ResultSuccess); | ||
| 323 | } | ||
| 324 | |||
| 325 | void SET_SYS::GetPrimaryAlbumStorage(HLERequestContext& ctx) { | ||
| 326 | LOG_WARNING(Service_SET, "(STUBBED) called"); | ||
| 327 | |||
| 328 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 329 | rb.Push(ResultSuccess); | ||
| 330 | rb.PushEnum(PrimaryAlbumStorage::SdCard); | ||
| 331 | } | ||
| 332 | |||
| 333 | void SET_SYS::GetSleepSettings(HLERequestContext& ctx) { | ||
| 334 | LOG_INFO(Service_SET, "called"); | ||
| 335 | |||
| 336 | IPC::ResponseBuilder rb{ctx, 5}; | ||
| 337 | rb.Push(ResultSuccess); | ||
| 338 | rb.PushRaw(sleep_settings); | ||
| 339 | } | ||
| 340 | |||
| 341 | void SET_SYS::SetSleepSettings(HLERequestContext& ctx) { | ||
| 342 | IPC::RequestParser rp{ctx}; | ||
| 343 | sleep_settings = rp.PopRaw<SleepSettings>(); | ||
| 344 | |||
| 345 | LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}", | ||
| 346 | sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan, | ||
| 347 | sleep_settings.console_sleep_plan); | ||
| 348 | |||
| 349 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 350 | rb.Push(ResultSuccess); | ||
| 351 | } | ||
| 352 | |||
| 353 | void SET_SYS::GetInitialLaunchSettings(HLERequestContext& ctx) { | ||
| 354 | LOG_INFO(Service_SET, "called"); | ||
| 355 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 356 | rb.Push(ResultSuccess); | ||
| 357 | rb.PushRaw(launch_settings); | ||
| 358 | } | ||
| 359 | |||
| 360 | void SET_SYS::SetInitialLaunchSettings(HLERequestContext& ctx) { | ||
| 361 | IPC::RequestParser rp{ctx}; | ||
| 362 | launch_settings = rp.PopRaw<InitialLaunchSettings>(); | ||
| 363 | |||
| 364 | LOG_INFO(Service_SET, "called, flags={}, timestamp={}", launch_settings.flags.raw, | ||
| 365 | launch_settings.timestamp.time_point); | ||
| 366 | |||
| 367 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 368 | rb.Push(ResultSuccess); | ||
| 369 | } | ||
| 370 | |||
| 180 | void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) { | 371 | void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) { |
| 181 | LOG_DEBUG(Service_SET, "called"); | 372 | LOG_DEBUG(Service_SET, "called"); |
| 373 | |||
| 374 | ctx.WriteBuffer(::Settings::values.device_name.GetValue()); | ||
| 375 | |||
| 182 | IPC::ResponseBuilder rb{ctx, 2}; | 376 | IPC::ResponseBuilder rb{ctx, 2}; |
| 183 | rb.Push(ResultSuccess); | 377 | rb.Push(ResultSuccess); |
| 184 | ctx.WriteBuffer(::Settings::values.device_name.GetValue()); | 378 | } |
| 379 | |||
| 380 | void SET_SYS::SetDeviceNickName(HLERequestContext& ctx) { | ||
| 381 | const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer()); | ||
| 382 | |||
| 383 | LOG_INFO(Service_SET, "called, device_name={}", device_name); | ||
| 384 | |||
| 385 | ::Settings::values.device_name = device_name; | ||
| 386 | |||
| 387 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 388 | rb.Push(ResultSuccess); | ||
| 389 | } | ||
| 390 | |||
| 391 | void SET_SYS::GetProductModel(HLERequestContext& ctx) { | ||
| 392 | const u32 product_model = 1; | ||
| 393 | |||
| 394 | LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model); | ||
| 395 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 396 | rb.Push(ResultSuccess); | ||
| 397 | rb.Push(product_model); | ||
| 398 | } | ||
| 399 | |||
| 400 | void SET_SYS::GetMiiAuthorId(HLERequestContext& ctx) { | ||
| 401 | const auto author_id = Common::UUID::MakeDefault(); | ||
| 402 | |||
| 403 | LOG_WARNING(Service_SET, "(STUBBED) called, author_id={}", author_id.FormattedString()); | ||
| 404 | |||
| 405 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 406 | rb.Push(ResultSuccess); | ||
| 407 | rb.PushRaw(author_id); | ||
| 408 | } | ||
| 409 | |||
| 410 | void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { | ||
| 411 | u8 auto_update_flag{}; | ||
| 412 | |||
| 413 | LOG_WARNING(Service_SET, "(STUBBED) called, auto_update_flag={}", auto_update_flag); | ||
| 414 | |||
| 415 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 416 | rb.Push(ResultSuccess); | ||
| 417 | rb.Push(auto_update_flag); | ||
| 418 | } | ||
| 419 | |||
| 420 | void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) { | ||
| 421 | u8 battery_percentage_flag{1}; | ||
| 422 | |||
| 423 | LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}", | ||
| 424 | battery_percentage_flag); | ||
| 425 | |||
| 426 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 427 | rb.Push(ResultSuccess); | ||
| 428 | rb.Push(battery_percentage_flag); | ||
| 429 | } | ||
| 430 | |||
| 431 | void SET_SYS::GetErrorReportSharePermission(HLERequestContext& ctx) { | ||
| 432 | LOG_WARNING(Service_SET, "(STUBBED) called"); | ||
| 433 | |||
| 434 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 435 | rb.Push(ResultSuccess); | ||
| 436 | rb.PushEnum(ErrorReportSharePermission::Denied); | ||
| 437 | } | ||
| 438 | |||
| 439 | void SET_SYS::GetAppletLaunchFlags(HLERequestContext& ctx) { | ||
| 440 | LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag); | ||
| 441 | |||
| 442 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 443 | rb.Push(ResultSuccess); | ||
| 444 | rb.Push(applet_launch_flag); | ||
| 445 | } | ||
| 446 | |||
| 447 | void SET_SYS::SetAppletLaunchFlags(HLERequestContext& ctx) { | ||
| 448 | IPC::RequestParser rp{ctx}; | ||
| 449 | applet_launch_flag = rp.Pop<u32>(); | ||
| 450 | |||
| 451 | LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag); | ||
| 452 | |||
| 453 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 454 | rb.Push(ResultSuccess); | ||
| 455 | } | ||
| 456 | |||
| 457 | void SET_SYS::GetKeyboardLayout(HLERequestContext& ctx) { | ||
| 458 | const auto language_code = | ||
| 459 | available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())]; | ||
| 460 | const auto key_code = | ||
| 461 | std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), | ||
| 462 | [=](const auto& element) { return element.first == language_code; }); | ||
| 463 | |||
| 464 | KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs; | ||
| 465 | if (key_code != language_to_layout.end()) { | ||
| 466 | selected_keyboard_layout = key_code->second; | ||
| 467 | } | ||
| 468 | |||
| 469 | LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout); | ||
| 470 | |||
| 471 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 472 | rb.Push(ResultSuccess); | ||
| 473 | rb.Push(static_cast<u32>(selected_keyboard_layout)); | ||
| 474 | } | ||
| 475 | |||
| 476 | void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) { | ||
| 477 | LOG_WARNING(Service_SET, "(STUBBED) called"); | ||
| 478 | |||
| 479 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 480 | rb.Push(ResultSuccess); | ||
| 481 | rb.PushEnum(ChineseTraditionalInputMethod::Unknown0); | ||
| 482 | } | ||
| 483 | |||
| 484 | void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) { | ||
| 485 | LOG_WARNING(Service_SET, "(STUBBED) called"); | ||
| 486 | |||
| 487 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 488 | rb.Push(ResultSuccess); | ||
| 489 | rb.Push<u8>(false); | ||
| 185 | } | 490 | } |
| 186 | 491 | ||
| 187 | SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | 492 | SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { |
| 188 | // clang-format off | 493 | // clang-format off |
| 189 | static const FunctionInfo functions[] = { | 494 | static const FunctionInfo functions[] = { |
| 190 | {0, nullptr, "SetLanguageCode"}, | 495 | {0, &SET_SYS::SetLanguageCode, "SetLanguageCode"}, |
| 191 | {1, nullptr, "SetNetworkSettings"}, | 496 | {1, nullptr, "SetNetworkSettings"}, |
| 192 | {2, nullptr, "GetNetworkSettings"}, | 497 | {2, nullptr, "GetNetworkSettings"}, |
| 193 | {3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"}, | 498 | {3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"}, |
| @@ -203,35 +508,35 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 203 | {14, nullptr, "SetExternalSteadyClockSourceId"}, | 508 | {14, nullptr, "SetExternalSteadyClockSourceId"}, |
| 204 | {15, nullptr, "GetUserSystemClockContext"}, | 509 | {15, nullptr, "GetUserSystemClockContext"}, |
| 205 | {16, nullptr, "SetUserSystemClockContext"}, | 510 | {16, nullptr, "SetUserSystemClockContext"}, |
| 206 | {17, nullptr, "GetAccountSettings"}, | 511 | {17, &SET_SYS::GetAccountSettings, "GetAccountSettings"}, |
| 207 | {18, nullptr, "SetAccountSettings"}, | 512 | {18, &SET_SYS::SetAccountSettings, "SetAccountSettings"}, |
| 208 | {19, nullptr, "GetAudioVolume"}, | 513 | {19, nullptr, "GetAudioVolume"}, |
| 209 | {20, nullptr, "SetAudioVolume"}, | 514 | {20, nullptr, "SetAudioVolume"}, |
| 210 | {21, nullptr, "GetEulaVersions"}, | 515 | {21, &SET_SYS::GetEulaVersions, "GetEulaVersions"}, |
| 211 | {22, nullptr, "SetEulaVersions"}, | 516 | {22, &SET_SYS::SetEulaVersions, "SetEulaVersions"}, |
| 212 | {23, &SET_SYS::GetColorSetId, "GetColorSetId"}, | 517 | {23, &SET_SYS::GetColorSetId, "GetColorSetId"}, |
| 213 | {24, &SET_SYS::SetColorSetId, "SetColorSetId"}, | 518 | {24, &SET_SYS::SetColorSetId, "SetColorSetId"}, |
| 214 | {25, nullptr, "GetConsoleInformationUploadFlag"}, | 519 | {25, nullptr, "GetConsoleInformationUploadFlag"}, |
| 215 | {26, nullptr, "SetConsoleInformationUploadFlag"}, | 520 | {26, nullptr, "SetConsoleInformationUploadFlag"}, |
| 216 | {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, | 521 | {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, |
| 217 | {28, nullptr, "SetAutomaticApplicationDownloadFlag"}, | 522 | {28, nullptr, "SetAutomaticApplicationDownloadFlag"}, |
| 218 | {29, nullptr, "GetNotificationSettings"}, | 523 | {29, &SET_SYS::GetNotificationSettings, "GetNotificationSettings"}, |
| 219 | {30, nullptr, "SetNotificationSettings"}, | 524 | {30, &SET_SYS::SetNotificationSettings, "SetNotificationSettings"}, |
| 220 | {31, nullptr, "GetAccountNotificationSettings"}, | 525 | {31, &SET_SYS::GetAccountNotificationSettings, "GetAccountNotificationSettings"}, |
| 221 | {32, nullptr, "SetAccountNotificationSettings"}, | 526 | {32, &SET_SYS::SetAccountNotificationSettings, "SetAccountNotificationSettings"}, |
| 222 | {35, nullptr, "GetVibrationMasterVolume"}, | 527 | {35, nullptr, "GetVibrationMasterVolume"}, |
| 223 | {36, nullptr, "SetVibrationMasterVolume"}, | 528 | {36, nullptr, "SetVibrationMasterVolume"}, |
| 224 | {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, | 529 | {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, |
| 225 | {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"}, | 530 | {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"}, |
| 226 | {39, nullptr, "GetTvSettings"}, | 531 | {39, &SET_SYS::GetTvSettings, "GetTvSettings"}, |
| 227 | {40, nullptr, "SetTvSettings"}, | 532 | {40, &SET_SYS::SetTvSettings, "SetTvSettings"}, |
| 228 | {41, nullptr, "GetEdid"}, | 533 | {41, nullptr, "GetEdid"}, |
| 229 | {42, nullptr, "SetEdid"}, | 534 | {42, nullptr, "SetEdid"}, |
| 230 | {43, nullptr, "GetAudioOutputMode"}, | 535 | {43, nullptr, "GetAudioOutputMode"}, |
| 231 | {44, nullptr, "SetAudioOutputMode"}, | 536 | {44, nullptr, "SetAudioOutputMode"}, |
| 232 | {45, nullptr, "IsForceMuteOnHeadphoneRemoved"}, | 537 | {45, nullptr, "IsForceMuteOnHeadphoneRemoved"}, |
| 233 | {46, nullptr, "SetForceMuteOnHeadphoneRemoved"}, | 538 | {46, nullptr, "SetForceMuteOnHeadphoneRemoved"}, |
| 234 | {47, nullptr, "GetQuestFlag"}, | 539 | {47, &SET_SYS::GetQuestFlag, "GetQuestFlag"}, |
| 235 | {48, nullptr, "SetQuestFlag"}, | 540 | {48, nullptr, "SetQuestFlag"}, |
| 236 | {49, nullptr, "GetDataDeletionSettings"}, | 541 | {49, nullptr, "GetDataDeletionSettings"}, |
| 237 | {50, nullptr, "SetDataDeletionSettings"}, | 542 | {50, nullptr, "SetDataDeletionSettings"}, |
| @@ -241,13 +546,13 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 241 | {54, nullptr, "SetDeviceTimeZoneLocationName"}, | 546 | {54, nullptr, "SetDeviceTimeZoneLocationName"}, |
| 242 | {55, nullptr, "GetWirelessCertificationFileSize"}, | 547 | {55, nullptr, "GetWirelessCertificationFileSize"}, |
| 243 | {56, nullptr, "GetWirelessCertificationFile"}, | 548 | {56, nullptr, "GetWirelessCertificationFile"}, |
| 244 | {57, nullptr, "SetRegionCode"}, | 549 | {57, &SET_SYS::SetRegionCode, "SetRegionCode"}, |
| 245 | {58, nullptr, "GetNetworkSystemClockContext"}, | 550 | {58, nullptr, "GetNetworkSystemClockContext"}, |
| 246 | {59, nullptr, "SetNetworkSystemClockContext"}, | 551 | {59, nullptr, "SetNetworkSystemClockContext"}, |
| 247 | {60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"}, | 552 | {60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"}, |
| 248 | {61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"}, | 553 | {61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"}, |
| 249 | {62, nullptr, "GetDebugModeFlag"}, | 554 | {62, nullptr, "GetDebugModeFlag"}, |
| 250 | {63, nullptr, "GetPrimaryAlbumStorage"}, | 555 | {63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"}, |
| 251 | {64, nullptr, "SetPrimaryAlbumStorage"}, | 556 | {64, nullptr, "SetPrimaryAlbumStorage"}, |
| 252 | {65, nullptr, "GetUsb30EnableFlag"}, | 557 | {65, nullptr, "GetUsb30EnableFlag"}, |
| 253 | {66, nullptr, "SetUsb30EnableFlag"}, | 558 | {66, nullptr, "SetUsb30EnableFlag"}, |
| @@ -255,15 +560,15 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 255 | {68, nullptr, "GetSerialNumber"}, | 560 | {68, nullptr, "GetSerialNumber"}, |
| 256 | {69, nullptr, "GetNfcEnableFlag"}, | 561 | {69, nullptr, "GetNfcEnableFlag"}, |
| 257 | {70, nullptr, "SetNfcEnableFlag"}, | 562 | {70, nullptr, "SetNfcEnableFlag"}, |
| 258 | {71, nullptr, "GetSleepSettings"}, | 563 | {71, &SET_SYS::GetSleepSettings, "GetSleepSettings"}, |
| 259 | {72, nullptr, "SetSleepSettings"}, | 564 | {72, &SET_SYS::SetSleepSettings, "SetSleepSettings"}, |
| 260 | {73, nullptr, "GetWirelessLanEnableFlag"}, | 565 | {73, nullptr, "GetWirelessLanEnableFlag"}, |
| 261 | {74, nullptr, "SetWirelessLanEnableFlag"}, | 566 | {74, nullptr, "SetWirelessLanEnableFlag"}, |
| 262 | {75, nullptr, "GetInitialLaunchSettings"}, | 567 | {75, &SET_SYS::GetInitialLaunchSettings, "GetInitialLaunchSettings"}, |
| 263 | {76, nullptr, "SetInitialLaunchSettings"}, | 568 | {76, &SET_SYS::SetInitialLaunchSettings, "SetInitialLaunchSettings"}, |
| 264 | {77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"}, | 569 | {77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"}, |
| 265 | {78, nullptr, "SetDeviceNickName"}, | 570 | {78, &SET_SYS::SetDeviceNickName, "SetDeviceNickName"}, |
| 266 | {79, nullptr, "GetProductModel"}, | 571 | {79, &SET_SYS::GetProductModel, "GetProductModel"}, |
| 267 | {80, nullptr, "GetLdnChannel"}, | 572 | {80, nullptr, "GetLdnChannel"}, |
| 268 | {81, nullptr, "SetLdnChannel"}, | 573 | {81, nullptr, "SetLdnChannel"}, |
| 269 | {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, | 574 | {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, |
| @@ -274,16 +579,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 274 | {87, nullptr, "SetPtmFuelGaugeParameter"}, | 579 | {87, nullptr, "SetPtmFuelGaugeParameter"}, |
| 275 | {88, nullptr, "GetBluetoothEnableFlag"}, | 580 | {88, nullptr, "GetBluetoothEnableFlag"}, |
| 276 | {89, nullptr, "SetBluetoothEnableFlag"}, | 581 | {89, nullptr, "SetBluetoothEnableFlag"}, |
| 277 | {90, nullptr, "GetMiiAuthorId"}, | 582 | {90, &SET_SYS::GetMiiAuthorId, "GetMiiAuthorId"}, |
| 278 | {91, nullptr, "SetShutdownRtcValue"}, | 583 | {91, nullptr, "SetShutdownRtcValue"}, |
| 279 | {92, nullptr, "GetShutdownRtcValue"}, | 584 | {92, nullptr, "GetShutdownRtcValue"}, |
| 280 | {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, | 585 | {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, |
| 281 | {94, nullptr, "GetFatalDirtyFlags"}, | 586 | {94, nullptr, "GetFatalDirtyFlags"}, |
| 282 | {95, nullptr, "GetAutoUpdateEnableFlag"}, | 587 | {95, &SET_SYS::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, |
| 283 | {96, nullptr, "SetAutoUpdateEnableFlag"}, | 588 | {96, nullptr, "SetAutoUpdateEnableFlag"}, |
| 284 | {97, nullptr, "GetNxControllerSettings"}, | 589 | {97, nullptr, "GetNxControllerSettings"}, |
| 285 | {98, nullptr, "SetNxControllerSettings"}, | 590 | {98, nullptr, "SetNxControllerSettings"}, |
| 286 | {99, nullptr, "GetBatteryPercentageFlag"}, | 591 | {99, &SET_SYS::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, |
| 287 | {100, nullptr, "SetBatteryPercentageFlag"}, | 592 | {100, nullptr, "SetBatteryPercentageFlag"}, |
| 288 | {101, nullptr, "GetExternalRtcResetFlag"}, | 593 | {101, nullptr, "GetExternalRtcResetFlag"}, |
| 289 | {102, nullptr, "SetExternalRtcResetFlag"}, | 594 | {102, nullptr, "SetExternalRtcResetFlag"}, |
| @@ -308,10 +613,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 308 | {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, | 613 | {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, |
| 309 | {122, nullptr, "GetServiceDiscoveryControlSettings"}, | 614 | {122, nullptr, "GetServiceDiscoveryControlSettings"}, |
| 310 | {123, nullptr, "SetServiceDiscoveryControlSettings"}, | 615 | {123, nullptr, "SetServiceDiscoveryControlSettings"}, |
| 311 | {124, nullptr, "GetErrorReportSharePermission"}, | 616 | {124, &SET_SYS::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, |
| 312 | {125, nullptr, "SetErrorReportSharePermission"}, | 617 | {125, nullptr, "SetErrorReportSharePermission"}, |
| 313 | {126, nullptr, "GetAppletLaunchFlags"}, | 618 | {126, &SET_SYS::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, |
| 314 | {127, nullptr, "SetAppletLaunchFlags"}, | 619 | {127, &SET_SYS::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, |
| 315 | {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, | 620 | {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, |
| 316 | {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, | 621 | {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, |
| 317 | {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, | 622 | {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, |
| @@ -320,7 +625,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 320 | {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, | 625 | {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, |
| 321 | {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, | 626 | {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, |
| 322 | {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, | 627 | {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, |
| 323 | {136, nullptr, "GetKeyboardLayout"}, | 628 | {136, &SET_SYS::GetKeyboardLayout, "GetKeyboardLayout"}, |
| 324 | {137, nullptr, "SetKeyboardLayout"}, | 629 | {137, nullptr, "SetKeyboardLayout"}, |
| 325 | {138, nullptr, "GetWebInspectorFlag"}, | 630 | {138, nullptr, "GetWebInspectorFlag"}, |
| 326 | {139, nullptr, "GetAllowedSslHosts"}, | 631 | {139, nullptr, "GetAllowedSslHosts"}, |
| @@ -354,7 +659,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 354 | {167, nullptr, "SetUsb30DeviceEnableFlag"}, | 659 | {167, nullptr, "SetUsb30DeviceEnableFlag"}, |
| 355 | {168, nullptr, "GetThemeId"}, | 660 | {168, nullptr, "GetThemeId"}, |
| 356 | {169, nullptr, "SetThemeId"}, | 661 | {169, nullptr, "SetThemeId"}, |
| 357 | {170, nullptr, "GetChineseTraditionalInputMethod"}, | 662 | {170, &SET_SYS::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"}, |
| 358 | {171, nullptr, "SetChineseTraditionalInputMethod"}, | 663 | {171, nullptr, "SetChineseTraditionalInputMethod"}, |
| 359 | {172, nullptr, "GetPtmCycleCountReliability"}, | 664 | {172, nullptr, "GetPtmCycleCountReliability"}, |
| 360 | {173, nullptr, "SetPtmCycleCountReliability"}, | 665 | {173, nullptr, "SetPtmCycleCountReliability"}, |
| @@ -385,12 +690,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { | |||
| 385 | {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, | 690 | {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, |
| 386 | {199, nullptr, "GetButtonConfigRegisteredSettings"}, | 691 | {199, nullptr, "GetButtonConfigRegisteredSettings"}, |
| 387 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, | 692 | {200, nullptr, "SetButtonConfigRegisteredSettings"}, |
| 388 | {201, nullptr, "GetFieldTestingFlag"}, | 693 | {201, &SET_SYS::GetFieldTestingFlag, "GetFieldTestingFlag"}, |
| 389 | {202, nullptr, "SetFieldTestingFlag"}, | 694 | {202, nullptr, "SetFieldTestingFlag"}, |
| 390 | {203, nullptr, "GetPanelCrcMode"}, | 695 | {203, nullptr, "GetPanelCrcMode"}, |
| 391 | {204, nullptr, "SetPanelCrcMode"}, | 696 | {204, nullptr, "SetPanelCrcMode"}, |
| 392 | {205, nullptr, "GetNxControllerSettingsEx"}, | 697 | {205, nullptr, "GetNxControllerSettingsEx"}, |
| 393 | {206, nullptr, "SetNxControllerSettingsEx"}, | 698 | {206, nullptr, "SetNxControllerSettingsEx"}, |
| 699 | {207, nullptr, "GetHearingProtectionSafeguardFlag"}, | ||
| 700 | {208, nullptr, "SetHearingProtectionSafeguardFlag"}, | ||
| 701 | {209, nullptr, "GetHearingProtectionSafeguardRemainingTime"}, | ||
| 702 | {210, nullptr, "SetHearingProtectionSafeguardRemainingTime"}, | ||
| 394 | }; | 703 | }; |
| 395 | // clang-format on | 704 | // clang-format on |
| 396 | 705 | ||
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index 1efbcc97a..c7dba2a9e 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h | |||
| @@ -3,7 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include "common/uuid.h" | ||
| 6 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | #include "core/hle/service/time/clock_types.h" | ||
| 7 | 9 | ||
| 8 | namespace Core { | 10 | namespace Core { |
| 9 | class System; | 11 | class System; |
| @@ -23,15 +25,331 @@ private: | |||
| 23 | BasicBlack = 1, | 25 | BasicBlack = 1, |
| 24 | }; | 26 | }; |
| 25 | 27 | ||
| 26 | void GetSettingsItemValueSize(HLERequestContext& ctx); | 28 | /// Indicates the current console is a retail or kiosk unit |
| 27 | void GetSettingsItemValue(HLERequestContext& ctx); | 29 | enum class QuestFlag : u8 { |
| 30 | Retail = 0, | ||
| 31 | Kiosk = 1, | ||
| 32 | }; | ||
| 33 | |||
| 34 | /// This is nn::settings::system::TvResolution | ||
| 35 | enum class TvResolution : u32 { | ||
| 36 | Auto, | ||
| 37 | Resolution1080p, | ||
| 38 | Resolution720p, | ||
| 39 | Resolution480p, | ||
| 40 | }; | ||
| 41 | |||
| 42 | /// This is nn::settings::system::HdmiContentType | ||
| 43 | enum class HdmiContentType : u32 { | ||
| 44 | None, | ||
| 45 | Graphics, | ||
| 46 | Cinema, | ||
| 47 | Photo, | ||
| 48 | Game, | ||
| 49 | }; | ||
| 50 | |||
| 51 | /// This is nn::settings::system::RgbRange | ||
| 52 | enum class RgbRange : u32 { | ||
| 53 | Auto, | ||
| 54 | Full, | ||
| 55 | Limited, | ||
| 56 | }; | ||
| 57 | |||
| 58 | /// This is nn::settings::system::CmuMode | ||
| 59 | enum class CmuMode : u32 { | ||
| 60 | None, | ||
| 61 | ColorInvert, | ||
| 62 | HighContrast, | ||
| 63 | GrayScale, | ||
| 64 | }; | ||
| 65 | |||
| 66 | /// This is nn::settings::system::PrimaryAlbumStorage | ||
| 67 | enum class PrimaryAlbumStorage : u32 { | ||
| 68 | Nand, | ||
| 69 | SdCard, | ||
| 70 | }; | ||
| 71 | |||
| 72 | /// This is nn::settings::system::NotificationVolume | ||
| 73 | enum class NotificationVolume : u32 { | ||
| 74 | Mute, | ||
| 75 | Low, | ||
| 76 | High, | ||
| 77 | }; | ||
| 78 | |||
| 79 | /// This is nn::settings::system::ChineseTraditionalInputMethod | ||
| 80 | enum class ChineseTraditionalInputMethod : u32 { | ||
| 81 | Unknown0 = 0, | ||
| 82 | Unknown1 = 1, | ||
| 83 | Unknown2 = 2, | ||
| 84 | }; | ||
| 85 | |||
| 86 | /// This is nn::settings::system::ErrorReportSharePermission | ||
| 87 | enum class ErrorReportSharePermission : u32 { | ||
| 88 | NotConfirmed, | ||
| 89 | Granted, | ||
| 90 | Denied, | ||
| 91 | }; | ||
| 92 | |||
| 93 | /// This is nn::settings::system::FriendPresenceOverlayPermission | ||
| 94 | enum class FriendPresenceOverlayPermission : u8 { | ||
| 95 | NotConfirmed, | ||
| 96 | NoDisplay, | ||
| 97 | FavoriteFriends, | ||
| 98 | Friends, | ||
| 99 | }; | ||
| 100 | |||
| 101 | /// This is nn::settings::system::HandheldSleepPlan | ||
| 102 | enum class HandheldSleepPlan : u32 { | ||
| 103 | Sleep1Min, | ||
| 104 | Sleep3Min, | ||
| 105 | Sleep5Min, | ||
| 106 | Sleep10Min, | ||
| 107 | Sleep30Min, | ||
| 108 | Never, | ||
| 109 | }; | ||
| 110 | |||
| 111 | /// This is nn::settings::system::ConsoleSleepPlan | ||
| 112 | enum class ConsoleSleepPlan : u32 { | ||
| 113 | Sleep1Hour, | ||
| 114 | Sleep2Hour, | ||
| 115 | Sleep3Hour, | ||
| 116 | Sleep6Hour, | ||
| 117 | Sleep12Hour, | ||
| 118 | Never, | ||
| 119 | }; | ||
| 120 | |||
| 121 | /// This is nn::settings::system::RegionCode | ||
| 122 | enum class RegionCode : u32 { | ||
| 123 | Japan, | ||
| 124 | Usa, | ||
| 125 | Europe, | ||
| 126 | Australia, | ||
| 127 | HongKongTaiwanKorea, | ||
| 128 | China, | ||
| 129 | }; | ||
| 130 | |||
| 131 | /// This is nn::settings::system::EulaVersionClockType | ||
| 132 | enum class EulaVersionClockType : u32 { | ||
| 133 | NetworkSystemClock, | ||
| 134 | SteadyClock, | ||
| 135 | }; | ||
| 136 | |||
| 137 | /// This is nn::settings::system::SleepFlag | ||
| 138 | struct SleepFlag { | ||
| 139 | union { | ||
| 140 | u32 raw{}; | ||
| 141 | |||
| 142 | BitField<0, 1, u32> SleepsWhilePlayingMedia; | ||
| 143 | BitField<1, 1, u32> WakesAtPowerStateChange; | ||
| 144 | }; | ||
| 145 | }; | ||
| 146 | static_assert(sizeof(SleepFlag) == 4, "TvFlag is an invalid size"); | ||
| 147 | |||
| 148 | /// This is nn::settings::system::TvFlag | ||
| 149 | struct TvFlag { | ||
| 150 | union { | ||
| 151 | u32 raw{}; | ||
| 152 | |||
| 153 | BitField<0, 1, u32> Allows4k; | ||
| 154 | BitField<1, 1, u32> Allows3d; | ||
| 155 | BitField<2, 1, u32> AllowsCec; | ||
| 156 | BitField<3, 1, u32> PreventsScreenBurnIn; | ||
| 157 | }; | ||
| 158 | }; | ||
| 159 | static_assert(sizeof(TvFlag) == 4, "TvFlag is an invalid size"); | ||
| 160 | |||
| 161 | /// This is nn::settings::system::InitialLaunchFlag | ||
| 162 | struct InitialLaunchFlag { | ||
| 163 | union { | ||
| 164 | u32 raw{}; | ||
| 165 | |||
| 166 | BitField<0, 1, u32> InitialLaunchCompletionFlag; | ||
| 167 | BitField<8, 1, u32> InitialLaunchUserAdditionFlag; | ||
| 168 | BitField<16, 1, u32> InitialLaunchTimestampFlag; | ||
| 169 | }; | ||
| 170 | }; | ||
| 171 | static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size"); | ||
| 172 | |||
| 173 | /// This is nn::settings::system::NotificationFlag | ||
| 174 | struct NotificationFlag { | ||
| 175 | union { | ||
| 176 | u32 raw{}; | ||
| 177 | |||
| 178 | BitField<0, 1, u32> RingtoneFlag; | ||
| 179 | BitField<1, 1, u32> DownloadCompletionFlag; | ||
| 180 | BitField<8, 1, u32> EnablesNews; | ||
| 181 | BitField<9, 1, u32> IncomingLampFlag; | ||
| 182 | }; | ||
| 183 | }; | ||
| 184 | static_assert(sizeof(NotificationFlag) == 4, "NotificationFlag is an invalid size"); | ||
| 185 | |||
| 186 | /// This is nn::settings::system::AccountNotificationFlag | ||
| 187 | struct AccountNotificationFlag { | ||
| 188 | union { | ||
| 189 | u32 raw{}; | ||
| 190 | |||
| 191 | BitField<0, 1, u32> FriendOnlineFlag; | ||
| 192 | BitField<1, 1, u32> FriendRequestFlag; | ||
| 193 | BitField<8, 1, u32> CoralInvitationFlag; | ||
| 194 | }; | ||
| 195 | }; | ||
| 196 | static_assert(sizeof(AccountNotificationFlag) == 4, | ||
| 197 | "AccountNotificationFlag is an invalid size"); | ||
| 198 | |||
| 199 | /// This is nn::settings::system::TvSettings | ||
| 200 | struct TvSettings { | ||
| 201 | TvFlag flags; | ||
| 202 | TvResolution tv_resolution; | ||
| 203 | HdmiContentType hdmi_content_type; | ||
| 204 | RgbRange rgb_range; | ||
| 205 | CmuMode cmu_mode; | ||
| 206 | u32 tv_underscan; | ||
| 207 | f32 tv_gama; | ||
| 208 | f32 constrast_ratio; | ||
| 209 | }; | ||
| 210 | static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size"); | ||
| 211 | |||
| 212 | /// This is nn::settings::system::NotificationTime | ||
| 213 | struct NotificationTime { | ||
| 214 | u32 hour; | ||
| 215 | u32 minute; | ||
| 216 | }; | ||
| 217 | static_assert(sizeof(NotificationTime) == 0x8, "NotificationTime is an invalid size"); | ||
| 218 | |||
| 219 | /// This is nn::settings::system::NotificationSettings | ||
| 220 | struct NotificationSettings { | ||
| 221 | NotificationFlag flags; | ||
| 222 | NotificationVolume volume; | ||
| 223 | NotificationTime start_time; | ||
| 224 | NotificationTime stop_time; | ||
| 225 | }; | ||
| 226 | static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); | ||
| 227 | |||
| 228 | /// This is nn::settings::system::AccountSettings | ||
| 229 | struct AccountSettings { | ||
| 230 | u32 flags; | ||
| 231 | }; | ||
| 232 | static_assert(sizeof(AccountSettings) == 0x4, "AccountSettings is an invalid size"); | ||
| 233 | |||
| 234 | /// This is nn::settings::system::AccountNotificationSettings | ||
| 235 | struct AccountNotificationSettings { | ||
| 236 | Common::UUID uid; | ||
| 237 | AccountNotificationFlag flags; | ||
| 238 | FriendPresenceOverlayPermission friend_presence_permission; | ||
| 239 | FriendPresenceOverlayPermission friend_invitation_permission; | ||
| 240 | INSERT_PADDING_BYTES(0x2); | ||
| 241 | }; | ||
| 242 | static_assert(sizeof(AccountNotificationSettings) == 0x18, | ||
| 243 | "AccountNotificationSettings is an invalid size"); | ||
| 244 | |||
| 245 | /// This is nn::settings::system::InitialLaunchSettings | ||
| 246 | struct SleepSettings { | ||
| 247 | SleepFlag flags; | ||
| 248 | HandheldSleepPlan handheld_sleep_plan; | ||
| 249 | ConsoleSleepPlan console_sleep_plan; | ||
| 250 | }; | ||
| 251 | static_assert(sizeof(SleepSettings) == 0xc, "SleepSettings is incorrect size"); | ||
| 252 | |||
| 253 | /// This is nn::settings::system::InitialLaunchSettings | ||
| 254 | struct InitialLaunchSettings { | ||
| 255 | InitialLaunchFlag flags; | ||
| 256 | INSERT_PADDING_BYTES(0x4); | ||
| 257 | Time::Clock::SteadyClockTimePoint timestamp; | ||
| 258 | }; | ||
| 259 | static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size"); | ||
| 260 | |||
| 261 | /// This is nn::settings::system::InitialLaunchSettings | ||
| 262 | struct EulaVersion { | ||
| 263 | u32 version; | ||
| 264 | RegionCode region_code; | ||
| 265 | EulaVersionClockType clock_type; | ||
| 266 | INSERT_PADDING_BYTES(0x4); | ||
| 267 | s64 posix_time; | ||
| 268 | Time::Clock::SteadyClockTimePoint timestamp; | ||
| 269 | }; | ||
| 270 | static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size"); | ||
| 271 | |||
| 272 | void SetLanguageCode(HLERequestContext& ctx); | ||
| 28 | void GetFirmwareVersion(HLERequestContext& ctx); | 273 | void GetFirmwareVersion(HLERequestContext& ctx); |
| 29 | void GetFirmwareVersion2(HLERequestContext& ctx); | 274 | void GetFirmwareVersion2(HLERequestContext& ctx); |
| 275 | void GetAccountSettings(HLERequestContext& ctx); | ||
| 276 | void SetAccountSettings(HLERequestContext& ctx); | ||
| 277 | void GetEulaVersions(HLERequestContext& ctx); | ||
| 278 | void SetEulaVersions(HLERequestContext& ctx); | ||
| 30 | void GetColorSetId(HLERequestContext& ctx); | 279 | void GetColorSetId(HLERequestContext& ctx); |
| 31 | void SetColorSetId(HLERequestContext& ctx); | 280 | void SetColorSetId(HLERequestContext& ctx); |
| 281 | void GetNotificationSettings(HLERequestContext& ctx); | ||
| 282 | void SetNotificationSettings(HLERequestContext& ctx); | ||
| 283 | void GetAccountNotificationSettings(HLERequestContext& ctx); | ||
| 284 | void SetAccountNotificationSettings(HLERequestContext& ctx); | ||
| 285 | void GetSettingsItemValueSize(HLERequestContext& ctx); | ||
| 286 | void GetSettingsItemValue(HLERequestContext& ctx); | ||
| 287 | void GetTvSettings(HLERequestContext& ctx); | ||
| 288 | void SetTvSettings(HLERequestContext& ctx); | ||
| 289 | void GetQuestFlag(HLERequestContext& ctx); | ||
| 290 | void SetRegionCode(HLERequestContext& ctx); | ||
| 291 | void GetPrimaryAlbumStorage(HLERequestContext& ctx); | ||
| 292 | void GetSleepSettings(HLERequestContext& ctx); | ||
| 293 | void SetSleepSettings(HLERequestContext& ctx); | ||
| 294 | void GetInitialLaunchSettings(HLERequestContext& ctx); | ||
| 295 | void SetInitialLaunchSettings(HLERequestContext& ctx); | ||
| 32 | void GetDeviceNickName(HLERequestContext& ctx); | 296 | void GetDeviceNickName(HLERequestContext& ctx); |
| 297 | void SetDeviceNickName(HLERequestContext& ctx); | ||
| 298 | void GetProductModel(HLERequestContext& ctx); | ||
| 299 | void GetMiiAuthorId(HLERequestContext& ctx); | ||
| 300 | void GetAutoUpdateEnableFlag(HLERequestContext& ctx); | ||
| 301 | void GetBatteryPercentageFlag(HLERequestContext& ctx); | ||
| 302 | void GetErrorReportSharePermission(HLERequestContext& ctx); | ||
| 303 | void GetAppletLaunchFlags(HLERequestContext& ctx); | ||
| 304 | void SetAppletLaunchFlags(HLERequestContext& ctx); | ||
| 305 | void GetKeyboardLayout(HLERequestContext& ctx); | ||
| 306 | void GetChineseTraditionalInputMethod(HLERequestContext& ctx); | ||
| 307 | void GetFieldTestingFlag(HLERequestContext& ctx); | ||
| 308 | |||
| 309 | AccountSettings account_settings{ | ||
| 310 | .flags = {}, | ||
| 311 | }; | ||
| 33 | 312 | ||
| 34 | ColorSet color_set = ColorSet::BasicWhite; | 313 | ColorSet color_set = ColorSet::BasicWhite; |
| 314 | |||
| 315 | NotificationSettings notification_settings{ | ||
| 316 | .flags = {0x300}, | ||
| 317 | .volume = NotificationVolume::High, | ||
| 318 | .start_time = {.hour = 9, .minute = 0}, | ||
| 319 | .stop_time = {.hour = 21, .minute = 0}, | ||
| 320 | }; | ||
| 321 | |||
| 322 | std::vector<AccountNotificationSettings> account_notifications{}; | ||
| 323 | |||
| 324 | TvSettings tv_settings{ | ||
| 325 | .flags = {0xc}, | ||
| 326 | .tv_resolution = TvResolution::Auto, | ||
| 327 | .hdmi_content_type = HdmiContentType::Game, | ||
| 328 | .rgb_range = RgbRange::Auto, | ||
| 329 | .cmu_mode = CmuMode::None, | ||
| 330 | .tv_underscan = {}, | ||
| 331 | .tv_gama = 1.0f, | ||
| 332 | .constrast_ratio = 0.5f, | ||
| 333 | }; | ||
| 334 | |||
| 335 | InitialLaunchSettings launch_settings{ | ||
| 336 | .flags = {0x10001}, | ||
| 337 | .timestamp = {}, | ||
| 338 | }; | ||
| 339 | |||
| 340 | SleepSettings sleep_settings{ | ||
| 341 | .flags = {0x3}, | ||
| 342 | .handheld_sleep_plan = HandheldSleepPlan::Sleep10Min, | ||
| 343 | .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, | ||
| 344 | }; | ||
| 345 | |||
| 346 | u32 applet_launch_flag{}; | ||
| 347 | |||
| 348 | std::vector<EulaVersion> eula_versions{}; | ||
| 349 | |||
| 350 | RegionCode region_code; | ||
| 351 | |||
| 352 | LanguageCode language_code_setting; | ||
| 35 | }; | 353 | }; |
| 36 | 354 | ||
| 37 | } // namespace Service::Set | 355 | } // namespace Service::Set |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 1608fa24c..9ab718e0a 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -52,8 +52,7 @@ static Result ValidateServiceName(const std::string& name) { | |||
| 52 | 52 | ||
| 53 | Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | 53 | Result ServiceManager::RegisterService(std::string name, u32 max_sessions, |
| 54 | SessionRequestHandlerPtr handler) { | 54 | SessionRequestHandlerPtr handler) { |
| 55 | 55 | R_TRY(ValidateServiceName(name)); | |
| 56 | CASCADE_CODE(ValidateServiceName(name)); | ||
| 57 | 56 | ||
| 58 | std::scoped_lock lk{lock}; | 57 | std::scoped_lock lk{lock}; |
| 59 | if (registered_services.find(name) != registered_services.end()) { | 58 | if (registered_services.find(name) != registered_services.end()) { |
| @@ -77,7 +76,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | |||
| 77 | } | 76 | } |
| 78 | 77 | ||
| 79 | Result ServiceManager::UnregisterService(const std::string& name) { | 78 | Result ServiceManager::UnregisterService(const std::string& name) { |
| 80 | CASCADE_CODE(ValidateServiceName(name)); | 79 | R_TRY(ValidateServiceName(name)); |
| 81 | 80 | ||
| 82 | std::scoped_lock lk{lock}; | 81 | std::scoped_lock lk{lock}; |
| 83 | const auto iter = registered_services.find(name); | 82 | const auto iter = registered_services.find(name); |
| @@ -92,8 +91,8 @@ Result ServiceManager::UnregisterService(const std::string& name) { | |||
| 92 | return ResultSuccess; | 91 | return ResultSuccess; |
| 93 | } | 92 | } |
| 94 | 93 | ||
| 95 | ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) { | 94 | Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) { |
| 96 | CASCADE_CODE(ValidateServiceName(name)); | 95 | R_TRY(ValidateServiceName(name)); |
| 97 | 96 | ||
| 98 | std::scoped_lock lk{lock}; | 97 | std::scoped_lock lk{lock}; |
| 99 | auto it = service_ports.find(name); | 98 | auto it = service_ports.find(name); |
| @@ -102,7 +101,8 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name | |||
| 102 | return Service::SM::ResultNotRegistered; | 101 | return Service::SM::ResultNotRegistered; |
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | return it->second; | 104 | *out_port = it->second; |
| 105 | return ResultSuccess; | ||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /** | 108 | /** |
| @@ -122,32 +122,34 @@ void SM::Initialize(HLERequestContext& ctx) { | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | void SM::GetService(HLERequestContext& ctx) { | 124 | void SM::GetService(HLERequestContext& ctx) { |
| 125 | auto result = GetServiceImpl(ctx); | 125 | Kernel::KClientSession* client_session{}; |
| 126 | auto result = GetServiceImpl(&client_session, ctx); | ||
| 126 | if (ctx.GetIsDeferred()) { | 127 | if (ctx.GetIsDeferred()) { |
| 127 | // Don't overwrite the command buffer. | 128 | // Don't overwrite the command buffer. |
| 128 | return; | 129 | return; |
| 129 | } | 130 | } |
| 130 | 131 | ||
| 131 | if (result.Succeeded()) { | 132 | if (result == ResultSuccess) { |
| 132 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 133 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 133 | rb.Push(result.Code()); | 134 | rb.Push(result); |
| 134 | rb.PushMoveObjects(result.Unwrap()); | 135 | rb.PushMoveObjects(client_session); |
| 135 | } else { | 136 | } else { |
| 136 | IPC::ResponseBuilder rb{ctx, 2}; | 137 | IPC::ResponseBuilder rb{ctx, 2}; |
| 137 | rb.Push(result.Code()); | 138 | rb.Push(result); |
| 138 | } | 139 | } |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | void SM::GetServiceTipc(HLERequestContext& ctx) { | 142 | void SM::GetServiceTipc(HLERequestContext& ctx) { |
| 142 | auto result = GetServiceImpl(ctx); | 143 | Kernel::KClientSession* client_session{}; |
| 144 | auto result = GetServiceImpl(&client_session, ctx); | ||
| 143 | if (ctx.GetIsDeferred()) { | 145 | if (ctx.GetIsDeferred()) { |
| 144 | // Don't overwrite the command buffer. | 146 | // Don't overwrite the command buffer. |
| 145 | return; | 147 | return; |
| 146 | } | 148 | } |
| 147 | 149 | ||
| 148 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 150 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 149 | rb.Push(result.Code()); | 151 | rb.Push(result); |
| 150 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | 152 | rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr); |
| 151 | } | 153 | } |
| 152 | 154 | ||
| 153 | static std::string PopServiceName(IPC::RequestParser& rp) { | 155 | static std::string PopServiceName(IPC::RequestParser& rp) { |
| @@ -161,7 +163,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) { | |||
| 161 | return result; | 163 | return result; |
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | 166 | Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx) { |
| 165 | if (!ctx.GetManager()->GetIsInitializedForSm()) { | 167 | if (!ctx.GetManager()->GetIsInitializedForSm()) { |
| 166 | return Service::SM::ResultInvalidClient; | 168 | return Service::SM::ResultInvalidClient; |
| 167 | } | 169 | } |
| @@ -170,18 +172,18 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | |||
| 170 | std::string name(PopServiceName(rp)); | 172 | std::string name(PopServiceName(rp)); |
| 171 | 173 | ||
| 172 | // Find the named port. | 174 | // Find the named port. |
| 173 | auto port_result = service_manager.GetServicePort(name); | 175 | Kernel::KPort* port{}; |
| 174 | if (port_result.Code() == Service::SM::ResultInvalidServiceName) { | 176 | auto port_result = service_manager.GetServicePort(&port, name); |
| 177 | if (port_result == Service::SM::ResultInvalidServiceName) { | ||
| 175 | LOG_ERROR(Service_SM, "Invalid service name '{}'", name); | 178 | LOG_ERROR(Service_SM, "Invalid service name '{}'", name); |
| 176 | return Service::SM::ResultInvalidServiceName; | 179 | return Service::SM::ResultInvalidServiceName; |
| 177 | } | 180 | } |
| 178 | 181 | ||
| 179 | if (port_result.Failed()) { | 182 | if (port_result != ResultSuccess) { |
| 180 | LOG_INFO(Service_SM, "Waiting for service {} to become available", name); | 183 | LOG_INFO(Service_SM, "Waiting for service {} to become available", name); |
| 181 | ctx.SetIsDeferred(); | 184 | ctx.SetIsDeferred(); |
| 182 | return Service::SM::ResultNotRegistered; | 185 | return Service::SM::ResultNotRegistered; |
| 183 | } | 186 | } |
| 184 | auto& port = port_result.Unwrap(); | ||
| 185 | 187 | ||
| 186 | // Create a new session. | 188 | // Create a new session. |
| 187 | Kernel::KClientSession* session{}; | 189 | Kernel::KClientSession* session{}; |
| @@ -192,7 +194,8 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) { | |||
| 192 | 194 | ||
| 193 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); | 195 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
| 194 | 196 | ||
| 195 | return session; | 197 | *out_client_session = session; |
| 198 | return ResultSuccess; | ||
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | void SM::RegisterService(HLERequestContext& ctx) { | 201 | void SM::RegisterService(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 6697f4007..14bfaf8c2 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -42,7 +42,7 @@ private: | |||
| 42 | void RegisterService(HLERequestContext& ctx); | 42 | void RegisterService(HLERequestContext& ctx); |
| 43 | void UnregisterService(HLERequestContext& ctx); | 43 | void UnregisterService(HLERequestContext& ctx); |
| 44 | 44 | ||
| 45 | ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx); | 45 | Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx); |
| 46 | 46 | ||
| 47 | ServiceManager& service_manager; | 47 | ServiceManager& service_manager; |
| 48 | Kernel::KernelCore& kernel; | 48 | Kernel::KernelCore& kernel; |
| @@ -55,7 +55,7 @@ public: | |||
| 55 | 55 | ||
| 56 | Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); | 56 | Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); |
| 57 | Result UnregisterService(const std::string& name); | 57 | Result UnregisterService(const std::string& name); |
| 58 | ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); | 58 | Result GetServicePort(Kernel::KPort** out_port, const std::string& name); |
| 59 | 59 | ||
| 60 | template <Common::DerivedFrom<SessionRequestHandler> T> | 60 | template <Common::DerivedFrom<SessionRequestHandler> T> |
| 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { | 61 | std::shared_ptr<T> GetService(const std::string& service_name) const { |
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index 5dfcaabb1..bac21752a 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp | |||
| @@ -54,7 +54,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na | |||
| 54 | RegisterHandlers(functions); | 54 | RegisterHandlers(functions); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) { | 57 | static std::string ResolveImpl(const std::string& fqdn_in) { |
| 58 | // The real implementation makes various substitutions. | 58 | // The real implementation makes various substitutions. |
| 59 | // For now we just return the string as-is, which is good enough when not | 59 | // For now we just return the string as-is, which is good enough when not |
| 60 | // connecting to real Nintendo servers. | 60 | // connecting to real Nintendo servers. |
| @@ -64,13 +64,10 @@ static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) { | |||
| 64 | 64 | ||
| 65 | static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) { | 65 | static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) { |
| 66 | const auto res = ResolveImpl(fqdn_in); | 66 | const auto res = ResolveImpl(fqdn_in); |
| 67 | if (res.Failed()) { | 67 | if (res.size() >= fqdn_out.size()) { |
| 68 | return res.Code(); | ||
| 69 | } | ||
| 70 | if (res->size() >= fqdn_out.size()) { | ||
| 71 | return ResultOverflow; | 68 | return ResultOverflow; |
| 72 | } | 69 | } |
| 73 | std::memcpy(fqdn_out.data(), res->c_str(), res->size() + 1); | 70 | std::memcpy(fqdn_out.data(), res.c_str(), res.size() + 1); |
| 74 | return ResultSuccess; | 71 | return ResultSuccess; |
| 75 | } | 72 | } |
| 76 | 73 | ||
diff --git a/src/core/hle/service/spl/spl_module.cpp b/src/core/hle/service/spl/spl_module.cpp index cd631b2ea..549e6f4fa 100644 --- a/src/core/hle/service/spl/spl_module.cpp +++ b/src/core/hle/service/spl/spl_module.cpp | |||
| @@ -30,10 +30,10 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) { | |||
| 30 | 30 | ||
| 31 | // This should call svcCallSecureMonitor with the appropriate args. | 31 | // This should call svcCallSecureMonitor with the appropriate args. |
| 32 | // Since we do not have it implemented yet, we will use this for now. | 32 | // Since we do not have it implemented yet, we will use this for now. |
| 33 | const auto smc_result = GetConfigImpl(config_item); | 33 | u64 smc_result{}; |
| 34 | const auto result_code = smc_result.Code(); | 34 | const auto result_code = GetConfigImpl(&smc_result, config_item); |
| 35 | 35 | ||
| 36 | if (smc_result.Failed()) { | 36 | if (result_code != ResultSuccess) { |
| 37 | LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, | 37 | LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, |
| 38 | result_code.raw); | 38 | result_code.raw); |
| 39 | 39 | ||
| @@ -42,11 +42,11 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) { | |||
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, | 44 | LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, |
| 45 | result_code.raw, *smc_result); | 45 | result_code.raw, smc_result); |
| 46 | 46 | ||
| 47 | IPC::ResponseBuilder rb{ctx, 4}; | 47 | IPC::ResponseBuilder rb{ctx, 4}; |
| 48 | rb.Push(result_code); | 48 | rb.Push(result_code); |
| 49 | rb.Push(*smc_result); | 49 | rb.Push(smc_result); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { | 52 | void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { |
| @@ -99,7 +99,7 @@ void Module::Interface::GetBootReason(HLERequestContext& ctx) { | |||
| 99 | rb.Push(ResultSecureMonitorNotImplemented); | 99 | rb.Push(ResultSecureMonitorNotImplemented); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const { | 102 | Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item) const { |
| 103 | switch (config_item) { | 103 | switch (config_item) { |
| 104 | case ConfigItem::DisableProgramVerification: | 104 | case ConfigItem::DisableProgramVerification: |
| 105 | case ConfigItem::DramId: | 105 | case ConfigItem::DramId: |
| @@ -121,40 +121,50 @@ ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const { | |||
| 121 | return ResultSecureMonitorNotImplemented; | 121 | return ResultSecureMonitorNotImplemented; |
| 122 | case ConfigItem::ExosphereApiVersion: | 122 | case ConfigItem::ExosphereApiVersion: |
| 123 | // Get information about the current exosphere version. | 123 | // Get information about the current exosphere version. |
| 124 | return (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | | 124 | *out_config = (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | |
| 125 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | | 125 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | |
| 126 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | | 126 | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | |
| 127 | (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())); | 127 | (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())); |
| 128 | return ResultSuccess; | ||
| 128 | case ConfigItem::ExosphereNeedsReboot: | 129 | case ConfigItem::ExosphereNeedsReboot: |
| 129 | // We are executing, so we aren't in the process of rebooting. | 130 | // We are executing, so we aren't in the process of rebooting. |
| 130 | return u64{0}; | 131 | *out_config = u64{0}; |
| 132 | return ResultSuccess; | ||
| 131 | case ConfigItem::ExosphereNeedsShutdown: | 133 | case ConfigItem::ExosphereNeedsShutdown: |
| 132 | // We are executing, so we aren't in the process of shutting down. | 134 | // We are executing, so we aren't in the process of shutting down. |
| 133 | return u64{0}; | 135 | *out_config = u64{0}; |
| 136 | return ResultSuccess; | ||
| 134 | case ConfigItem::ExosphereGitCommitHash: | 137 | case ConfigItem::ExosphereGitCommitHash: |
| 135 | // Get information about the current exosphere git commit hash. | 138 | // Get information about the current exosphere git commit hash. |
| 136 | return u64{0}; | 139 | *out_config = u64{0}; |
| 140 | return ResultSuccess; | ||
| 137 | case ConfigItem::ExosphereHasRcmBugPatch: | 141 | case ConfigItem::ExosphereHasRcmBugPatch: |
| 138 | // Get information about whether this unit has the RCM bug patched. | 142 | // Get information about whether this unit has the RCM bug patched. |
| 139 | return u64{0}; | 143 | *out_config = u64{0}; |
| 144 | return ResultSuccess; | ||
| 140 | case ConfigItem::ExosphereBlankProdInfo: | 145 | case ConfigItem::ExosphereBlankProdInfo: |
| 141 | // Get whether this unit should simulate a "blanked" PRODINFO. | 146 | // Get whether this unit should simulate a "blanked" PRODINFO. |
| 142 | return u64{0}; | 147 | *out_config = u64{0}; |
| 148 | return ResultSuccess; | ||
| 143 | case ConfigItem::ExosphereAllowCalWrites: | 149 | case ConfigItem::ExosphereAllowCalWrites: |
| 144 | // Get whether this unit should allow writing to the calibration partition. | 150 | // Get whether this unit should allow writing to the calibration partition. |
| 145 | return u64{0}; | 151 | *out_config = u64{0}; |
| 152 | return ResultSuccess; | ||
| 146 | case ConfigItem::ExosphereEmummcType: | 153 | case ConfigItem::ExosphereEmummcType: |
| 147 | // Get what kind of emummc this unit has active. | 154 | // Get what kind of emummc this unit has active. |
| 148 | return u64{0}; | 155 | *out_config = u64{0}; |
| 156 | return ResultSuccess; | ||
| 149 | case ConfigItem::ExospherePayloadAddress: | 157 | case ConfigItem::ExospherePayloadAddress: |
| 150 | // Gets the physical address of the reboot payload buffer, if one exists. | 158 | // Gets the physical address of the reboot payload buffer, if one exists. |
| 151 | return ResultSecureMonitorNotInitialized; | 159 | return ResultSecureMonitorNotInitialized; |
| 152 | case ConfigItem::ExosphereLogConfiguration: | 160 | case ConfigItem::ExosphereLogConfiguration: |
| 153 | // Get the log configuration. | 161 | // Get the log configuration. |
| 154 | return u64{0}; | 162 | *out_config = u64{0}; |
| 163 | return ResultSuccess; | ||
| 155 | case ConfigItem::ExosphereForceEnableUsb30: | 164 | case ConfigItem::ExosphereForceEnableUsb30: |
| 156 | // Get whether usb 3.0 should be force-enabled. | 165 | // Get whether usb 3.0 should be force-enabled. |
| 157 | return u64{0}; | 166 | *out_config = u64{0}; |
| 167 | return ResultSuccess; | ||
| 158 | default: | 168 | default: |
| 159 | return ResultSecureMonitorInvalidArgument; | 169 | return ResultSecureMonitorInvalidArgument; |
| 160 | } | 170 | } |
diff --git a/src/core/hle/service/spl/spl_module.h b/src/core/hle/service/spl/spl_module.h index e074e115d..06dcffa6c 100644 --- a/src/core/hle/service/spl/spl_module.h +++ b/src/core/hle/service/spl/spl_module.h | |||
| @@ -35,7 +35,7 @@ public: | |||
| 35 | std::shared_ptr<Module> module; | 35 | std::shared_ptr<Module> module; |
| 36 | 36 | ||
| 37 | private: | 37 | private: |
| 38 | ResultVal<u64> GetConfigImpl(ConfigItem config_item) const; | 38 | Result GetConfigImpl(u64* out_config, ConfigItem config_item) const; |
| 39 | 39 | ||
| 40 | std::mt19937 rng; | 40 | std::mt19937 rng; |
| 41 | }; | 41 | }; |
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 9c96f9763..2cba9e5c9 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include "common/string_util.h" | 4 | #include "common/string_util.h" |
| 5 | 5 | ||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/result.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | 8 | #include "core/hle/service/ipc_helpers.h" |
| 8 | #include "core/hle/service/server_manager.h" | 9 | #include "core/hle/service/server_manager.h" |
| 9 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| @@ -141,12 +142,12 @@ private: | |||
| 141 | bool did_set_host_name = false; | 142 | bool did_set_host_name = false; |
| 142 | bool did_handshake = false; | 143 | bool did_handshake = false; |
| 143 | 144 | ||
| 144 | ResultVal<s32> SetSocketDescriptorImpl(s32 fd) { | 145 | Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { |
| 145 | LOG_DEBUG(Service_SSL, "called, fd={}", fd); | 146 | LOG_DEBUG(Service_SSL, "called, fd={}", fd); |
| 146 | ASSERT(!did_handshake); | 147 | ASSERT(!did_handshake); |
| 147 | auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u"); | 148 | auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u"); |
| 148 | ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; }); | 149 | ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; }); |
| 149 | s32 ret_fd; | 150 | |
| 150 | // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor | 151 | // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor |
| 151 | if (do_not_close_socket) { | 152 | if (do_not_close_socket) { |
| 152 | auto res = bsd->DuplicateSocketImpl(fd); | 153 | auto res = bsd->DuplicateSocketImpl(fd); |
| @@ -156,9 +157,9 @@ private: | |||
| 156 | } | 157 | } |
| 157 | fd = *res; | 158 | fd = *res; |
| 158 | fd_to_close = fd; | 159 | fd_to_close = fd; |
| 159 | ret_fd = fd; | 160 | *out_fd = fd; |
| 160 | } else { | 161 | } else { |
| 161 | ret_fd = -1; | 162 | *out_fd = -1; |
| 162 | } | 163 | } |
| 163 | std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd); | 164 | std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd); |
| 164 | if (!sock.has_value()) { | 165 | if (!sock.has_value()) { |
| @@ -167,7 +168,7 @@ private: | |||
| 167 | } | 168 | } |
| 168 | socket = std::move(*sock); | 169 | socket = std::move(*sock); |
| 169 | backend->SetSocket(socket); | 170 | backend->SetSocket(socket); |
| 170 | return ret_fd; | 171 | return ResultSuccess; |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 173 | Result SetHostNameImpl(const std::string& hostname) { | 174 | Result SetHostNameImpl(const std::string& hostname) { |
| @@ -247,34 +248,36 @@ private: | |||
| 247 | return ret; | 248 | return ret; |
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | ResultVal<std::vector<u8>> ReadImpl(size_t size) { | 251 | Result ReadImpl(std::vector<u8>* out_data, size_t size) { |
| 251 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); | 252 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); |
| 252 | std::vector<u8> res(size); | 253 | size_t actual_size{}; |
| 253 | ResultVal<size_t> actual = backend->Read(res); | 254 | Result res = backend->Read(&actual_size, *out_data); |
| 254 | if (actual.Failed()) { | 255 | if (res != ResultSuccess) { |
| 255 | return actual.Code(); | 256 | return res; |
| 256 | } | 257 | } |
| 257 | res.resize(*actual); | 258 | out_data->resize(actual_size); |
| 258 | return res; | 259 | return res; |
| 259 | } | 260 | } |
| 260 | 261 | ||
| 261 | ResultVal<size_t> WriteImpl(std::span<const u8> data) { | 262 | Result WriteImpl(size_t* out_size, std::span<const u8> data) { |
| 262 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); | 263 | ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); |
| 263 | return backend->Write(data); | 264 | return backend->Write(out_size, data); |
| 264 | } | 265 | } |
| 265 | 266 | ||
| 266 | ResultVal<s32> PendingImpl() { | 267 | Result PendingImpl(s32* out_pending) { |
| 267 | LOG_WARNING(Service_SSL, "(STUBBED) called."); | 268 | LOG_WARNING(Service_SSL, "(STUBBED) called."); |
| 268 | return 0; | 269 | *out_pending = 0; |
| 270 | return ResultSuccess; | ||
| 269 | } | 271 | } |
| 270 | 272 | ||
| 271 | void SetSocketDescriptor(HLERequestContext& ctx) { | 273 | void SetSocketDescriptor(HLERequestContext& ctx) { |
| 272 | IPC::RequestParser rp{ctx}; | 274 | IPC::RequestParser rp{ctx}; |
| 273 | const s32 fd = rp.Pop<s32>(); | 275 | const s32 in_fd = rp.Pop<s32>(); |
| 274 | const ResultVal<s32> res = SetSocketDescriptorImpl(fd); | 276 | s32 out_fd{-1}; |
| 277 | const Result res = SetSocketDescriptorImpl(&out_fd, in_fd); | ||
| 275 | IPC::ResponseBuilder rb{ctx, 3}; | 278 | IPC::ResponseBuilder rb{ctx, 3}; |
| 276 | rb.Push(res.Code()); | 279 | rb.Push(res); |
| 277 | rb.Push<s32>(res.ValueOr(-1)); | 280 | rb.Push<s32>(out_fd); |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 280 | void SetHostName(HLERequestContext& ctx) { | 283 | void SetHostName(HLERequestContext& ctx) { |
| @@ -313,14 +316,15 @@ private: | |||
| 313 | }; | 316 | }; |
| 314 | static_assert(sizeof(OutputParameters) == 0x8); | 317 | static_assert(sizeof(OutputParameters) == 0x8); |
| 315 | 318 | ||
| 316 | const Result res = DoHandshakeImpl(); | 319 | Result res = DoHandshakeImpl(); |
| 317 | OutputParameters out{}; | 320 | OutputParameters out{}; |
| 318 | if (res == ResultSuccess) { | 321 | if (res == ResultSuccess) { |
| 319 | auto certs = backend->GetServerCerts(); | 322 | std::vector<std::vector<u8>> certs; |
| 320 | if (certs.Succeeded()) { | 323 | res = backend->GetServerCerts(&certs); |
| 321 | const std::vector<u8> certs_buf = SerializeServerCerts(*certs); | 324 | if (res == ResultSuccess) { |
| 325 | const std::vector<u8> certs_buf = SerializeServerCerts(certs); | ||
| 322 | ctx.WriteBuffer(certs_buf); | 326 | ctx.WriteBuffer(certs_buf); |
| 323 | out.certs_count = static_cast<u32>(certs->size()); | 327 | out.certs_count = static_cast<u32>(certs.size()); |
| 324 | out.certs_size = static_cast<u32>(certs_buf.size()); | 328 | out.certs_size = static_cast<u32>(certs_buf.size()); |
| 325 | } | 329 | } |
| 326 | } | 330 | } |
| @@ -330,29 +334,32 @@ private: | |||
| 330 | } | 334 | } |
| 331 | 335 | ||
| 332 | void Read(HLERequestContext& ctx) { | 336 | void Read(HLERequestContext& ctx) { |
| 333 | const ResultVal<std::vector<u8>> res = ReadImpl(ctx.GetWriteBufferSize()); | 337 | std::vector<u8> output_bytes; |
| 338 | const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize()); | ||
| 334 | IPC::ResponseBuilder rb{ctx, 3}; | 339 | IPC::ResponseBuilder rb{ctx, 3}; |
| 335 | rb.Push(res.Code()); | 340 | rb.Push(res); |
| 336 | if (res.Succeeded()) { | 341 | if (res == ResultSuccess) { |
| 337 | rb.Push(static_cast<u32>(res->size())); | 342 | rb.Push(static_cast<u32>(output_bytes.size())); |
| 338 | ctx.WriteBuffer(*res); | 343 | ctx.WriteBuffer(output_bytes); |
| 339 | } else { | 344 | } else { |
| 340 | rb.Push(static_cast<u32>(0)); | 345 | rb.Push(static_cast<u32>(0)); |
| 341 | } | 346 | } |
| 342 | } | 347 | } |
| 343 | 348 | ||
| 344 | void Write(HLERequestContext& ctx) { | 349 | void Write(HLERequestContext& ctx) { |
| 345 | const ResultVal<size_t> res = WriteImpl(ctx.ReadBuffer()); | 350 | size_t write_size{0}; |
| 351 | const Result res = WriteImpl(&write_size, ctx.ReadBuffer()); | ||
| 346 | IPC::ResponseBuilder rb{ctx, 3}; | 352 | IPC::ResponseBuilder rb{ctx, 3}; |
| 347 | rb.Push(res.Code()); | 353 | rb.Push(res); |
| 348 | rb.Push(static_cast<u32>(res.ValueOr(0))); | 354 | rb.Push(static_cast<u32>(write_size)); |
| 349 | } | 355 | } |
| 350 | 356 | ||
| 351 | void Pending(HLERequestContext& ctx) { | 357 | void Pending(HLERequestContext& ctx) { |
| 352 | const ResultVal<s32> res = PendingImpl(); | 358 | s32 pending_size{0}; |
| 359 | const Result res = PendingImpl(&pending_size); | ||
| 353 | IPC::ResponseBuilder rb{ctx, 3}; | 360 | IPC::ResponseBuilder rb{ctx, 3}; |
| 354 | rb.Push(res.Code()); | 361 | rb.Push(res); |
| 355 | rb.Push<s32>(res.ValueOr(0)); | 362 | rb.Push<s32>(pending_size); |
| 356 | } | 363 | } |
| 357 | 364 | ||
| 358 | void SetSessionCacheMode(HLERequestContext& ctx) { | 365 | void SetSessionCacheMode(HLERequestContext& ctx) { |
| @@ -438,13 +445,14 @@ private: | |||
| 438 | void CreateConnection(HLERequestContext& ctx) { | 445 | void CreateConnection(HLERequestContext& ctx) { |
| 439 | LOG_WARNING(Service_SSL, "called"); | 446 | LOG_WARNING(Service_SSL, "called"); |
| 440 | 447 | ||
| 441 | auto backend_res = CreateSSLConnectionBackend(); | 448 | std::unique_ptr<SSLConnectionBackend> backend; |
| 449 | const Result res = CreateSSLConnectionBackend(&backend); | ||
| 442 | 450 | ||
| 443 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 451 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 444 | rb.Push(backend_res.Code()); | 452 | rb.Push(res); |
| 445 | if (backend_res.Succeeded()) { | 453 | if (res == ResultSuccess) { |
| 446 | rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data, | 454 | rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data, |
| 447 | std::move(*backend_res)); | 455 | std::move(backend)); |
| 448 | } | 456 | } |
| 449 | } | 457 | } |
| 450 | 458 | ||
diff --git a/src/core/hle/service/ssl/ssl_backend.h b/src/core/hle/service/ssl/ssl_backend.h index 409f4367c..a2ec8e694 100644 --- a/src/core/hle/service/ssl/ssl_backend.h +++ b/src/core/hle/service/ssl/ssl_backend.h | |||
| @@ -35,11 +35,11 @@ public: | |||
| 35 | virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0; | 35 | virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0; |
| 36 | virtual Result SetHostName(const std::string& hostname) = 0; | 36 | virtual Result SetHostName(const std::string& hostname) = 0; |
| 37 | virtual Result DoHandshake() = 0; | 37 | virtual Result DoHandshake() = 0; |
| 38 | virtual ResultVal<size_t> Read(std::span<u8> data) = 0; | 38 | virtual Result Read(size_t* out_size, std::span<u8> data) = 0; |
| 39 | virtual ResultVal<size_t> Write(std::span<const u8> data) = 0; | 39 | virtual Result Write(size_t* out_size, std::span<const u8> data) = 0; |
| 40 | virtual ResultVal<std::vector<std::vector<u8>>> GetServerCerts() = 0; | 40 | virtual Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) = 0; |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend(); | 43 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend); |
| 44 | 44 | ||
| 45 | } // namespace Service::SSL | 45 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/ssl/ssl_backend_none.cpp b/src/core/hle/service/ssl/ssl_backend_none.cpp index 2f4f23c42..a7fafd0a3 100644 --- a/src/core/hle/service/ssl/ssl_backend_none.cpp +++ b/src/core/hle/service/ssl/ssl_backend_none.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | namespace Service::SSL { | 8 | namespace Service::SSL { |
| 9 | 9 | ||
| 10 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 10 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 11 | LOG_ERROR(Service_SSL, | 11 | LOG_ERROR(Service_SSL, |
| 12 | "Can't create SSL connection because no SSL backend is available on this platform"); | 12 | "Can't create SSL connection because no SSL backend is available on this platform"); |
| 13 | return ResultInternalError; | 13 | return ResultInternalError; |
diff --git a/src/core/hle/service/ssl/ssl_backend_openssl.cpp b/src/core/hle/service/ssl/ssl_backend_openssl.cpp index 6ca869dbf..b2dd37cd4 100644 --- a/src/core/hle/service/ssl/ssl_backend_openssl.cpp +++ b/src/core/hle/service/ssl/ssl_backend_openssl.cpp | |||
| @@ -105,31 +105,30 @@ public: | |||
| 105 | return ResultInternalError; | 105 | return ResultInternalError; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | return HandleReturn("SSL_do_handshake", 0, ret).Code(); | 108 | return HandleReturn("SSL_do_handshake", 0, ret); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | ResultVal<size_t> Read(std::span<u8> data) override { | 111 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 112 | size_t actual; | 112 | const int ret = SSL_read_ex(ssl, data.data(), data.size(), out_size); |
| 113 | const int ret = SSL_read_ex(ssl, data.data(), data.size(), &actual); | 113 | return HandleReturn("SSL_read_ex", out_size, ret); |
| 114 | return HandleReturn("SSL_read_ex", actual, ret); | ||
| 115 | } | 114 | } |
| 116 | 115 | ||
| 117 | ResultVal<size_t> Write(std::span<const u8> data) override { | 116 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 118 | size_t actual; | 117 | const int ret = SSL_write_ex(ssl, data.data(), data.size(), out_size); |
| 119 | const int ret = SSL_write_ex(ssl, data.data(), data.size(), &actual); | 118 | return HandleReturn("SSL_write_ex", out_size, ret); |
| 120 | return HandleReturn("SSL_write_ex", actual, ret); | ||
| 121 | } | 119 | } |
| 122 | 120 | ||
| 123 | ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) { | 121 | Result HandleReturn(const char* what, size_t* actual, int ret) { |
| 124 | const int ssl_err = SSL_get_error(ssl, ret); | 122 | const int ssl_err = SSL_get_error(ssl, ret); |
| 125 | CheckOpenSSLErrors(); | 123 | CheckOpenSSLErrors(); |
| 126 | switch (ssl_err) { | 124 | switch (ssl_err) { |
| 127 | case SSL_ERROR_NONE: | 125 | case SSL_ERROR_NONE: |
| 128 | return actual; | 126 | return ResultSuccess; |
| 129 | case SSL_ERROR_ZERO_RETURN: | 127 | case SSL_ERROR_ZERO_RETURN: |
| 130 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what); | 128 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what); |
| 131 | // DoHandshake special-cases this, but for Read and Write: | 129 | // DoHandshake special-cases this, but for Read and Write: |
| 132 | return size_t(0); | 130 | *actual = 0; |
| 131 | return ResultSuccess; | ||
| 133 | case SSL_ERROR_WANT_READ: | 132 | case SSL_ERROR_WANT_READ: |
| 134 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what); | 133 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what); |
| 135 | return ResultWouldBlock; | 134 | return ResultWouldBlock; |
| @@ -139,20 +138,20 @@ public: | |||
| 139 | default: | 138 | default: |
| 140 | if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) { | 139 | if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) { |
| 141 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what); | 140 | LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what); |
| 142 | return size_t(0); | 141 | *actual = 0; |
| 142 | return ResultSuccess; | ||
| 143 | } | 143 | } |
| 144 | LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err); | 144 | LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err); |
| 145 | return ResultInternalError; | 145 | return ResultInternalError; |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 149 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 150 | STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); | 150 | STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); |
| 151 | if (!chain) { | 151 | if (!chain) { |
| 152 | LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr"); | 152 | LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr"); |
| 153 | return ResultInternalError; | 153 | return ResultInternalError; |
| 154 | } | 154 | } |
| 155 | std::vector<std::vector<u8>> ret; | ||
| 156 | int count = sk_X509_num(chain); | 155 | int count = sk_X509_num(chain); |
| 157 | ASSERT(count >= 0); | 156 | ASSERT(count >= 0); |
| 158 | for (int i = 0; i < count; i++) { | 157 | for (int i = 0; i < count; i++) { |
| @@ -161,10 +160,10 @@ public: | |||
| 161 | unsigned char* buf = nullptr; | 160 | unsigned char* buf = nullptr; |
| 162 | int len = i2d_X509(x509, &buf); | 161 | int len = i2d_X509(x509, &buf); |
| 163 | ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; }); | 162 | ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; }); |
| 164 | ret.emplace_back(buf, buf + len); | 163 | out_certs->emplace_back(buf, buf + len); |
| 165 | OPENSSL_free(buf); | 164 | OPENSSL_free(buf); |
| 166 | } | 165 | } |
| 167 | return ret; | 166 | return ResultSuccess; |
| 168 | } | 167 | } |
| 169 | 168 | ||
| 170 | ~SSLConnectionBackendOpenSSL() { | 169 | ~SSLConnectionBackendOpenSSL() { |
| @@ -253,13 +252,13 @@ public: | |||
| 253 | std::shared_ptr<Network::SocketBase> socket; | 252 | std::shared_ptr<Network::SocketBase> socket; |
| 254 | }; | 253 | }; |
| 255 | 254 | ||
| 256 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 255 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 257 | auto conn = std::make_unique<SSLConnectionBackendOpenSSL>(); | 256 | auto conn = std::make_unique<SSLConnectionBackendOpenSSL>(); |
| 258 | const Result res = conn->Init(); | 257 | |
| 259 | if (res.IsFailure()) { | 258 | R_TRY(conn->Init()); |
| 260 | return res; | 259 | |
| 261 | } | 260 | *out_backend = std::move(conn); |
| 262 | return conn; | 261 | return ResultSuccess; |
| 263 | } | 262 | } |
| 264 | 263 | ||
| 265 | namespace { | 264 | namespace { |
diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp index d8074339a..bda12b761 100644 --- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp +++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp | |||
| @@ -299,21 +299,22 @@ public: | |||
| 299 | return ResultSuccess; | 299 | return ResultSuccess; |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | ResultVal<size_t> Read(std::span<u8> data) override { | 302 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 303 | *out_size = 0; | ||
| 303 | if (handshake_state != HandshakeState::Connected) { | 304 | if (handshake_state != HandshakeState::Connected) { |
| 304 | LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); | 305 | LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); |
| 305 | return ResultInternalError; | 306 | return ResultInternalError; |
| 306 | } | 307 | } |
| 307 | if (data.size() == 0 || got_read_eof) { | 308 | if (data.size() == 0 || got_read_eof) { |
| 308 | return size_t(0); | 309 | return ResultSuccess; |
| 309 | } | 310 | } |
| 310 | while (1) { | 311 | while (1) { |
| 311 | if (!cleartext_read_buf.empty()) { | 312 | if (!cleartext_read_buf.empty()) { |
| 312 | const size_t read_size = std::min(cleartext_read_buf.size(), data.size()); | 313 | *out_size = std::min(cleartext_read_buf.size(), data.size()); |
| 313 | std::memcpy(data.data(), cleartext_read_buf.data(), read_size); | 314 | std::memcpy(data.data(), cleartext_read_buf.data(), *out_size); |
| 314 | cleartext_read_buf.erase(cleartext_read_buf.begin(), | 315 | cleartext_read_buf.erase(cleartext_read_buf.begin(), |
| 315 | cleartext_read_buf.begin() + read_size); | 316 | cleartext_read_buf.begin() + *out_size); |
| 316 | return read_size; | 317 | return ResultSuccess; |
| 317 | } | 318 | } |
| 318 | if (!ciphertext_read_buf.empty()) { | 319 | if (!ciphertext_read_buf.empty()) { |
| 319 | SecBuffer empty{ | 320 | SecBuffer empty{ |
| @@ -366,7 +367,8 @@ public: | |||
| 366 | case SEC_I_CONTEXT_EXPIRED: | 367 | case SEC_I_CONTEXT_EXPIRED: |
| 367 | // Server hung up by sending close_notify. | 368 | // Server hung up by sending close_notify. |
| 368 | got_read_eof = true; | 369 | got_read_eof = true; |
| 369 | return size_t(0); | 370 | *out_size = 0; |
| 371 | return ResultSuccess; | ||
| 370 | default: | 372 | default: |
| 371 | LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", | 373 | LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", |
| 372 | Common::NativeErrorToString(ret)); | 374 | Common::NativeErrorToString(ret)); |
| @@ -379,18 +381,21 @@ public: | |||
| 379 | } | 381 | } |
| 380 | if (ciphertext_read_buf.empty()) { | 382 | if (ciphertext_read_buf.empty()) { |
| 381 | got_read_eof = true; | 383 | got_read_eof = true; |
| 382 | return size_t(0); | 384 | *out_size = 0; |
| 385 | return ResultSuccess; | ||
| 383 | } | 386 | } |
| 384 | } | 387 | } |
| 385 | } | 388 | } |
| 386 | 389 | ||
| 387 | ResultVal<size_t> Write(std::span<const u8> data) override { | 390 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 391 | *out_size = 0; | ||
| 392 | |||
| 388 | if (handshake_state != HandshakeState::Connected) { | 393 | if (handshake_state != HandshakeState::Connected) { |
| 389 | LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); | 394 | LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); |
| 390 | return ResultInternalError; | 395 | return ResultInternalError; |
| 391 | } | 396 | } |
| 392 | if (data.size() == 0) { | 397 | if (data.size() == 0) { |
| 393 | return size_t(0); | 398 | return ResultSuccess; |
| 394 | } | 399 | } |
| 395 | data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); | 400 | data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); |
| 396 | if (!cleartext_write_buf.empty()) { | 401 | if (!cleartext_write_buf.empty()) { |
| @@ -402,7 +407,7 @@ public: | |||
| 402 | LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); | 407 | LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); |
| 403 | return ResultInternalError; | 408 | return ResultInternalError; |
| 404 | } | 409 | } |
| 405 | return WriteAlreadyEncryptedData(); | 410 | return WriteAlreadyEncryptedData(out_size); |
| 406 | } else { | 411 | } else { |
| 407 | cleartext_write_buf.assign(data.begin(), data.end()); | 412 | cleartext_write_buf.assign(data.begin(), data.end()); |
| 408 | } | 413 | } |
| @@ -448,21 +453,21 @@ public: | |||
| 448 | tmp_data_buf.end()); | 453 | tmp_data_buf.end()); |
| 449 | ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), | 454 | ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), |
| 450 | trailer_buf.end()); | 455 | trailer_buf.end()); |
| 451 | return WriteAlreadyEncryptedData(); | 456 | return WriteAlreadyEncryptedData(out_size); |
| 452 | } | 457 | } |
| 453 | 458 | ||
| 454 | ResultVal<size_t> WriteAlreadyEncryptedData() { | 459 | Result WriteAlreadyEncryptedData(size_t* out_size) { |
| 455 | const Result r = FlushCiphertextWriteBuf(); | 460 | const Result r = FlushCiphertextWriteBuf(); |
| 456 | if (r != ResultSuccess) { | 461 | if (r != ResultSuccess) { |
| 457 | return r; | 462 | return r; |
| 458 | } | 463 | } |
| 459 | // write buf is empty | 464 | // write buf is empty |
| 460 | const size_t cleartext_bytes_written = cleartext_write_buf.size(); | 465 | *out_size = cleartext_write_buf.size(); |
| 461 | cleartext_write_buf.clear(); | 466 | cleartext_write_buf.clear(); |
| 462 | return cleartext_bytes_written; | 467 | return ResultSuccess; |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 470 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 466 | PCCERT_CONTEXT returned_cert = nullptr; | 471 | PCCERT_CONTEXT returned_cert = nullptr; |
| 467 | const SECURITY_STATUS ret = | 472 | const SECURITY_STATUS ret = |
| 468 | QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); | 473 | QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); |
| @@ -473,16 +478,15 @@ public: | |||
| 473 | return ResultInternalError; | 478 | return ResultInternalError; |
| 474 | } | 479 | } |
| 475 | PCCERT_CONTEXT some_cert = nullptr; | 480 | PCCERT_CONTEXT some_cert = nullptr; |
| 476 | std::vector<std::vector<u8>> certs; | ||
| 477 | while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) { | 481 | while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) { |
| 478 | certs.emplace_back(static_cast<u8*>(some_cert->pbCertEncoded), | 482 | out_certs->emplace_back(static_cast<u8*>(some_cert->pbCertEncoded), |
| 479 | static_cast<u8*>(some_cert->pbCertEncoded) + | 483 | static_cast<u8*>(some_cert->pbCertEncoded) + |
| 480 | some_cert->cbCertEncoded); | 484 | some_cert->cbCertEncoded); |
| 481 | } | 485 | } |
| 482 | std::reverse(certs.begin(), | 486 | std::reverse(out_certs->begin(), |
| 483 | certs.end()); // Windows returns certs in reverse order from what we want | 487 | out_certs->end()); // Windows returns certs in reverse order from what we want |
| 484 | CertFreeCertificateContext(returned_cert); | 488 | CertFreeCertificateContext(returned_cert); |
| 485 | return certs; | 489 | return ResultSuccess; |
| 486 | } | 490 | } |
| 487 | 491 | ||
| 488 | ~SSLConnectionBackendSchannel() { | 492 | ~SSLConnectionBackendSchannel() { |
| @@ -532,13 +536,13 @@ public: | |||
| 532 | size_t read_buf_fill_size = 0; | 536 | size_t read_buf_fill_size = 0; |
| 533 | }; | 537 | }; |
| 534 | 538 | ||
| 535 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 539 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 536 | auto conn = std::make_unique<SSLConnectionBackendSchannel>(); | 540 | auto conn = std::make_unique<SSLConnectionBackendSchannel>(); |
| 537 | const Result res = conn->Init(); | 541 | |
| 538 | if (res.IsFailure()) { | 542 | R_TRY(conn->Init()); |
| 539 | return res; | 543 | |
| 540 | } | 544 | *out_backend = std::move(conn); |
| 541 | return conn; | 545 | return ResultSuccess; |
| 542 | } | 546 | } |
| 543 | 547 | ||
| 544 | } // namespace Service::SSL | 548 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/ssl/ssl_backend_securetransport.cpp b/src/core/hle/service/ssl/ssl_backend_securetransport.cpp index b3083cbad..c48914f64 100644 --- a/src/core/hle/service/ssl/ssl_backend_securetransport.cpp +++ b/src/core/hle/service/ssl/ssl_backend_securetransport.cpp | |||
| @@ -100,27 +100,23 @@ public: | |||
| 100 | 100 | ||
| 101 | Result DoHandshake() override { | 101 | Result DoHandshake() override { |
| 102 | OSStatus status = SSLHandshake(context); | 102 | OSStatus status = SSLHandshake(context); |
| 103 | return HandleReturn("SSLHandshake", 0, status).Code(); | 103 | return HandleReturn("SSLHandshake", 0, status); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | ResultVal<size_t> Read(std::span<u8> data) override { | 106 | Result Read(size_t* out_size, std::span<u8> data) override { |
| 107 | size_t actual; | 107 | OSStatus status = SSLRead(context, data.data(), data.size(), out_size); |
| 108 | OSStatus status = SSLRead(context, data.data(), data.size(), &actual); | 108 | return HandleReturn("SSLRead", out_size, status); |
| 109 | ; | ||
| 110 | return HandleReturn("SSLRead", actual, status); | ||
| 111 | } | 109 | } |
| 112 | 110 | ||
| 113 | ResultVal<size_t> Write(std::span<const u8> data) override { | 111 | Result Write(size_t* out_size, std::span<const u8> data) override { |
| 114 | size_t actual; | 112 | OSStatus status = SSLWrite(context, data.data(), data.size(), out_size); |
| 115 | OSStatus status = SSLWrite(context, data.data(), data.size(), &actual); | 113 | return HandleReturn("SSLWrite", out_size, status); |
| 116 | ; | ||
| 117 | return HandleReturn("SSLWrite", actual, status); | ||
| 118 | } | 114 | } |
| 119 | 115 | ||
| 120 | ResultVal<size_t> HandleReturn(const char* what, size_t actual, OSStatus status) { | 116 | Result HandleReturn(const char* what, size_t* actual, OSStatus status) { |
| 121 | switch (status) { | 117 | switch (status) { |
| 122 | case 0: | 118 | case 0: |
| 123 | return actual; | 119 | return ResultSuccess; |
| 124 | case errSSLWouldBlock: | 120 | case errSSLWouldBlock: |
| 125 | return ResultWouldBlock; | 121 | return ResultWouldBlock; |
| 126 | default: { | 122 | default: { |
| @@ -136,22 +132,21 @@ public: | |||
| 136 | } | 132 | } |
| 137 | } | 133 | } |
| 138 | 134 | ||
| 139 | ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { | 135 | Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { |
| 140 | CFReleaser<SecTrustRef> trust; | 136 | CFReleaser<SecTrustRef> trust; |
| 141 | OSStatus status = SSLCopyPeerTrust(context, &trust.ptr); | 137 | OSStatus status = SSLCopyPeerTrust(context, &trust.ptr); |
| 142 | if (status) { | 138 | if (status) { |
| 143 | LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status)); | 139 | LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status)); |
| 144 | return ResultInternalError; | 140 | return ResultInternalError; |
| 145 | } | 141 | } |
| 146 | std::vector<std::vector<u8>> ret; | ||
| 147 | for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) { | 142 | for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) { |
| 148 | SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i); | 143 | SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i); |
| 149 | CFReleaser<CFDataRef> data(SecCertificateCopyData(cert)); | 144 | CFReleaser<CFDataRef> data(SecCertificateCopyData(cert)); |
| 150 | ASSERT_OR_EXECUTE(data, { return ResultInternalError; }); | 145 | ASSERT_OR_EXECUTE(data, { return ResultInternalError; }); |
| 151 | const u8* ptr = CFDataGetBytePtr(data); | 146 | const u8* ptr = CFDataGetBytePtr(data); |
| 152 | ret.emplace_back(ptr, ptr + CFDataGetLength(data)); | 147 | out_certs->emplace_back(ptr, ptr + CFDataGetLength(data)); |
| 153 | } | 148 | } |
| 154 | return ret; | 149 | return ResultSuccess; |
| 155 | } | 150 | } |
| 156 | 151 | ||
| 157 | static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) { | 152 | static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) { |
| @@ -210,13 +205,13 @@ private: | |||
| 210 | std::shared_ptr<Network::SocketBase> socket; | 205 | std::shared_ptr<Network::SocketBase> socket; |
| 211 | }; | 206 | }; |
| 212 | 207 | ||
| 213 | ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { | 208 | Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { |
| 214 | auto conn = std::make_unique<SSLConnectionBackendSecureTransport>(); | 209 | auto conn = std::make_unique<SSLConnectionBackendSecureTransport>(); |
| 215 | const Result res = conn->Init(); | 210 | |
| 216 | if (res.IsFailure()) { | 211 | R_TRY(conn->Init()); |
| 217 | return res; | 212 | |
| 218 | } | 213 | *out_backend = std::move(conn); |
| 219 | return conn; | 214 | return ResultSuccess; |
| 220 | } | 215 | } |
| 221 | 216 | ||
| 222 | } // namespace Service::SSL | 217 | } // namespace Service::SSL |
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 69af2868a..f0b5eff8a 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -58,14 +58,15 @@ const Layer& Display::GetLayer(std::size_t index) const { | |||
| 58 | return *layers.at(index); | 58 | return *layers.at(index); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() { | 61 | Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) { |
| 62 | if (got_vsync_event) { | 62 | if (got_vsync_event) { |
| 63 | return ResultPermissionDenied; | 63 | return ResultPermissionDenied; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | got_vsync_event = true; | 66 | got_vsync_event = true; |
| 67 | 67 | ||
| 68 | return GetVSyncEventUnchecked(); | 68 | *out_vsync_event = GetVSyncEventUnchecked(); |
| 69 | return ResultSuccess; | ||
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { | 72 | Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 3f31d1f32..101cbce20 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -85,7 +85,7 @@ public: | |||
| 85 | * @returns The internal Vsync event if it has not yet been retrieved, | 85 | * @returns The internal Vsync event if it has not yet been retrieved, |
| 86 | * VI::ResultPermissionDenied otherwise. | 86 | * VI::ResultPermissionDenied otherwise. |
| 87 | */ | 87 | */ |
| 88 | [[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent(); | 88 | [[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event); |
| 89 | 89 | ||
| 90 | /// Gets the internal vsync event. | 90 | /// Gets the internal vsync event. |
| 91 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); | 91 | Kernel::KReadableEvent* GetVSyncEventUnchecked(); |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1b193f00c..6bb02393c 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -683,9 +683,9 @@ private: | |||
| 683 | 683 | ||
| 684 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | 684 | LOG_DEBUG(Service_VI, "called. display_id={}", display_id); |
| 685 | 685 | ||
| 686 | const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); | 686 | Kernel::KReadableEvent* vsync_event{}; |
| 687 | if (vsync_event.Failed()) { | 687 | const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id); |
| 688 | const auto result = vsync_event.Code(); | 688 | if (result != ResultSuccess) { |
| 689 | if (result == ResultNotFound) { | 689 | if (result == ResultNotFound) { |
| 690 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | 690 | LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); |
| 691 | } | 691 | } |
| @@ -697,7 +697,7 @@ private: | |||
| 697 | 697 | ||
| 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 698 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 699 | rb.Push(ResultSuccess); | 699 | rb.Push(ResultSuccess); |
| 700 | rb.PushCopyObjects(*vsync_event); | 700 | rb.PushCopyObjects(vsync_event); |
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | void ConvertScalingMode(HLERequestContext& ctx) { | 703 | void ConvertScalingMode(HLERequestContext& ctx) { |
| @@ -705,15 +705,16 @@ private: | |||
| 705 | const auto mode = rp.PopEnum<NintendoScaleMode>(); | 705 | const auto mode = rp.PopEnum<NintendoScaleMode>(); |
| 706 | LOG_DEBUG(Service_VI, "called mode={}", mode); | 706 | LOG_DEBUG(Service_VI, "called mode={}", mode); |
| 707 | 707 | ||
| 708 | const auto converted_mode = ConvertScalingModeImpl(mode); | 708 | ConvertedScaleMode converted_mode{}; |
| 709 | const auto result = ConvertScalingModeImpl(&converted_mode, mode); | ||
| 709 | 710 | ||
| 710 | if (converted_mode.Succeeded()) { | 711 | if (result == ResultSuccess) { |
| 711 | IPC::ResponseBuilder rb{ctx, 4}; | 712 | IPC::ResponseBuilder rb{ctx, 4}; |
| 712 | rb.Push(ResultSuccess); | 713 | rb.Push(ResultSuccess); |
| 713 | rb.PushEnum(*converted_mode); | 714 | rb.PushEnum(converted_mode); |
| 714 | } else { | 715 | } else { |
| 715 | IPC::ResponseBuilder rb{ctx, 2}; | 716 | IPC::ResponseBuilder rb{ctx, 2}; |
| 716 | rb.Push(converted_mode.Code()); | 717 | rb.Push(result); |
| 717 | } | 718 | } |
| 718 | } | 719 | } |
| 719 | 720 | ||
| @@ -760,18 +761,24 @@ private: | |||
| 760 | rb.Push(alignment); | 761 | rb.Push(alignment); |
| 761 | } | 762 | } |
| 762 | 763 | ||
| 763 | static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) { | 764 | static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, |
| 765 | NintendoScaleMode mode) { | ||
| 764 | switch (mode) { | 766 | switch (mode) { |
| 765 | case NintendoScaleMode::None: | 767 | case NintendoScaleMode::None: |
| 766 | return ConvertedScaleMode::None; | 768 | *out_scaling_mode = ConvertedScaleMode::None; |
| 769 | return ResultSuccess; | ||
| 767 | case NintendoScaleMode::Freeze: | 770 | case NintendoScaleMode::Freeze: |
| 768 | return ConvertedScaleMode::Freeze; | 771 | *out_scaling_mode = ConvertedScaleMode::Freeze; |
| 772 | return ResultSuccess; | ||
| 769 | case NintendoScaleMode::ScaleToWindow: | 773 | case NintendoScaleMode::ScaleToWindow: |
| 770 | return ConvertedScaleMode::ScaleToWindow; | 774 | *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; |
| 775 | return ResultSuccess; | ||
| 771 | case NintendoScaleMode::ScaleAndCrop: | 776 | case NintendoScaleMode::ScaleAndCrop: |
| 772 | return ConvertedScaleMode::ScaleAndCrop; | 777 | *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; |
| 778 | return ResultSuccess; | ||
| 773 | case NintendoScaleMode::PreserveAspectRatio: | 779 | case NintendoScaleMode::PreserveAspectRatio: |
| 774 | return ConvertedScaleMode::PreserveAspectRatio; | 780 | *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; |
| 781 | return ResultSuccess; | ||
| 775 | default: | 782 | default: |
| 776 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | 783 | LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); |
| 777 | return ResultOperationFailed; | 784 | return ResultOperationFailed; |
diff --git a/src/core/memory.h b/src/core/memory.h index 2eb61ffd3..13047a545 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -509,9 +509,9 @@ class GuestMemory { | |||
| 509 | 509 | ||
| 510 | public: | 510 | public: |
| 511 | GuestMemory() = delete; | 511 | GuestMemory() = delete; |
| 512 | explicit GuestMemory(M& memory_, u64 addr_, std::size_t size_, | 512 | explicit GuestMemory(M& memory, u64 addr, std::size_t size, |
| 513 | Common::ScratchBuffer<T>* backup = nullptr) | 513 | Common::ScratchBuffer<T>* backup = nullptr) |
| 514 | : memory{memory_}, addr{addr_}, size{size_} { | 514 | : m_memory{memory}, m_addr{addr}, m_size{size} { |
| 515 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); | 515 | static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write); |
| 516 | if constexpr (FLAGS & GuestMemoryFlags::Read) { | 516 | if constexpr (FLAGS & GuestMemoryFlags::Read) { |
| 517 | Read(addr, size, backup); | 517 | Read(addr, size, backup); |
| @@ -521,89 +521,97 @@ public: | |||
| 521 | ~GuestMemory() = default; | 521 | ~GuestMemory() = default; |
| 522 | 522 | ||
| 523 | T* data() noexcept { | 523 | T* data() noexcept { |
| 524 | return data_span.data(); | 524 | return m_data_span.data(); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | const T* data() const noexcept { | 527 | const T* data() const noexcept { |
| 528 | return data_span.data(); | 528 | return m_data_span.data(); |
| 529 | } | ||
| 530 | |||
| 531 | size_t size() const noexcept { | ||
| 532 | return m_size; | ||
| 533 | } | ||
| 534 | |||
| 535 | size_t size_bytes() const noexcept { | ||
| 536 | return this->size() * sizeof(T); | ||
| 529 | } | 537 | } |
| 530 | 538 | ||
| 531 | [[nodiscard]] T* begin() noexcept { | 539 | [[nodiscard]] T* begin() noexcept { |
| 532 | return data(); | 540 | return this->data(); |
| 533 | } | 541 | } |
| 534 | 542 | ||
| 535 | [[nodiscard]] const T* begin() const noexcept { | 543 | [[nodiscard]] const T* begin() const noexcept { |
| 536 | return data(); | 544 | return this->data(); |
| 537 | } | 545 | } |
| 538 | 546 | ||
| 539 | [[nodiscard]] T* end() noexcept { | 547 | [[nodiscard]] T* end() noexcept { |
| 540 | return data() + size; | 548 | return this->data() + this->size(); |
| 541 | } | 549 | } |
| 542 | 550 | ||
| 543 | [[nodiscard]] const T* end() const noexcept { | 551 | [[nodiscard]] const T* end() const noexcept { |
| 544 | return data() + size; | 552 | return this->data() + this->size(); |
| 545 | } | 553 | } |
| 546 | 554 | ||
| 547 | T& operator[](size_t index) noexcept { | 555 | T& operator[](size_t index) noexcept { |
| 548 | return data_span[index]; | 556 | return m_data_span[index]; |
| 549 | } | 557 | } |
| 550 | 558 | ||
| 551 | const T& operator[](size_t index) const noexcept { | 559 | const T& operator[](size_t index) const noexcept { |
| 552 | return data_span[index]; | 560 | return m_data_span[index]; |
| 553 | } | 561 | } |
| 554 | 562 | ||
| 555 | void SetAddressAndSize(u64 addr_, std::size_t size_) noexcept { | 563 | void SetAddressAndSize(u64 addr, std::size_t size) noexcept { |
| 556 | addr = addr_; | 564 | m_addr = addr; |
| 557 | size = size_; | 565 | m_size = size; |
| 558 | addr_changed = true; | 566 | m_addr_changed = true; |
| 559 | } | 567 | } |
| 560 | 568 | ||
| 561 | std::span<T> Read(u64 addr_, std::size_t size_, | 569 | std::span<T> Read(u64 addr, std::size_t size, |
| 562 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { | 570 | Common::ScratchBuffer<T>* backup = nullptr) noexcept { |
| 563 | addr = addr_; | 571 | m_addr = addr; |
| 564 | size = size_; | 572 | m_size = size; |
| 565 | if (size == 0) { | 573 | if (m_size == 0) { |
| 566 | is_data_copy = true; | 574 | m_is_data_copy = true; |
| 567 | return {}; | 575 | return {}; |
| 568 | } | 576 | } |
| 569 | 577 | ||
| 570 | if (TrySetSpan()) { | 578 | if (this->TrySetSpan()) { |
| 571 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 579 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 572 | memory.FlushRegion(addr, size * sizeof(T)); | 580 | m_memory.FlushRegion(m_addr, this->size_bytes()); |
| 573 | } | 581 | } |
| 574 | } else { | 582 | } else { |
| 575 | if (backup) { | 583 | if (backup) { |
| 576 | backup->resize_destructive(size); | 584 | backup->resize_destructive(this->size()); |
| 577 | data_span = *backup; | 585 | m_data_span = *backup; |
| 578 | } else { | 586 | } else { |
| 579 | data_copy.resize(size); | 587 | m_data_copy.resize(this->size()); |
| 580 | data_span = std::span(data_copy); | 588 | m_data_span = std::span(m_data_copy); |
| 581 | } | 589 | } |
| 582 | is_data_copy = true; | 590 | m_is_data_copy = true; |
| 583 | span_valid = true; | 591 | m_span_valid = true; |
| 584 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 592 | if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 585 | memory.ReadBlock(addr, data_span.data(), size * sizeof(T)); | 593 | m_memory.ReadBlock(m_addr, this->data(), this->size_bytes()); |
| 586 | } else { | 594 | } else { |
| 587 | memory.ReadBlockUnsafe(addr, data_span.data(), size * sizeof(T)); | 595 | m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes()); |
| 588 | } | 596 | } |
| 589 | } | 597 | } |
| 590 | return data_span; | 598 | return m_data_span; |
| 591 | } | 599 | } |
| 592 | 600 | ||
| 593 | void Write(std::span<T> write_data) noexcept { | 601 | void Write(std::span<T> write_data) noexcept { |
| 594 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | 602 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { |
| 595 | memory.WriteBlockCached(addr, write_data.data(), size * sizeof(T)); | 603 | m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes()); |
| 596 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 604 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 597 | memory.WriteBlock(addr, write_data.data(), size * sizeof(T)); | 605 | m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes()); |
| 598 | } else { | 606 | } else { |
| 599 | memory.WriteBlockUnsafe(addr, write_data.data(), size * sizeof(T)); | 607 | m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes()); |
| 600 | } | 608 | } |
| 601 | } | 609 | } |
| 602 | 610 | ||
| 603 | bool TrySetSpan() noexcept { | 611 | bool TrySetSpan() noexcept { |
| 604 | if (u8* ptr = memory.GetSpan(addr, size * sizeof(T)); ptr) { | 612 | if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) { |
| 605 | data_span = {reinterpret_cast<T*>(ptr), size}; | 613 | m_data_span = {reinterpret_cast<T*>(ptr), this->size()}; |
| 606 | span_valid = true; | 614 | m_span_valid = true; |
| 607 | return true; | 615 | return true; |
| 608 | } | 616 | } |
| 609 | return false; | 617 | return false; |
| @@ -611,36 +619,36 @@ public: | |||
| 611 | 619 | ||
| 612 | protected: | 620 | protected: |
| 613 | bool IsDataCopy() const noexcept { | 621 | bool IsDataCopy() const noexcept { |
| 614 | return is_data_copy; | 622 | return m_is_data_copy; |
| 615 | } | 623 | } |
| 616 | 624 | ||
| 617 | bool AddressChanged() const noexcept { | 625 | bool AddressChanged() const noexcept { |
| 618 | return addr_changed; | 626 | return m_addr_changed; |
| 619 | } | 627 | } |
| 620 | 628 | ||
| 621 | M& memory; | 629 | M& m_memory; |
| 622 | u64 addr; | 630 | u64 m_addr{}; |
| 623 | size_t size; | 631 | size_t m_size{}; |
| 624 | std::span<T> data_span{}; | 632 | std::span<T> m_data_span{}; |
| 625 | std::vector<T> data_copy; | 633 | std::vector<T> m_data_copy{}; |
| 626 | bool span_valid{false}; | 634 | bool m_span_valid{false}; |
| 627 | bool is_data_copy{false}; | 635 | bool m_is_data_copy{false}; |
| 628 | bool addr_changed{false}; | 636 | bool m_addr_changed{false}; |
| 629 | }; | 637 | }; |
| 630 | 638 | ||
| 631 | template <typename M, typename T, GuestMemoryFlags FLAGS> | 639 | template <typename M, typename T, GuestMemoryFlags FLAGS> |
| 632 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { | 640 | class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> { |
| 633 | public: | 641 | public: |
| 634 | GuestMemoryScoped() = delete; | 642 | GuestMemoryScoped() = delete; |
| 635 | explicit GuestMemoryScoped(M& memory_, u64 addr_, std::size_t size_, | 643 | explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size, |
| 636 | Common::ScratchBuffer<T>* backup = nullptr) | 644 | Common::ScratchBuffer<T>* backup = nullptr) |
| 637 | : GuestMemory<M, T, FLAGS>(memory_, addr_, size_, backup) { | 645 | : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) { |
| 638 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { | 646 | if constexpr (!(FLAGS & GuestMemoryFlags::Read)) { |
| 639 | if (!this->TrySetSpan()) { | 647 | if (!this->TrySetSpan()) { |
| 640 | if (backup) { | 648 | if (backup) { |
| 641 | this->data_span = *backup; | 649 | this->m_data_span = *backup; |
| 642 | this->span_valid = true; | 650 | this->m_span_valid = true; |
| 643 | this->is_data_copy = true; | 651 | this->m_is_data_copy = true; |
| 644 | } | 652 | } |
| 645 | } | 653 | } |
| 646 | } | 654 | } |
| @@ -648,24 +656,21 @@ public: | |||
| 648 | 656 | ||
| 649 | ~GuestMemoryScoped() { | 657 | ~GuestMemoryScoped() { |
| 650 | if constexpr (FLAGS & GuestMemoryFlags::Write) { | 658 | if constexpr (FLAGS & GuestMemoryFlags::Write) { |
| 651 | if (this->size == 0) [[unlikely]] { | 659 | if (this->size() == 0) [[unlikely]] { |
| 652 | return; | 660 | return; |
| 653 | } | 661 | } |
| 654 | 662 | ||
| 655 | if (this->AddressChanged() || this->IsDataCopy()) { | 663 | if (this->AddressChanged() || this->IsDataCopy()) { |
| 656 | ASSERT(this->span_valid); | 664 | ASSERT(this->m_span_valid); |
| 657 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { | 665 | if constexpr (FLAGS & GuestMemoryFlags::Cached) { |
| 658 | this->memory.WriteBlockCached(this->addr, this->data_span.data(), | 666 | this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes()); |
| 659 | this->size * sizeof(T)); | ||
| 660 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 667 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 661 | this->memory.WriteBlock(this->addr, this->data_span.data(), | 668 | this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes()); |
| 662 | this->size * sizeof(T)); | ||
| 663 | } else { | 669 | } else { |
| 664 | this->memory.WriteBlockUnsafe(this->addr, this->data_span.data(), | 670 | this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes()); |
| 665 | this->size * sizeof(T)); | ||
| 666 | } | 671 | } |
| 667 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { | 672 | } else if constexpr (FLAGS & GuestMemoryFlags::Safe) { |
| 668 | this->memory.InvalidateRegion(this->addr, this->size * sizeof(T)); | 673 | this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes()); |
| 669 | } | 674 | } |
| 670 | } | 675 | } |
| 671 | } | 676 | } |
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 26e8307c1..15285ab0a 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h | |||
| @@ -39,7 +39,7 @@ public: | |||
| 39 | [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank, | 39 | [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank, |
| 40 | u32 offset) = 0; | 40 | u32 offset) = 0; |
| 41 | 41 | ||
| 42 | virtual void Dump(u64 hash) = 0; | 42 | virtual void Dump(u64 pipeline_hash, u64 shader_hash) = 0; |
| 43 | 43 | ||
| 44 | [[nodiscard]] const ProgramHeader& SPH() const noexcept { | 44 | [[nodiscard]] const ProgramHeader& SPH() const noexcept { |
| 45 | return sph; | 45 | return sph; |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index cd8e24b0b..da8eab7ee 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/microprofile.h" | 7 | #include "common/microprofile.h" |
| 8 | #include "common/polyfill_ranges.h" | ||
| 8 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 9 | #include "core/core.h" | 10 | #include "core/core.h" |
| 10 | #include "core/memory.h" | 11 | #include "core/memory.h" |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index ee140c9c2..94258ccd0 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -106,6 +106,43 @@ bool IsASTCSupported() { | |||
| 106 | return true; | 106 | return true; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static bool HasSlowSoftwareAstc(std::string_view vendor_name, std::string_view renderer) { | ||
| 110 | // ifdef for Unix reduces string comparisons for non-Windows drivers, and Intel | ||
| 111 | #ifdef YUZU_UNIX | ||
| 112 | // Sorted vaguely by how likely a vendor is to appear | ||
| 113 | if (vendor_name == "AMD") { | ||
| 114 | // RadeonSI | ||
| 115 | return true; | ||
| 116 | } | ||
| 117 | if (vendor_name == "Intel") { | ||
| 118 | // Must be inside YUZU_UNIX ifdef as the Windows driver uses the same vendor string | ||
| 119 | // iris, crocus | ||
| 120 | const bool is_intel_dg = (renderer.find("DG") != std::string_view::npos); | ||
| 121 | return is_intel_dg; | ||
| 122 | } | ||
| 123 | if (vendor_name == "nouveau") { | ||
| 124 | return true; | ||
| 125 | } | ||
| 126 | if (vendor_name == "X.Org") { | ||
| 127 | // R600 | ||
| 128 | return true; | ||
| 129 | } | ||
| 130 | #endif | ||
| 131 | if (vendor_name == "Collabora Ltd") { | ||
| 132 | // Zink | ||
| 133 | return true; | ||
| 134 | } | ||
| 135 | if (vendor_name == "Microsoft Corporation") { | ||
| 136 | // d3d12 | ||
| 137 | return true; | ||
| 138 | } | ||
| 139 | if (vendor_name == "Mesa/X.org") { | ||
| 140 | // llvmpipe, softpipe, virgl | ||
| 141 | return true; | ||
| 142 | } | ||
| 143 | return false; | ||
| 144 | } | ||
| 145 | |||
| 109 | [[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) { | 146 | [[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) { |
| 110 | const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); | 147 | const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); |
| 111 | return nsight || HasExtension(extensions, "GL_EXT_debug_tool") || | 148 | return nsight || HasExtension(extensions, "GL_EXT_debug_tool") || |
| @@ -120,12 +157,16 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { | |||
| 120 | } | 157 | } |
| 121 | vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 158 | vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
| 122 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); | 159 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); |
| 160 | const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | ||
| 123 | const std::vector extensions = GetExtensions(); | 161 | const std::vector extensions = GetExtensions(); |
| 124 | 162 | ||
| 125 | const bool is_nvidia = vendor_name == "NVIDIA Corporation"; | 163 | const bool is_nvidia = vendor_name == "NVIDIA Corporation"; |
| 126 | const bool is_amd = vendor_name == "ATI Technologies Inc."; | 164 | const bool is_amd = vendor_name == "ATI Technologies Inc."; |
| 127 | const bool is_intel = vendor_name == "Intel"; | 165 | const bool is_intel = vendor_name == "Intel"; |
| 128 | 166 | ||
| 167 | const bool has_slow_software_astc = | ||
| 168 | !is_nvidia && !is_amd && HasSlowSoftwareAstc(vendor_name, renderer); | ||
| 169 | |||
| 129 | #ifdef __unix__ | 170 | #ifdef __unix__ |
| 130 | constexpr bool is_linux = true; | 171 | constexpr bool is_linux = true; |
| 131 | #else | 172 | #else |
| @@ -152,7 +193,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { | |||
| 152 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; | 193 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; |
| 153 | has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); | 194 | has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); |
| 154 | has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod"); | 195 | has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod"); |
| 155 | has_astc = IsASTCSupported(); | 196 | has_astc = !has_slow_software_astc && IsASTCSupported(); |
| 156 | has_variable_aoffi = TestVariableAoffi(); | 197 | has_variable_aoffi = TestVariableAoffi(); |
| 157 | has_component_indexing_bug = is_amd; | 198 | has_component_indexing_bug = is_amd; |
| 158 | has_precise_bug = TestPreciseBug(); | 199 | has_precise_bug = TestPreciseBug(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 618cb6354..2888e0238 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -445,7 +445,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 445 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, | 445 | ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, |
| 446 | std::span<Shader::Environment* const> envs, bool use_shader_workers, | 446 | std::span<Shader::Environment* const> envs, bool use_shader_workers, |
| 447 | bool force_context_flush) try { | 447 | bool force_context_flush) try { |
| 448 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 448 | auto hash = key.Hash(); |
| 449 | LOG_INFO(Render_OpenGL, "0x{:016x}", hash); | ||
| 449 | size_t env_index{}; | 450 | size_t env_index{}; |
| 450 | u32 total_storage_buffers{}; | 451 | u32 total_storage_buffers{}; |
| 451 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 452 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| @@ -474,7 +475,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 474 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); | 475 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); |
| 475 | 476 | ||
| 476 | if (Settings::values.dump_shaders) { | 477 | if (Settings::values.dump_shaders) { |
| 477 | env.Dump(key.unique_hashes[index]); | 478 | env.Dump(hash, key.unique_hashes[index]); |
| 478 | } | 479 | } |
| 479 | 480 | ||
| 480 | if (!uses_vertex_a || index != 1) { | 481 | if (!uses_vertex_a || index != 1) { |
| @@ -566,12 +567,13 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | |||
| 566 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( | 567 | std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( |
| 567 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, | 568 | ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, |
| 568 | bool force_context_flush) try { | 569 | bool force_context_flush) try { |
| 569 | LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); | 570 | auto hash = key.Hash(); |
| 571 | LOG_INFO(Render_OpenGL, "0x{:016x}", hash); | ||
| 570 | 572 | ||
| 571 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 573 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| 572 | 574 | ||
| 573 | if (Settings::values.dump_shaders) { | 575 | if (Settings::values.dump_shaders) { |
| 574 | env.Dump(key.Hash()); | 576 | env.Dump(hash, key.unique_hash); |
| 575 | } | 577 | } |
| 576 | 578 | ||
| 577 | auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; | 579 | auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4f84d8497..c1314ca99 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -584,7 +584,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 584 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, | 584 | ShaderPools& pools, const GraphicsPipelineCacheKey& key, |
| 585 | std::span<Shader::Environment* const> envs, PipelineStatistics* statistics, | 585 | std::span<Shader::Environment* const> envs, PipelineStatistics* statistics, |
| 586 | bool build_in_parallel) try { | 586 | bool build_in_parallel) try { |
| 587 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); | 587 | auto hash = key.Hash(); |
| 588 | LOG_INFO(Render_Vulkan, "0x{:016x}", hash); | ||
| 588 | size_t env_index{0}; | 589 | size_t env_index{0}; |
| 589 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 590 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 590 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | 591 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; |
| @@ -611,7 +612,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 611 | const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))}; | 612 | const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))}; |
| 612 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); | 613 | Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); |
| 613 | if (Settings::values.dump_shaders) { | 614 | if (Settings::values.dump_shaders) { |
| 614 | env.Dump(key.unique_hashes[index]); | 615 | env.Dump(hash, key.unique_hashes[index]); |
| 615 | } | 616 | } |
| 616 | if (!uses_vertex_a || index != 1) { | 617 | if (!uses_vertex_a || index != 1) { |
| 617 | // Normal path | 618 | // Normal path |
| @@ -712,18 +713,19 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | |||
| 712 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( | 713 | std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( |
| 713 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, | 714 | ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, |
| 714 | PipelineStatistics* statistics, bool build_in_parallel) try { | 715 | PipelineStatistics* statistics, bool build_in_parallel) try { |
| 716 | auto hash = key.Hash(); | ||
| 715 | if (device.HasBrokenCompute()) { | 717 | if (device.HasBrokenCompute()) { |
| 716 | LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); | 718 | LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", hash); |
| 717 | return nullptr; | 719 | return nullptr; |
| 718 | } | 720 | } |
| 719 | 721 | ||
| 720 | LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); | 722 | LOG_INFO(Render_Vulkan, "0x{:016x}", hash); |
| 721 | 723 | ||
| 722 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; | 724 | Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; |
| 723 | 725 | ||
| 724 | // Dump it before error. | 726 | // Dump it before error. |
| 725 | if (Settings::values.dump_shaders) { | 727 | if (Settings::values.dump_shaders) { |
| 726 | env.Dump(key.Hash()); | 728 | env.Dump(hash, key.unique_hash); |
| 727 | } | 729 | } |
| 728 | 730 | ||
| 729 | auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; | 731 | auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; |
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index 01701201d..e81cd031b 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp | |||
| @@ -51,6 +51,11 @@ bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) { | |||
| 51 | } | 51 | } |
| 52 | const auto& shader_config{maxwell3d->regs.pipelines[index]}; | 52 | const auto& shader_config{maxwell3d->regs.pipelines[index]}; |
| 53 | const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)}; | 53 | const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)}; |
| 54 | if (program == Tegra::Engines::Maxwell3D::Regs::ShaderType::Pixel && | ||
| 55 | !maxwell3d->regs.rasterize_enable) { | ||
| 56 | unique_hashes[index] = 0; | ||
| 57 | continue; | ||
| 58 | } | ||
| 54 | const GPUVAddr shader_addr{base_addr + shader_config.offset}; | 59 | const GPUVAddr shader_addr{base_addr + shader_config.offset}; |
| 55 | const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)}; | 60 | const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)}; |
| 56 | if (!cpu_shader_addr) { | 61 | if (!cpu_shader_addr) { |
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index de8e08002..a76896620 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h | |||
| @@ -70,7 +70,7 @@ public: | |||
| 70 | protected: | 70 | protected: |
| 71 | struct GraphicsEnvironments { | 71 | struct GraphicsEnvironments { |
| 72 | std::array<GraphicsEnvironment, NUM_PROGRAMS> envs; | 72 | std::array<GraphicsEnvironment, NUM_PROGRAMS> envs; |
| 73 | std::array<Shader::Environment*, NUM_PROGRAMS> env_ptrs; | 73 | std::array<Shader::Environment*, NUM_PROGRAMS> env_ptrs{}; |
| 74 | 74 | ||
| 75 | std::span<Shader::Environment* const> Span() const noexcept { | 75 | std::span<Shader::Environment* const> Span() const noexcept { |
| 76 | return std::span(env_ptrs.begin(), std::ranges::find(env_ptrs, nullptr)); | 76 | return std::span(env_ptrs.begin(), std::ranges::find(env_ptrs, nullptr)); |
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index c7cb56243..4edbe5700 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp | |||
| @@ -102,7 +102,8 @@ static std::string_view StageToPrefix(Shader::Stage stage) { | |||
| 102 | } | 102 | } |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static void DumpImpl(u64 hash, const u64* code, u32 read_highest, u32 read_lowest, | 105 | static void DumpImpl(u64 pipeline_hash, u64 shader_hash, std::span<const u64> code, |
| 106 | [[maybe_unused]] u32 read_highest, [[maybe_unused]] u32 read_lowest, | ||
| 106 | u32 initial_offset, Shader::Stage stage) { | 107 | u32 initial_offset, Shader::Stage stage) { |
| 107 | const auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)}; | 108 | const auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)}; |
| 108 | const auto base_dir{shader_dir / "shaders"}; | 109 | const auto base_dir{shader_dir / "shaders"}; |
| @@ -111,13 +112,18 @@ static void DumpImpl(u64 hash, const u64* code, u32 read_highest, u32 read_lowes | |||
| 111 | return; | 112 | return; |
| 112 | } | 113 | } |
| 113 | const auto prefix = StageToPrefix(stage); | 114 | const auto prefix = StageToPrefix(stage); |
| 114 | const auto name{base_dir / fmt::format("{}{:016x}.ash", prefix, hash)}; | 115 | const auto name{base_dir / |
| 115 | const size_t real_size = read_highest - read_lowest + initial_offset; | 116 | fmt::format("{:016x}_{}_{:016x}.ash", pipeline_hash, prefix, shader_hash)}; |
| 116 | const size_t padding_needed = ((32 - (real_size % 32)) % 32); | ||
| 117 | std::fstream shader_file(name, std::ios::out | std::ios::binary); | 117 | std::fstream shader_file(name, std::ios::out | std::ios::binary); |
| 118 | ASSERT(initial_offset % sizeof(u64) == 0); | ||
| 118 | const size_t jump_index = initial_offset / sizeof(u64); | 119 | const size_t jump_index = initial_offset / sizeof(u64); |
| 119 | shader_file.write(reinterpret_cast<const char*>(code + jump_index), real_size); | 120 | const size_t code_size = code.size_bytes() - initial_offset; |
| 120 | for (size_t i = 0; i < padding_needed; i++) { | 121 | shader_file.write(reinterpret_cast<const char*>(&code[jump_index]), code_size); |
| 122 | |||
| 123 | // + 1 instruction, due to the fact that we skip the final self branch instruction in the code, | ||
| 124 | // but we need to consider it for padding, otherwise nvdisasm rages. | ||
| 125 | const size_t padding_needed = (32 - ((code_size + INST_SIZE) % 32)) % 32; | ||
| 126 | for (size_t i = 0; i < INST_SIZE + padding_needed; i++) { | ||
| 121 | shader_file.put(0); | 127 | shader_file.put(0); |
| 122 | } | 128 | } |
| 123 | } | 129 | } |
| @@ -197,8 +203,8 @@ u64 GenericEnvironment::CalculateHash() const { | |||
| 197 | return Common::CityHash64(data.get(), size); | 203 | return Common::CityHash64(data.get(), size); |
| 198 | } | 204 | } |
| 199 | 205 | ||
| 200 | void GenericEnvironment::Dump(u64 hash) { | 206 | void GenericEnvironment::Dump(u64 pipeline_hash, u64 shader_hash) { |
| 201 | DumpImpl(hash, code.data(), read_highest, read_lowest, initial_offset, stage); | 207 | DumpImpl(pipeline_hash, shader_hash, code, read_highest, read_lowest, initial_offset, stage); |
| 202 | } | 208 | } |
| 203 | 209 | ||
| 204 | void GenericEnvironment::Serialize(std::ofstream& file) const { | 210 | void GenericEnvironment::Serialize(std::ofstream& file) const { |
| @@ -282,6 +288,7 @@ std::optional<u64> GenericEnvironment::TryFindSize() { | |||
| 282 | Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit, | 288 | Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit, |
| 283 | bool via_header_index, u32 raw) { | 289 | bool via_header_index, u32 raw) { |
| 284 | const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; | 290 | const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; |
| 291 | ASSERT(handle.first <= tic_limit); | ||
| 285 | const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)}; | 292 | const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)}; |
| 286 | Tegra::Texture::TICEntry entry; | 293 | Tegra::Texture::TICEntry entry; |
| 287 | gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry)); | 294 | gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry)); |
| @@ -465,8 +472,8 @@ void FileEnvironment::Deserialize(std::ifstream& file) { | |||
| 465 | .read(reinterpret_cast<char*>(&read_highest), sizeof(read_highest)) | 472 | .read(reinterpret_cast<char*>(&read_highest), sizeof(read_highest)) |
| 466 | .read(reinterpret_cast<char*>(&viewport_transform_state), sizeof(viewport_transform_state)) | 473 | .read(reinterpret_cast<char*>(&viewport_transform_state), sizeof(viewport_transform_state)) |
| 467 | .read(reinterpret_cast<char*>(&stage), sizeof(stage)); | 474 | .read(reinterpret_cast<char*>(&stage), sizeof(stage)); |
| 468 | code = std::make_unique<u64[]>(Common::DivCeil(code_size, sizeof(u64))); | 475 | code.resize(Common::DivCeil(code_size, sizeof(u64))); |
| 469 | file.read(reinterpret_cast<char*>(code.get()), code_size); | 476 | file.read(reinterpret_cast<char*>(code.data()), code_size); |
| 470 | for (size_t i = 0; i < num_texture_types; ++i) { | 477 | for (size_t i = 0; i < num_texture_types; ++i) { |
| 471 | u32 key; | 478 | u32 key; |
| 472 | Shader::TextureType type; | 479 | Shader::TextureType type; |
| @@ -509,8 +516,8 @@ void FileEnvironment::Deserialize(std::ifstream& file) { | |||
| 509 | is_propietary_driver = texture_bound == 2; | 516 | is_propietary_driver = texture_bound == 2; |
| 510 | } | 517 | } |
| 511 | 518 | ||
| 512 | void FileEnvironment::Dump(u64 hash) { | 519 | void FileEnvironment::Dump(u64 pipeline_hash, u64 shader_hash) { |
| 513 | DumpImpl(hash, code.get(), read_highest, read_lowest, initial_offset, stage); | 520 | DumpImpl(pipeline_hash, shader_hash, code, read_highest, read_lowest, initial_offset, stage); |
| 514 | } | 521 | } |
| 515 | 522 | ||
| 516 | u64 FileEnvironment::ReadInstruction(u32 address) { | 523 | u64 FileEnvironment::ReadInstruction(u32 address) { |
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index a0f61cbda..b90f3d44e 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h | |||
| @@ -58,7 +58,7 @@ public: | |||
| 58 | 58 | ||
| 59 | [[nodiscard]] u64 CalculateHash() const; | 59 | [[nodiscard]] u64 CalculateHash() const; |
| 60 | 60 | ||
| 61 | void Dump(u64 hash) override; | 61 | void Dump(u64 pipeline_hash, u64 shader_hash) override; |
| 62 | 62 | ||
| 63 | void Serialize(std::ofstream& file) const; | 63 | void Serialize(std::ofstream& file) const; |
| 64 | 64 | ||
| @@ -188,10 +188,10 @@ public: | |||
| 188 | return cbuf_replacements.size() != 0; | 188 | return cbuf_replacements.size() != 0; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | void Dump(u64 hash) override; | 191 | void Dump(u64 pipeline_hash, u64 shader_hash) override; |
| 192 | 192 | ||
| 193 | private: | 193 | private: |
| 194 | std::unique_ptr<u64[]> code; | 194 | std::vector<u64> code; |
| 195 | std::unordered_map<u32, Shader::TextureType> texture_types; | 195 | std::unordered_map<u32, Shader::TextureType> texture_types; |
| 196 | std::unordered_map<u32, Shader::TexturePixelFormat> texture_pixel_formats; | 196 | std::unordered_map<u32, Shader::TexturePixelFormat> texture_pixel_formats; |
| 197 | std::unordered_map<u64, u32> cbuf_values; | 197 | std::unordered_map<u64, u32> cbuf_values; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index bd67e27ed..adde96aa5 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -326,6 +326,43 @@ std::vector<const char*> ExtensionListForVulkan( | |||
| 326 | 326 | ||
| 327 | } // Anonymous namespace | 327 | } // Anonymous namespace |
| 328 | 328 | ||
| 329 | void Device::RemoveExtension(bool& extension, const std::string& extension_name) { | ||
| 330 | extension = false; | ||
| 331 | loaded_extensions.erase(extension_name); | ||
| 332 | } | ||
| 333 | |||
| 334 | void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) { | ||
| 335 | if (loaded_extensions.contains(extension_name) && !is_suitable) { | ||
| 336 | LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name); | ||
| 337 | this->RemoveExtension(is_suitable, extension_name); | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | template <typename Feature> | ||
| 342 | void Device::RemoveExtensionFeature(bool& extension, Feature& feature, | ||
| 343 | const std::string& extension_name) { | ||
| 344 | // Unload extension. | ||
| 345 | this->RemoveExtension(extension, extension_name); | ||
| 346 | |||
| 347 | // Save sType and pNext for chain. | ||
| 348 | VkStructureType sType = feature.sType; | ||
| 349 | void* pNext = feature.pNext; | ||
| 350 | |||
| 351 | // Clear feature struct and restore chain. | ||
| 352 | feature = {}; | ||
| 353 | feature.sType = sType; | ||
| 354 | feature.pNext = pNext; | ||
| 355 | } | ||
| 356 | |||
| 357 | template <typename Feature> | ||
| 358 | void Device::RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature, | ||
| 359 | const std::string& extension_name) { | ||
| 360 | if (loaded_extensions.contains(extension_name) && !is_suitable) { | ||
| 361 | LOG_WARNING(Render_Vulkan, "Removing features for unsuitable extension {}", extension_name); | ||
| 362 | this->RemoveExtensionFeature(is_suitable, feature, extension_name); | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 329 | Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface, | 366 | Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface, |
| 330 | const vk::InstanceDispatch& dld_) | 367 | const vk::InstanceDispatch& dld_) |
| 331 | : instance{instance_}, dld{dld_}, physical{physical_}, | 368 | : instance{instance_}, dld{dld_}, physical{physical_}, |
| @@ -397,21 +434,20 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 397 | if (is_qualcomm || is_turnip) { | 434 | if (is_qualcomm || is_turnip) { |
| 398 | LOG_WARNING(Render_Vulkan, | 435 | LOG_WARNING(Render_Vulkan, |
| 399 | "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); | 436 | "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); |
| 400 | extensions.custom_border_color = false; | 437 | RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color, |
| 401 | loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); | 438 | VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); |
| 402 | } | 439 | } |
| 403 | 440 | ||
| 404 | if (is_qualcomm) { | 441 | if (is_qualcomm) { |
| 405 | must_emulate_scaled_formats = true; | 442 | must_emulate_scaled_formats = true; |
| 406 | 443 | ||
| 407 | LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state"); | 444 | LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state"); |
| 408 | extensions.extended_dynamic_state = false; | 445 | RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, |
| 409 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 446 | VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| 410 | 447 | ||
| 411 | LOG_WARNING(Render_Vulkan, | 448 | LOG_WARNING(Render_Vulkan, |
| 412 | "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); | 449 | "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); |
| 413 | extensions.push_descriptor = false; | 450 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| 414 | loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||
| 415 | 451 | ||
| 416 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) | 452 | #if defined(ANDROID) && defined(ARCHITECTURE_arm64) |
| 417 | // Patch the driver to enable BCn textures. | 453 | // Patch the driver to enable BCn textures. |
| @@ -440,15 +476,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 440 | must_emulate_scaled_formats = true; | 476 | must_emulate_scaled_formats = true; |
| 441 | 477 | ||
| 442 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); | 478 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); |
| 443 | extensions.extended_dynamic_state = false; | 479 | RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state, |
| 444 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 480 | VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| 445 | 481 | ||
| 446 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2"); | 482 | LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2"); |
| 447 | features.extended_dynamic_state2.extendedDynamicState2 = false; | 483 | RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2, |
| 448 | features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; | 484 | VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); |
| 449 | features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false; | ||
| 450 | extensions.extended_dynamic_state2 = false; | ||
| 451 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); | ||
| 452 | } | 485 | } |
| 453 | 486 | ||
| 454 | if (is_nvidia) { | 487 | if (is_nvidia) { |
| @@ -464,8 +497,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 464 | case NvidiaArchitecture::VoltaOrOlder: | 497 | case NvidiaArchitecture::VoltaOrOlder: |
| 465 | if (nv_major_version < 527) { | 498 | if (nv_major_version < 527) { |
| 466 | LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); | 499 | LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); |
| 467 | extensions.push_descriptor = false; | 500 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| 468 | loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||
| 469 | } | 501 | } |
| 470 | break; | 502 | break; |
| 471 | } | 503 | } |
| @@ -480,8 +512,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 480 | if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) { | 512 | if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) { |
| 481 | LOG_WARNING(Render_Vulkan, | 513 | LOG_WARNING(Render_Vulkan, |
| 482 | "RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state"); | 514 | "RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state"); |
| 483 | extensions.extended_dynamic_state = false; | 515 | RemoveExtensionFeature(extensions.extended_dynamic_state, |
| 484 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 516 | features.extended_dynamic_state, |
| 517 | VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 485 | } | 518 | } |
| 486 | } | 519 | } |
| 487 | if (extensions.extended_dynamic_state2 && is_radv) { | 520 | if (extensions.extended_dynamic_state2 && is_radv) { |
| @@ -490,11 +523,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 490 | LOG_WARNING( | 523 | LOG_WARNING( |
| 491 | Render_Vulkan, | 524 | Render_Vulkan, |
| 492 | "RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2"); | 525 | "RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2"); |
| 493 | features.extended_dynamic_state2.extendedDynamicState2 = false; | 526 | RemoveExtensionFeature(extensions.extended_dynamic_state2, |
| 494 | features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; | 527 | features.extended_dynamic_state2, |
| 495 | features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false; | 528 | VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); |
| 496 | extensions.extended_dynamic_state2 = false; | ||
| 497 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); | ||
| 498 | } | 529 | } |
| 499 | } | 530 | } |
| 500 | if (extensions.extended_dynamic_state2 && is_qualcomm) { | 531 | if (extensions.extended_dynamic_state2 && is_qualcomm) { |
| @@ -504,11 +535,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 504 | // Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2. | 535 | // Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2. |
| 505 | LOG_WARNING(Render_Vulkan, | 536 | LOG_WARNING(Render_Vulkan, |
| 506 | "Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2"); | 537 | "Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2"); |
| 507 | features.extended_dynamic_state2.extendedDynamicState2 = false; | 538 | RemoveExtensionFeature(extensions.extended_dynamic_state2, |
| 508 | features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; | 539 | features.extended_dynamic_state2, |
| 509 | features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false; | 540 | VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); |
| 510 | extensions.extended_dynamic_state2 = false; | ||
| 511 | loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); | ||
| 512 | } | 541 | } |
| 513 | } | 542 | } |
| 514 | if (extensions.extended_dynamic_state3 && is_radv) { | 543 | if (extensions.extended_dynamic_state3 && is_radv) { |
| @@ -540,9 +569,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 540 | if (is_rdna2) { | 569 | if (is_rdna2) { |
| 541 | LOG_WARNING(Render_Vulkan, | 570 | LOG_WARNING(Render_Vulkan, |
| 542 | "RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware"); | 571 | "RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware"); |
| 543 | features.vertex_input_dynamic_state.vertexInputDynamicState = false; | 572 | RemoveExtensionFeature(extensions.vertex_input_dynamic_state, |
| 544 | extensions.vertex_input_dynamic_state = false; | 573 | features.vertex_input_dynamic_state, |
| 545 | loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | 574 | VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); |
| 546 | } | 575 | } |
| 547 | } | 576 | } |
| 548 | if (extensions.vertex_input_dynamic_state && is_qualcomm) { | 577 | if (extensions.vertex_input_dynamic_state && is_qualcomm) { |
| @@ -553,9 +582,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 553 | LOG_WARNING( | 582 | LOG_WARNING( |
| 554 | Render_Vulkan, | 583 | Render_Vulkan, |
| 555 | "Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state"); | 584 | "Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state"); |
| 556 | features.vertex_input_dynamic_state.vertexInputDynamicState = false; | 585 | RemoveExtensionFeature(extensions.vertex_input_dynamic_state, |
| 557 | extensions.vertex_input_dynamic_state = false; | 586 | features.vertex_input_dynamic_state, |
| 558 | loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | 587 | VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); |
| 559 | } | 588 | } |
| 560 | } | 589 | } |
| 561 | 590 | ||
| @@ -575,8 +604,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 575 | if (!features.shader_float16_int8.shaderFloat16) { | 604 | if (!features.shader_float16_int8.shaderFloat16) { |
| 576 | LOG_WARNING(Render_Vulkan, | 605 | LOG_WARNING(Render_Vulkan, |
| 577 | "AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax"); | 606 | "AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax"); |
| 578 | extensions.sampler_filter_minmax = false; | 607 | RemoveExtension(extensions.sampler_filter_minmax, |
| 579 | loaded_extensions.erase(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME); | 608 | VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME); |
| 580 | } | 609 | } |
| 581 | } | 610 | } |
| 582 | 611 | ||
| @@ -584,8 +613,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 584 | const u32 version = (properties.properties.driverVersion << 3) >> 3; | 613 | const u32 version = (properties.properties.driverVersion << 3) >> 3; |
| 585 | if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) { | 614 | if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) { |
| 586 | LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state"); | 615 | LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state"); |
| 587 | extensions.vertex_input_dynamic_state = false; | 616 | RemoveExtensionFeature(extensions.vertex_input_dynamic_state, |
| 588 | loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | 617 | features.vertex_input_dynamic_state, |
| 618 | VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 589 | } | 619 | } |
| 590 | } | 620 | } |
| 591 | if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) { | 621 | if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) { |
| @@ -612,8 +642,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 612 | // mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc | 642 | // mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc |
| 613 | LOG_WARNING(Render_Vulkan, | 643 | LOG_WARNING(Render_Vulkan, |
| 614 | "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); | 644 | "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); |
| 615 | extensions.push_descriptor = false; | 645 | RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); |
| 616 | loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); | ||
| 617 | } | 646 | } |
| 618 | } | 647 | } |
| 619 | if (is_mvk) { | 648 | if (is_mvk) { |
| @@ -963,7 +992,7 @@ bool Device::GetSuitability(bool requires_swapchain) { | |||
| 963 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR; | 992 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR; |
| 964 | SetNext(next, properties.push_descriptor); | 993 | SetNext(next, properties.push_descriptor); |
| 965 | } | 994 | } |
| 966 | if (extensions.subgroup_size_control) { | 995 | if (extensions.subgroup_size_control || features.subgroup_size_control.subgroupSizeControl) { |
| 967 | properties.subgroup_size_control.sType = | 996 | properties.subgroup_size_control.sType = |
| 968 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES; | 997 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES; |
| 969 | SetNext(next, properties.subgroup_size_control); | 998 | SetNext(next, properties.subgroup_size_control); |
| @@ -1007,34 +1036,29 @@ bool Device::GetSuitability(bool requires_swapchain) { | |||
| 1007 | return suitable; | 1036 | return suitable; |
| 1008 | } | 1037 | } |
| 1009 | 1038 | ||
| 1010 | void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) { | ||
| 1011 | if (loaded_extensions.contains(extension_name) && !is_suitable) { | ||
| 1012 | LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name); | ||
| 1013 | loaded_extensions.erase(extension_name); | ||
| 1014 | } | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | void Device::RemoveUnsuitableExtensions() { | 1039 | void Device::RemoveUnsuitableExtensions() { |
| 1018 | // VK_EXT_custom_border_color | 1040 | // VK_EXT_custom_border_color |
| 1019 | extensions.custom_border_color = features.custom_border_color.customBorderColors && | 1041 | extensions.custom_border_color = features.custom_border_color.customBorderColors && |
| 1020 | features.custom_border_color.customBorderColorWithoutFormat; | 1042 | features.custom_border_color.customBorderColorWithoutFormat; |
| 1021 | RemoveExtensionIfUnsuitable(extensions.custom_border_color, | 1043 | RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, |
| 1022 | VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); | 1044 | VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); |
| 1023 | 1045 | ||
| 1024 | // VK_EXT_depth_clip_control | 1046 | // VK_EXT_depth_clip_control |
| 1025 | extensions.depth_clip_control = features.depth_clip_control.depthClipControl; | 1047 | extensions.depth_clip_control = features.depth_clip_control.depthClipControl; |
| 1026 | RemoveExtensionIfUnsuitable(extensions.depth_clip_control, | 1048 | RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control, |
| 1027 | VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); | 1049 | VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); |
| 1028 | 1050 | ||
| 1029 | // VK_EXT_extended_dynamic_state | 1051 | // VK_EXT_extended_dynamic_state |
| 1030 | extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState; | 1052 | extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState; |
| 1031 | RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state, | 1053 | RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state, |
| 1032 | VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 1054 | features.extended_dynamic_state, |
| 1055 | VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 1033 | 1056 | ||
| 1034 | // VK_EXT_extended_dynamic_state2 | 1057 | // VK_EXT_extended_dynamic_state2 |
| 1035 | extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2; | 1058 | extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2; |
| 1036 | RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state2, | 1059 | RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state2, |
| 1037 | VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); | 1060 | features.extended_dynamic_state2, |
| 1061 | VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); | ||
| 1038 | 1062 | ||
| 1039 | // VK_EXT_extended_dynamic_state3 | 1063 | // VK_EXT_extended_dynamic_state3 |
| 1040 | dynamic_state3_blending = | 1064 | dynamic_state3_blending = |
| @@ -1048,35 +1072,38 @@ void Device::RemoveUnsuitableExtensions() { | |||
| 1048 | extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables; | 1072 | extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables; |
| 1049 | dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3; | 1073 | dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3; |
| 1050 | dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3; | 1074 | dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3; |
| 1051 | RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state3, | 1075 | RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state3, |
| 1052 | VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); | 1076 | features.extended_dynamic_state3, |
| 1077 | VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); | ||
| 1053 | 1078 | ||
| 1054 | // VK_EXT_provoking_vertex | 1079 | // VK_EXT_provoking_vertex |
| 1055 | extensions.provoking_vertex = | 1080 | extensions.provoking_vertex = |
| 1056 | features.provoking_vertex.provokingVertexLast && | 1081 | features.provoking_vertex.provokingVertexLast && |
| 1057 | features.provoking_vertex.transformFeedbackPreservesProvokingVertex; | 1082 | features.provoking_vertex.transformFeedbackPreservesProvokingVertex; |
| 1058 | RemoveExtensionIfUnsuitable(extensions.provoking_vertex, | 1083 | RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex, |
| 1059 | VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); | 1084 | VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); |
| 1060 | 1085 | ||
| 1061 | // VK_KHR_shader_atomic_int64 | 1086 | // VK_KHR_shader_atomic_int64 |
| 1062 | extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics && | 1087 | extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics && |
| 1063 | features.shader_atomic_int64.shaderSharedInt64Atomics; | 1088 | features.shader_atomic_int64.shaderSharedInt64Atomics; |
| 1064 | RemoveExtensionIfUnsuitable(extensions.shader_atomic_int64, | 1089 | RemoveExtensionFeatureIfUnsuitable(extensions.shader_atomic_int64, features.shader_atomic_int64, |
| 1065 | VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); | 1090 | VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); |
| 1066 | 1091 | ||
| 1067 | // VK_EXT_shader_demote_to_helper_invocation | 1092 | // VK_EXT_shader_demote_to_helper_invocation |
| 1068 | extensions.shader_demote_to_helper_invocation = | 1093 | extensions.shader_demote_to_helper_invocation = |
| 1069 | features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation; | 1094 | features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation; |
| 1070 | RemoveExtensionIfUnsuitable(extensions.shader_demote_to_helper_invocation, | 1095 | RemoveExtensionFeatureIfUnsuitable(extensions.shader_demote_to_helper_invocation, |
| 1071 | VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); | 1096 | features.shader_demote_to_helper_invocation, |
| 1097 | VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); | ||
| 1072 | 1098 | ||
| 1073 | // VK_EXT_subgroup_size_control | 1099 | // VK_EXT_subgroup_size_control |
| 1074 | extensions.subgroup_size_control = | 1100 | extensions.subgroup_size_control = |
| 1075 | features.subgroup_size_control.subgroupSizeControl && | 1101 | features.subgroup_size_control.subgroupSizeControl && |
| 1076 | properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize && | 1102 | properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize && |
| 1077 | properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize; | 1103 | properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize; |
| 1078 | RemoveExtensionIfUnsuitable(extensions.subgroup_size_control, | 1104 | RemoveExtensionFeatureIfUnsuitable(extensions.subgroup_size_control, |
| 1079 | VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); | 1105 | features.subgroup_size_control, |
| 1106 | VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); | ||
| 1080 | 1107 | ||
| 1081 | // VK_EXT_transform_feedback | 1108 | // VK_EXT_transform_feedback |
| 1082 | extensions.transform_feedback = | 1109 | extensions.transform_feedback = |
| @@ -1086,24 +1113,27 @@ void Device::RemoveUnsuitableExtensions() { | |||
| 1086 | properties.transform_feedback.maxTransformFeedbackBuffers > 0 && | 1113 | properties.transform_feedback.maxTransformFeedbackBuffers > 0 && |
| 1087 | properties.transform_feedback.transformFeedbackQueries && | 1114 | properties.transform_feedback.transformFeedbackQueries && |
| 1088 | properties.transform_feedback.transformFeedbackDraw; | 1115 | properties.transform_feedback.transformFeedbackDraw; |
| 1089 | RemoveExtensionIfUnsuitable(extensions.transform_feedback, | 1116 | RemoveExtensionFeatureIfUnsuitable(extensions.transform_feedback, features.transform_feedback, |
| 1090 | VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); | 1117 | VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); |
| 1091 | 1118 | ||
| 1092 | // VK_EXT_vertex_input_dynamic_state | 1119 | // VK_EXT_vertex_input_dynamic_state |
| 1093 | extensions.vertex_input_dynamic_state = | 1120 | extensions.vertex_input_dynamic_state = |
| 1094 | features.vertex_input_dynamic_state.vertexInputDynamicState; | 1121 | features.vertex_input_dynamic_state.vertexInputDynamicState; |
| 1095 | RemoveExtensionIfUnsuitable(extensions.vertex_input_dynamic_state, | 1122 | RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state, |
| 1096 | VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | 1123 | features.vertex_input_dynamic_state, |
| 1124 | VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | ||
| 1097 | 1125 | ||
| 1098 | // VK_KHR_pipeline_executable_properties | 1126 | // VK_KHR_pipeline_executable_properties |
| 1099 | if (Settings::values.renderer_shader_feedback.GetValue()) { | 1127 | if (Settings::values.renderer_shader_feedback.GetValue()) { |
| 1100 | extensions.pipeline_executable_properties = | 1128 | extensions.pipeline_executable_properties = |
| 1101 | features.pipeline_executable_properties.pipelineExecutableInfo; | 1129 | features.pipeline_executable_properties.pipelineExecutableInfo; |
| 1102 | RemoveExtensionIfUnsuitable(extensions.pipeline_executable_properties, | 1130 | RemoveExtensionFeatureIfUnsuitable(extensions.pipeline_executable_properties, |
| 1103 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | 1131 | features.pipeline_executable_properties, |
| 1132 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | ||
| 1104 | } else { | 1133 | } else { |
| 1105 | extensions.pipeline_executable_properties = false; | 1134 | RemoveExtensionFeature(extensions.pipeline_executable_properties, |
| 1106 | loaded_extensions.erase(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | 1135 | features.pipeline_executable_properties, |
| 1136 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | ||
| 1107 | } | 1137 | } |
| 1108 | 1138 | ||
| 1109 | // VK_KHR_workgroup_memory_explicit_layout | 1139 | // VK_KHR_workgroup_memory_explicit_layout |
| @@ -1113,8 +1143,9 @@ void Device::RemoveUnsuitableExtensions() { | |||
| 1113 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess && | 1143 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess && |
| 1114 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess && | 1144 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess && |
| 1115 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; | 1145 | features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; |
| 1116 | RemoveExtensionIfUnsuitable(extensions.workgroup_memory_explicit_layout, | 1146 | RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout, |
| 1117 | VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); | 1147 | features.workgroup_memory_explicit_layout, |
| 1148 | VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); | ||
| 1118 | } | 1149 | } |
| 1119 | 1150 | ||
| 1120 | void Device::SetupFamilies(VkSurfaceKHR surface) { | 1151 | void Device::SetupFamilies(VkSurfaceKHR surface) { |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index be3ed45ff..488fdd313 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -20,7 +20,6 @@ VK_DEFINE_HANDLE(VmaAllocator) | |||
| 20 | // Vulkan version in the macro describes the minimum version required for feature availability. | 20 | // Vulkan version in the macro describes the minimum version required for feature availability. |
| 21 | // If the Vulkan version is lower than the required version, the named extension is required. | 21 | // If the Vulkan version is lower than the required version, the named extension is required. |
| 22 | #define FOR_EACH_VK_FEATURE_1_1(FEATURE) \ | 22 | #define FOR_EACH_VK_FEATURE_1_1(FEATURE) \ |
| 23 | FEATURE(EXT, SubgroupSizeControl, SUBGROUP_SIZE_CONTROL, subgroup_size_control) \ | ||
| 24 | FEATURE(KHR, 16BitStorage, 16BIT_STORAGE, bit16_storage) \ | 23 | FEATURE(KHR, 16BitStorage, 16BIT_STORAGE, bit16_storage) \ |
| 25 | FEATURE(KHR, ShaderAtomicInt64, SHADER_ATOMIC_INT64, shader_atomic_int64) \ | 24 | FEATURE(KHR, ShaderAtomicInt64, SHADER_ATOMIC_INT64, shader_atomic_int64) \ |
| 26 | FEATURE(KHR, ShaderDrawParameters, SHADER_DRAW_PARAMETERS, shader_draw_parameters) \ | 25 | FEATURE(KHR, ShaderDrawParameters, SHADER_DRAW_PARAMETERS, shader_draw_parameters) \ |
| @@ -36,7 +35,8 @@ VK_DEFINE_HANDLE(VmaAllocator) | |||
| 36 | 35 | ||
| 37 | #define FOR_EACH_VK_FEATURE_1_3(FEATURE) \ | 36 | #define FOR_EACH_VK_FEATURE_1_3(FEATURE) \ |
| 38 | FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \ | 37 | FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \ |
| 39 | shader_demote_to_helper_invocation) | 38 | shader_demote_to_helper_invocation) \ |
| 39 | FEATURE(EXT, SubgroupSizeControl, SUBGROUP_SIZE_CONTROL, subgroup_size_control) | ||
| 40 | 40 | ||
| 41 | // Define all features which may be used by the implementation and require an extension here. | 41 | // Define all features which may be used by the implementation and require an extension here. |
| 42 | #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ | 42 | #define FOR_EACH_VK_FEATURE_EXT(FEATURE) \ |
| @@ -639,8 +639,17 @@ private: | |||
| 639 | 639 | ||
| 640 | // Remove extensions which have incomplete feature support. | 640 | // Remove extensions which have incomplete feature support. |
| 641 | void RemoveUnsuitableExtensions(); | 641 | void RemoveUnsuitableExtensions(); |
| 642 | |||
| 643 | void RemoveExtension(bool& extension, const std::string& extension_name); | ||
| 642 | void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name); | 644 | void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name); |
| 643 | 645 | ||
| 646 | template <typename Feature> | ||
| 647 | void RemoveExtensionFeature(bool& extension, Feature& feature, | ||
| 648 | const std::string& extension_name); | ||
| 649 | template <typename Feature> | ||
| 650 | void RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature, | ||
| 651 | const std::string& extension_name); | ||
| 652 | |||
| 644 | /// Sets up queue families. | 653 | /// Sets up queue families. |
| 645 | void SetupFamilies(VkSurfaceKHR surface); | 654 | void SetupFamilies(VkSurfaceKHR surface); |
| 646 | 655 | ||
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 465084fea..b5a02700d 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -214,13 +214,17 @@ void GameList::OnTextChanged(const QString& new_text) { | |||
| 214 | const int children_count = folder->rowCount(); | 214 | const int children_count = folder->rowCount(); |
| 215 | for (int j = 0; j < children_count; ++j) { | 215 | for (int j = 0; j < children_count; ++j) { |
| 216 | ++children_total; | 216 | ++children_total; |
| 217 | |||
| 217 | const QStandardItem* child = folder->child(j, 0); | 218 | const QStandardItem* child = folder->child(j, 0); |
| 219 | |||
| 220 | const auto program_id = child->data(GameListItemPath::ProgramIdRole).toULongLong(); | ||
| 221 | |||
| 218 | const QString file_path = | 222 | const QString file_path = |
| 219 | child->data(GameListItemPath::FullPathRole).toString().toLower(); | 223 | child->data(GameListItemPath::FullPathRole).toString().toLower(); |
| 220 | const QString file_title = | 224 | const QString file_title = |
| 221 | child->data(GameListItemPath::TitleRole).toString().toLower(); | 225 | child->data(GameListItemPath::TitleRole).toString().toLower(); |
| 222 | const QString file_program_id = | 226 | const QString file_program_id = |
| 223 | child->data(GameListItemPath::ProgramIdRole).toString().toLower(); | 227 | QStringLiteral("%1").arg(program_id, 16, 16, QLatin1Char{'0'}); |
| 224 | 228 | ||
| 225 | // Only items which filename in combination with its title contains all words | 229 | // Only items which filename in combination with its title contains all words |
| 226 | // that are in the searchfield will be visible in the gamelist | 230 | // that are in the searchfield will be visible in the gamelist |
| @@ -231,7 +235,7 @@ void GameList::OnTextChanged(const QString& new_text) { | |||
| 231 | file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} + | 235 | file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} + |
| 232 | file_title; | 236 | file_title; |
| 233 | if (ContainsAllWords(file_name, edit_filter_text) || | 237 | if (ContainsAllWords(file_name, edit_filter_text) || |
| 234 | (file_program_id.count() == 16 && edit_filter_text.contains(file_program_id))) { | 238 | (file_program_id.count() == 16 && file_program_id.contains(edit_filter_text))) { |
| 235 | tree_view->setRowHidden(j, folder_index, false); | 239 | tree_view->setRowHidden(j, folder_index, false); |
| 236 | ++result_count; | 240 | ++result_count; |
| 237 | } else { | 241 | } else { |