summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-10-29 16:20:10 -0400
committerGravatar Zach Hilman2018-10-29 16:20:16 -0400
commitbdaa76c0dbcf6811ae83bbca61ae103e06e93c27 (patch)
tree786b213e1e82bbaeac60f422b87cd78bf72dc664 /src
parentfsp_srv: Implement ISaveDataInfoReader (diff)
downloadyuzu-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.cpp2
-rw-r--r--src/core/file_sys/savedata_factory.h2
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp24
-rw-r--r--src/core/hle/service/ns/ns.cpp64
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
86VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) { 86VirtualDir 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
489private: 489private:
@@ -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
248class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { 310class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {