diff options
| -rw-r--r-- | src/core/file_sys/card_image.cpp | 114 | ||||
| -rw-r--r-- | src/core/file_sys/card_image.h | 23 | ||||
| -rw-r--r-- | src/core/file_sys/partition_filesystem.cpp | 11 | ||||
| -rw-r--r-- | src/core/file_sys/partition_filesystem.h | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 22 |
5 files changed, 146 insertions, 30 deletions
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index db54113a0..07d0c8d5d 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp | |||
| @@ -31,7 +31,7 @@ constexpr std::array partition_names{ | |||
| 31 | 31 | ||
| 32 | XCI::XCI(VirtualFile file_) | 32 | XCI::XCI(VirtualFile file_) |
| 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, | 33 | : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, |
| 34 | partitions(partition_names.size()) { | 34 | partitions(partition_names.size()), partitions_raw(partition_names.size()) { |
| 35 | if (file->ReadObject(&header) != sizeof(GamecardHeader)) { | 35 | if (file->ReadObject(&header) != sizeof(GamecardHeader)) { |
| 36 | status = Loader::ResultStatus::ErrorBadXCIHeader; | 36 | status = Loader::ResultStatus::ErrorBadXCIHeader; |
| 37 | return; | 37 | return; |
| @@ -42,8 +42,10 @@ XCI::XCI(VirtualFile file_) | |||
| 42 | return; | 42 | return; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | PartitionFilesystem main_hfs( | 45 | PartitionFilesystem main_hfs(std::make_shared<OffsetVfsFile>( |
| 46 | std::make_shared<OffsetVfsFile>(file, header.hfs_size, header.hfs_offset)); | 46 | file, file->GetSize() - header.hfs_offset, header.hfs_offset)); |
| 47 | |||
| 48 | update_normal_partition_end = main_hfs.GetFileOffsets()["secure"]; | ||
| 47 | 49 | ||
| 48 | if (main_hfs.GetStatus() != Loader::ResultStatus::Success) { | 50 | if (main_hfs.GetStatus() != Loader::ResultStatus::Success) { |
| 49 | status = main_hfs.GetStatus(); | 51 | status = main_hfs.GetStatus(); |
| @@ -55,9 +57,7 @@ XCI::XCI(VirtualFile file_) | |||
| 55 | const auto partition_idx = static_cast<std::size_t>(partition); | 57 | const auto partition_idx = static_cast<std::size_t>(partition); |
| 56 | auto raw = main_hfs.GetFile(partition_names[partition_idx]); | 58 | auto raw = main_hfs.GetFile(partition_names[partition_idx]); |
| 57 | 59 | ||
| 58 | if (raw != nullptr) { | 60 | partitions_raw[static_cast<std::size_t>(partition)] = std::move(raw); |
| 59 | partitions[partition_idx] = std::make_shared<PartitionFilesystem>(std::move(raw)); | ||
| 60 | } | ||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | secure_partition = std::make_shared<NSP>( | 63 | secure_partition = std::make_shared<NSP>( |
| @@ -71,13 +71,7 @@ XCI::XCI(VirtualFile file_) | |||
| 71 | program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; | 71 | program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | auto result = AddNCAFromPartition(XCIPartition::Update); | 74 | auto result = AddNCAFromPartition(XCIPartition::Normal); |
| 75 | if (result != Loader::ResultStatus::Success) { | ||
| 76 | status = result; | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | |||
| 80 | result = AddNCAFromPartition(XCIPartition::Normal); | ||
| 81 | if (result != Loader::ResultStatus::Success) { | 75 | if (result != Loader::ResultStatus::Success) { |
| 82 | status = result; | 76 | status = result; |
| 83 | return; | 77 | return; |
| @@ -104,34 +98,114 @@ Loader::ResultStatus XCI::GetProgramNCAStatus() const { | |||
| 104 | return program_nca_status; | 98 | return program_nca_status; |
| 105 | } | 99 | } |
| 106 | 100 | ||
| 107 | VirtualDir XCI::GetPartition(XCIPartition partition) const { | 101 | VirtualDir XCI::GetPartition(XCIPartition partition) { |
| 102 | const auto id = static_cast<std::size_t>(partition); | ||
| 103 | if (partitions[id] == nullptr && partitions_raw[id] != nullptr) { | ||
| 104 | partitions[id] = std::make_shared<PartitionFilesystem>(partitions_raw[id]); | ||
| 105 | } | ||
| 106 | |||
| 108 | return partitions[static_cast<std::size_t>(partition)]; | 107 | return partitions[static_cast<std::size_t>(partition)]; |
| 109 | } | 108 | } |
| 110 | 109 | ||
| 110 | std::vector<VirtualDir> XCI::GetPartitions() { | ||
| 111 | std::vector<VirtualDir> out; | ||
| 112 | for (const auto& id : | ||
| 113 | {XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) { | ||
| 114 | const auto part = GetPartition(id); | ||
| 115 | if (part != nullptr) { | ||
| 116 | out.push_back(part); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | return out; | ||
| 120 | } | ||
| 121 | |||
| 111 | std::shared_ptr<NSP> XCI::GetSecurePartitionNSP() const { | 122 | std::shared_ptr<NSP> XCI::GetSecurePartitionNSP() const { |
| 112 | return secure_partition; | 123 | return secure_partition; |
| 113 | } | 124 | } |
| 114 | 125 | ||
| 115 | VirtualDir XCI::GetSecurePartition() const { | 126 | VirtualDir XCI::GetSecurePartition() { |
| 116 | return GetPartition(XCIPartition::Secure); | 127 | return GetPartition(XCIPartition::Secure); |
| 117 | } | 128 | } |
| 118 | 129 | ||
| 119 | VirtualDir XCI::GetNormalPartition() const { | 130 | VirtualDir XCI::GetNormalPartition() { |
| 120 | return GetPartition(XCIPartition::Normal); | 131 | return GetPartition(XCIPartition::Normal); |
| 121 | } | 132 | } |
| 122 | 133 | ||
| 123 | VirtualDir XCI::GetUpdatePartition() const { | 134 | VirtualDir XCI::GetUpdatePartition() { |
| 124 | return GetPartition(XCIPartition::Update); | 135 | return GetPartition(XCIPartition::Update); |
| 125 | } | 136 | } |
| 126 | 137 | ||
| 127 | VirtualDir XCI::GetLogoPartition() const { | 138 | VirtualDir XCI::GetLogoPartition() { |
| 128 | return GetPartition(XCIPartition::Logo); | 139 | return GetPartition(XCIPartition::Logo); |
| 129 | } | 140 | } |
| 130 | 141 | ||
| 142 | VirtualFile XCI::GetPartitionRaw(XCIPartition partition) const { | ||
| 143 | return partitions_raw[static_cast<std::size_t>(partition)]; | ||
| 144 | } | ||
| 145 | |||
| 146 | VirtualFile XCI::GetSecurePartitionRaw() const { | ||
| 147 | return GetPartitionRaw(XCIPartition::Secure); | ||
| 148 | } | ||
| 149 | |||
| 150 | VirtualFile XCI::GetStoragePartition0() const { | ||
| 151 | return std::make_shared<OffsetVfsFile>(file, update_normal_partition_end, 0, "partition0"); | ||
| 152 | } | ||
| 153 | |||
| 154 | VirtualFile XCI::GetStoragePartition1() const { | ||
| 155 | return std::make_shared<OffsetVfsFile>(file, file->GetSize() - update_normal_partition_end, | ||
| 156 | update_normal_partition_end, "partition1"); | ||
| 157 | } | ||
| 158 | |||
| 159 | VirtualFile XCI::GetNormalPartitionRaw() const { | ||
| 160 | return GetPartitionRaw(XCIPartition::Normal); | ||
| 161 | } | ||
| 162 | |||
| 163 | VirtualFile XCI::GetUpdatePartitionRaw() const { | ||
| 164 | return GetPartitionRaw(XCIPartition::Update); | ||
| 165 | } | ||
| 166 | |||
| 167 | VirtualFile XCI::GetLogoPartitionRaw() const { | ||
| 168 | return GetPartitionRaw(XCIPartition::Logo); | ||
| 169 | } | ||
| 170 | |||
| 131 | u64 XCI::GetProgramTitleID() const { | 171 | u64 XCI::GetProgramTitleID() const { |
| 132 | return secure_partition->GetProgramTitleID(); | 172 | return secure_partition->GetProgramTitleID(); |
| 133 | } | 173 | } |
| 134 | 174 | ||
| 175 | u32 XCI::GetSystemUpdateVersion() { | ||
| 176 | const auto update = GetPartition(XCIPartition::Update); | ||
| 177 | if (update == nullptr) | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | for (const auto& file : update->GetFiles()) { | ||
| 181 | NCA nca{file, nullptr, 0, keys}; | ||
| 182 | |||
| 183 | if (nca.GetStatus() != Loader::ResultStatus::Success) | ||
| 184 | continue; | ||
| 185 | |||
| 186 | if (nca.GetType() == NCAContentType::Meta && nca.GetTitleId() == 0x0100000000000816) { | ||
| 187 | const auto dir = nca.GetSubdirectories()[0]; | ||
| 188 | const auto cnmt = dir->GetFile("SystemUpdate_0100000000000816.cnmt"); | ||
| 189 | if (cnmt == nullptr) | ||
| 190 | continue; | ||
| 191 | |||
| 192 | CNMT cnmt_data{cnmt}; | ||
| 193 | |||
| 194 | const auto metas = cnmt_data.GetMetaRecords(); | ||
| 195 | if (metas.empty()) | ||
| 196 | continue; | ||
| 197 | |||
| 198 | return metas[0].title_version; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | u64 XCI::GetSystemUpdateTitleID() const { | ||
| 206 | return 0x0100000000000816; | ||
| 207 | } | ||
| 208 | |||
| 135 | bool XCI::HasProgramNCA() const { | 209 | bool XCI::HasProgramNCA() const { |
| 136 | return program != nullptr; | 210 | return program != nullptr; |
| 137 | } | 211 | } |
| @@ -201,7 +275,7 @@ std::array<u8, 0x200> XCI::GetCertificate() const { | |||
| 201 | 275 | ||
| 202 | Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { | 276 | Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { |
| 203 | const auto partition_index = static_cast<std::size_t>(part); | 277 | const auto partition_index = static_cast<std::size_t>(part); |
| 204 | const auto& partition = partitions[partition_index]; | 278 | const auto partition = GetPartition(part); |
| 205 | 279 | ||
| 206 | if (partition == nullptr) { | 280 | if (partition == nullptr) { |
| 207 | return Loader::ResultStatus::ErrorXCIMissingPartition; | 281 | return Loader::ResultStatus::ErrorXCIMissingPartition; |
| @@ -232,7 +306,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) { | |||
| 232 | return Loader::ResultStatus::Success; | 306 | return Loader::ResultStatus::Success; |
| 233 | } | 307 | } |
| 234 | 308 | ||
| 235 | u8 XCI::GetFormatVersion() const { | 309 | u8 XCI::GetFormatVersion() { |
| 236 | return GetLogoPartition() == nullptr ? 0x1 : 0x2; | 310 | return GetLogoPartition() == nullptr ? 0x1 : 0x2; |
| 237 | } | 311 | } |
| 238 | } // namespace FileSys | 312 | } // namespace FileSys |
diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 3e6b92ff3..c2ee0ea99 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h | |||
| @@ -81,14 +81,24 @@ public: | |||
| 81 | Loader::ResultStatus GetStatus() const; | 81 | Loader::ResultStatus GetStatus() const; |
| 82 | Loader::ResultStatus GetProgramNCAStatus() const; | 82 | Loader::ResultStatus GetProgramNCAStatus() const; |
| 83 | 83 | ||
| 84 | u8 GetFormatVersion() const; | 84 | u8 GetFormatVersion(); |
| 85 | |||
| 86 | VirtualDir GetPartition(XCIPartition partition); | ||
| 87 | std::vector<VirtualDir> GetPartitions(); | ||
| 85 | 88 | ||
| 86 | VirtualDir GetPartition(XCIPartition partition) const; | ||
| 87 | std::shared_ptr<NSP> GetSecurePartitionNSP() const; | 89 | std::shared_ptr<NSP> GetSecurePartitionNSP() const; |
| 88 | VirtualDir GetSecurePartition() const; | 90 | VirtualDir GetSecurePartition(); |
| 89 | VirtualDir GetNormalPartition() const; | 91 | VirtualDir GetNormalPartition(); |
| 90 | VirtualDir GetUpdatePartition() const; | 92 | VirtualDir GetUpdatePartition(); |
| 91 | VirtualDir GetLogoPartition() const; | 93 | VirtualDir GetLogoPartition(); |
| 94 | |||
| 95 | VirtualFile GetPartitionRaw(XCIPartition partition) const; | ||
| 96 | VirtualFile GetSecurePartitionRaw() const; | ||
| 97 | VirtualFile GetStoragePartition0() const; | ||
| 98 | VirtualFile GetStoragePartition1() const; | ||
| 99 | VirtualFile GetNormalPartitionRaw() const; | ||
| 100 | VirtualFile GetUpdatePartitionRaw() const; | ||
| 101 | VirtualFile GetLogoPartitionRaw() const; | ||
| 92 | 102 | ||
| 93 | u64 GetProgramTitleID() const; | 103 | u64 GetProgramTitleID() const; |
| 94 | u32 GetSystemUpdateVersion(); | 104 | u32 GetSystemUpdateVersion(); |
| @@ -123,6 +133,7 @@ private: | |||
| 123 | Loader::ResultStatus program_nca_status; | 133 | Loader::ResultStatus program_nca_status; |
| 124 | 134 | ||
| 125 | std::vector<VirtualDir> partitions; | 135 | std::vector<VirtualDir> partitions; |
| 136 | std::vector<VirtualFile> partitions_raw; | ||
| 126 | std::shared_ptr<NSP> secure_partition; | 137 | std::shared_ptr<NSP> secure_partition; |
| 127 | std::shared_ptr<NCA> program; | 138 | std::shared_ptr<NCA> program; |
| 128 | std::vector<std::shared_ptr<NCA>> ncas; | 139 | std::vector<std::shared_ptr<NCA>> ncas; |
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index a5259a593..846986736 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp | |||
| @@ -65,6 +65,9 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) { | |||
| 65 | std::string name( | 65 | std::string name( |
| 66 | reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset])); | 66 | reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset])); |
| 67 | 67 | ||
| 68 | offsets.insert_or_assign(name, content_offset + entry.offset); | ||
| 69 | sizes.insert_or_assign(name, entry.size); | ||
| 70 | |||
| 68 | pfs_files.emplace_back(std::make_shared<OffsetVfsFile>( | 71 | pfs_files.emplace_back(std::make_shared<OffsetVfsFile>( |
| 69 | file, entry.size, content_offset + entry.offset, std::move(name))); | 72 | file, entry.size, content_offset + entry.offset, std::move(name))); |
| 70 | } | 73 | } |
| @@ -78,6 +81,14 @@ Loader::ResultStatus PartitionFilesystem::GetStatus() const { | |||
| 78 | return status; | 81 | return status; |
| 79 | } | 82 | } |
| 80 | 83 | ||
| 84 | std::map<std::string, u64> PartitionFilesystem::GetFileOffsets() const { | ||
| 85 | return offsets; | ||
| 86 | } | ||
| 87 | |||
| 88 | std::map<std::string, u64> PartitionFilesystem::GetFileSizes() const { | ||
| 89 | return sizes; | ||
| 90 | } | ||
| 91 | |||
| 81 | std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const { | 92 | std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const { |
| 82 | return pfs_files; | 93 | return pfs_files; |
| 83 | } | 94 | } |
diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h index 248fdfdeb..279193b19 100644 --- a/src/core/file_sys/partition_filesystem.h +++ b/src/core/file_sys/partition_filesystem.h | |||
| @@ -29,6 +29,9 @@ public: | |||
| 29 | 29 | ||
| 30 | Loader::ResultStatus GetStatus() const; | 30 | Loader::ResultStatus GetStatus() const; |
| 31 | 31 | ||
| 32 | std::map<std::string, u64> GetFileOffsets() const; | ||
| 33 | std::map<std::string, u64> GetFileSizes() const; | ||
| 34 | |||
| 32 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; | 35 | std::vector<std::shared_ptr<VfsFile>> GetFiles() const override; |
| 33 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; | 36 | std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override; |
| 34 | std::string GetName() const override; | 37 | std::string GetName() const override; |
| @@ -80,6 +83,9 @@ private: | |||
| 80 | bool is_hfs = false; | 83 | bool is_hfs = false; |
| 81 | std::size_t content_offset = 0; | 84 | std::size_t content_offset = 0; |
| 82 | 85 | ||
| 86 | std::map<std::string, u64> offsets; | ||
| 87 | std::map<std::string, u64> sizes; | ||
| 88 | |||
| 83 | std::vector<VirtualFile> pfs_files; | 89 | std::vector<VirtualFile> pfs_files; |
| 84 | }; | 90 | }; |
| 85 | 91 | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index a968cfb5d..67c9a7c6d 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -245,10 +245,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 245 | 245 | ||
| 246 | button->setContextMenuPolicy(Qt::CustomContextMenu); | 246 | button->setContextMenuPolicy(Qt::CustomContextMenu); |
| 247 | connect(button, &QPushButton::clicked, [=] { | 247 | connect(button, &QPushButton::clicked, [=] { |
| 248 | HandleClick( | 248 | HandleClick(button_map[button_id], |
| 249 | button_map[button_id], | 249 | [=](Common::ParamPackage params) { |
| 250 | [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, | 250 | // Workaround for ZL & ZR for analog triggers like on XBOX controllors. |
| 251 | InputCommon::Polling::DeviceType::Button); | 251 | // Analog triggers (from controllers like the XBOX controller) would not |
| 252 | // work due to a different range of their signals (from 0 to 255 on | ||
| 253 | // analog triggers instead of -32768 to 32768 on analog joysticks). The | ||
| 254 | // SDL driver misinterprets analog triggers as analog joysticks. | ||
| 255 | // TODO: reinterpret the signal range for analog triggers to map the | ||
| 256 | // values correctly. This is required for the correct emulation of the | ||
| 257 | // analog triggers of the GameCube controller. | ||
| 258 | if (button_id == Settings::NativeButton::ZL || | ||
| 259 | button_id == Settings::NativeButton::ZR) { | ||
| 260 | params.Set("direction", "+"); | ||
| 261 | params.Set("threshold", "0.5"); | ||
| 262 | } | ||
| 263 | buttons_param[button_id] = std::move(params); | ||
| 264 | }, | ||
| 265 | InputCommon::Polling::DeviceType::Button); | ||
| 252 | }); | 266 | }); |
| 253 | connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { | 267 | connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { |
| 254 | QMenu context_menu; | 268 | QMenu context_menu; |