diff options
| author | 2018-10-29 16:20:10 -0400 | |
|---|---|---|
| committer | 2018-10-29 16:20:16 -0400 | |
| commit | bdaa76c0dbcf6811ae83bbca61ae103e06e93c27 (patch) | |
| tree | 786b213e1e82bbaeac60f422b87cd78bf72dc664 /src | |
| parent | fsp_srv: Implement ISaveDataInfoReader (diff) | |
| download | yuzu-bdaa76c0dbcf6811ae83bbca61ae103e06e93c27.tar.gz yuzu-bdaa76c0dbcf6811ae83bbca61ae103e06e93c27.tar.xz yuzu-bdaa76c0dbcf6811ae83bbca61ae103e06e93c27.zip | |
ns: Implement command 400: GetApplicationControlData
Returns the raw NACP bytes and the raw icon bytes into a title-provided buffer. Pulls from Registration Cache for control data, returning all zeros should it not exist.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/file_sys/savedata_factory.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/service/ns/ns.cpp | 64 |
4 files changed, 75 insertions, 17 deletions
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index 1ec54c78f..5434f2149 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -83,7 +83,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr | |||
| 83 | return MakeResult<VirtualDir>(std::move(out)); | 83 | return MakeResult<VirtualDir>(std::move(out)); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) { | 86 | VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) const { |
| 87 | return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space)); | 87 | return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space)); |
| 88 | } | 88 | } |
| 89 | 89 | ||
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index 024a305d3..2a0088040 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -52,7 +52,7 @@ public: | |||
| 52 | 52 | ||
| 53 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta); | 53 | ResultVal<VirtualDir> Open(SaveDataSpaceId space, SaveDataDescriptor meta); |
| 54 | 54 | ||
| 55 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space); | 55 | VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; |
| 56 | 56 | ||
| 57 | static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); | 57 | static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); |
| 58 | static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, | 58 | static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 3d1c2ecda..b9a1d5105 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -481,9 +481,9 @@ public: | |||
| 481 | // Write the data to memory | 481 | // Write the data to memory |
| 482 | ctx.WriteBuffer(begin, range_size); | 482 | ctx.WriteBuffer(begin, range_size); |
| 483 | 483 | ||
| 484 | IPC::ResponseBuilder rb{ctx, 4}; | 484 | IPC::ResponseBuilder rb{ctx, 3}; |
| 485 | rb.Push(RESULT_SUCCESS); | 485 | rb.Push(RESULT_SUCCESS); |
| 486 | rb.Push(actual_entries); | 486 | rb.Push<u32>(static_cast<u32>(actual_entries)); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | private: | 489 | private: |
| @@ -498,15 +498,6 @@ private: | |||
| 498 | return Common::swap64(out); | 498 | return Common::swap64(out); |
| 499 | } | 499 | } |
| 500 | 500 | ||
| 501 | static std::array<u8, 0x10> ArraySwap(const std::array<u8, 0x10>& in) { | ||
| 502 | std::array<u8, 0x10> out; | ||
| 503 | for (std::size_t i = 0; i < in.size(); ++i) { | ||
| 504 | out[0xF - i] = in[i]; | ||
| 505 | } | ||
| 506 | |||
| 507 | return out; | ||
| 508 | } | ||
| 509 | |||
| 510 | void FindAllSaves(FileSys::SaveDataSpaceId space) { | 501 | void FindAllSaves(FileSys::SaveDataSpaceId space) { |
| 511 | const auto save_root = OpenSaveDataSpace(space); | 502 | const auto save_root = OpenSaveDataSpace(space); |
| 512 | ASSERT(save_root.Succeeded()); | 503 | ASSERT(save_root.Succeeded()); |
| @@ -516,8 +507,9 @@ private: | |||
| 516 | for (const auto& save_id : type->GetSubdirectories()) { | 507 | for (const auto& save_id : type->GetSubdirectories()) { |
| 517 | for (const auto& user_id : save_id->GetSubdirectories()) { | 508 | for (const auto& user_id : save_id->GetSubdirectories()) { |
| 518 | const auto save_id_numeric = stoull_be(save_id->GetName()); | 509 | const auto save_id_numeric = stoull_be(save_id->GetName()); |
| 519 | const auto user_id_numeric = | 510 | auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName()); |
| 520 | ArraySwap(Common::HexStringToArray<0x10>(user_id->GetName())); | 511 | std::reverse(user_id_numeric.begin(), user_id_numeric.end()); |
| 512 | |||
| 521 | if (save_id_numeric != 0) { | 513 | if (save_id_numeric != 0) { |
| 522 | // System Save Data | 514 | // System Save Data |
| 523 | info.emplace_back(SaveDataInfo{ | 515 | info.emplace_back(SaveDataInfo{ |
| @@ -560,12 +552,16 @@ private: | |||
| 560 | for (const auto& title_id : user_id->GetSubdirectories()) { | 552 | for (const auto& title_id : user_id->GetSubdirectories()) { |
| 561 | if (!title_id->GetFiles().empty() || | 553 | if (!title_id->GetFiles().empty() || |
| 562 | !title_id->GetSubdirectories().empty()) { | 554 | !title_id->GetSubdirectories().empty()) { |
| 555 | auto user_id_numeric = | ||
| 556 | Common::HexStringToArray<0x10>(user_id->GetName()); | ||
| 557 | std::reverse(user_id_numeric.begin(), user_id_numeric.end()); | ||
| 558 | |||
| 563 | info.emplace_back(SaveDataInfo{ | 559 | info.emplace_back(SaveDataInfo{ |
| 564 | 0, | 560 | 0, |
| 565 | space, | 561 | space, |
| 566 | FileSys::SaveDataType::TemporaryStorage, | 562 | FileSys::SaveDataType::TemporaryStorage, |
| 567 | {}, | 563 | {}, |
| 568 | Common::HexStringToArray<0x10, true>(user_id->GetName()), | 564 | user_id_numeric, |
| 569 | stoull_be(type->GetName()), | 565 | stoull_be(type->GetName()), |
| 570 | stoull_be(title_id->GetName()), | 566 | stoull_be(title_id->GetName()), |
| 571 | title_id->GetSize(), | 567 | title_id->GetSize(), |
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 07c1381fe..1d2978f24 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -2,6 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/file_sys/control_metadata.h" | ||
| 7 | #include "core/file_sys/patch_manager.h" | ||
| 5 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 6 | #include "core/hle/kernel/hle_ipc.h" | 9 | #include "core/hle/kernel/hle_ipc.h" |
| 7 | #include "core/hle/service/ns/ns.h" | 10 | #include "core/hle/service/ns/ns.h" |
| @@ -118,7 +121,7 @@ public: | |||
| 118 | {305, nullptr, "TerminateSystemApplet"}, | 121 | {305, nullptr, "TerminateSystemApplet"}, |
| 119 | {306, nullptr, "LaunchOverlayApplet"}, | 122 | {306, nullptr, "LaunchOverlayApplet"}, |
| 120 | {307, nullptr, "TerminateOverlayApplet"}, | 123 | {307, nullptr, "TerminateOverlayApplet"}, |
| 121 | {400, nullptr, "GetApplicationControlData"}, | 124 | {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, |
| 122 | {401, nullptr, "InvalidateAllApplicationControlCache"}, | 125 | {401, nullptr, "InvalidateAllApplicationControlCache"}, |
| 123 | {402, nullptr, "RequestDownloadApplicationControlData"}, | 126 | {402, nullptr, "RequestDownloadApplicationControlData"}, |
| 124 | {403, nullptr, "GetMaxApplicationControlCacheCount"}, | 127 | {403, nullptr, "GetMaxApplicationControlCacheCount"}, |
| @@ -243,6 +246,65 @@ public: | |||
| 243 | 246 | ||
| 244 | RegisterHandlers(functions); | 247 | RegisterHandlers(functions); |
| 245 | } | 248 | } |
| 249 | |||
| 250 | void GetApplicationControlData(Kernel::HLERequestContext& ctx) { | ||
| 251 | IPC::RequestParser rp{ctx}; | ||
| 252 | const auto flag = rp.PopRaw<u64>(); | ||
| 253 | LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); | ||
| 254 | |||
| 255 | const auto title_id = rp.PopRaw<u64>(); | ||
| 256 | |||
| 257 | const auto size = ctx.GetWriteBufferSize(); | ||
| 258 | |||
| 259 | const FileSys::PatchManager pm{title_id}; | ||
| 260 | const auto control = pm.GetControlMetadata(); | ||
| 261 | |||
| 262 | std::vector<u8> out; | ||
| 263 | |||
| 264 | if (control.first != nullptr) { | ||
| 265 | if (size < 0x4000) { | ||
| 266 | LOG_ERROR(Service_NS, | ||
| 267 | "output buffer is too small! (actual={:016X}, expected_min=0x4000)", | ||
| 268 | size); | ||
| 269 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 270 | // TODO(DarkLordZach): Find a better error code for this. | ||
| 271 | rb.Push(ResultCode(-1)); | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | out.resize(0x4000); | ||
| 276 | const auto bytes = control.first->GetRawBytes(); | ||
| 277 | std::memcpy(out.data(), bytes.data(), bytes.size()); | ||
| 278 | } else { | ||
| 279 | LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", | ||
| 280 | title_id); | ||
| 281 | out.resize(std::min<u64>(0x4000, size)); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (control.second != nullptr) { | ||
| 285 | if (size < 0x4000 + control.second->GetSize()) { | ||
| 286 | LOG_ERROR(Service_NS, | ||
| 287 | "output buffer is too small! (actual={:016X}, expected_min={:016X})", | ||
| 288 | size, 0x4000 + control.second->GetSize()); | ||
| 289 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 290 | // TODO(DarkLordZach): Find a better error code for this. | ||
| 291 | rb.Push(ResultCode(-1)); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | |||
| 295 | out.resize(0x4000 + control.second->GetSize()); | ||
| 296 | control.second->Read(out.data() + 0x4000, control.second->GetSize()); | ||
| 297 | } else { | ||
| 298 | LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", | ||
| 299 | title_id); | ||
| 300 | } | ||
| 301 | |||
| 302 | ctx.WriteBuffer(out); | ||
| 303 | |||
| 304 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 305 | rb.Push(RESULT_SUCCESS); | ||
| 306 | rb.Push<u32>(static_cast<u32>(out.size())); | ||
| 307 | } | ||
| 246 | }; | 308 | }; |
| 247 | 309 | ||
| 248 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { | 310 | class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { |