diff options
| author | Zach Hilman <zachhilman@gmail.com> | 2018-10-29 16:20:10 -0400 | 
|---|---|---|
| committer | Zach Hilman <zachhilman@gmail.com> | 2018-10-29 16:20:16 -0400 | 
| commit | bdaa76c0dbcf6811ae83bbca61ae103e06e93c27 (patch) | |
| tree | 786b213e1e82bbaeac60f422b87cd78bf72dc664 /src/core/hle | |
| parent | 5ee19add1bf221bd5259e4df76089252f04ce060 (diff) | |
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/core/hle')
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 24 | ||||
| -rw-r--r-- | src/core/hle/service/ns/ns.cpp | 64 | 
2 files changed, 73 insertions, 15 deletions
| 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:          // Write the data to memory          ctx.WriteBuffer(begin, range_size); -        IPC::ResponseBuilder rb{ctx, 4}; +        IPC::ResponseBuilder rb{ctx, 3};          rb.Push(RESULT_SUCCESS); -        rb.Push(actual_entries); +        rb.Push<u32>(static_cast<u32>(actual_entries));      }  private: @@ -498,15 +498,6 @@ private:          return Common::swap64(out);      } -    static std::array<u8, 0x10> ArraySwap(const std::array<u8, 0x10>& in) { -        std::array<u8, 0x10> out; -        for (std::size_t i = 0; i < in.size(); ++i) { -            out[0xF - i] = in[i]; -        } - -        return out; -    } -      void FindAllSaves(FileSys::SaveDataSpaceId space) {          const auto save_root = OpenSaveDataSpace(space);          ASSERT(save_root.Succeeded()); @@ -516,8 +507,9 @@ private:                  for (const auto& save_id : type->GetSubdirectories()) {                      for (const auto& user_id : save_id->GetSubdirectories()) {                          const auto save_id_numeric = stoull_be(save_id->GetName()); -                        const auto user_id_numeric = -                            ArraySwap(Common::HexStringToArray<0x10>(user_id->GetName())); +                        auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName()); +                        std::reverse(user_id_numeric.begin(), user_id_numeric.end()); +                          if (save_id_numeric != 0) {                              // System Save Data                              info.emplace_back(SaveDataInfo{ @@ -560,12 +552,16 @@ private:                      for (const auto& title_id : user_id->GetSubdirectories()) {                          if (!title_id->GetFiles().empty() ||                              !title_id->GetSubdirectories().empty()) { +                            auto user_id_numeric = +                                Common::HexStringToArray<0x10>(user_id->GetName()); +                            std::reverse(user_id_numeric.begin(), user_id_numeric.end()); +                              info.emplace_back(SaveDataInfo{                                  0,                                  space,                                  FileSys::SaveDataType::TemporaryStorage,                                  {}, -                                Common::HexStringToArray<0x10, true>(user_id->GetName()), +                                user_id_numeric,                                  stoull_be(type->GetName()),                                  stoull_be(title_id->GetName()),                                  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 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/hle_ipc.h"  #include "core/hle/service/ns/ns.h" @@ -118,7 +121,7 @@ public:              {305, nullptr, "TerminateSystemApplet"},              {306, nullptr, "LaunchOverlayApplet"},              {307, nullptr, "TerminateOverlayApplet"}, -            {400, nullptr, "GetApplicationControlData"}, +            {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"},              {401, nullptr, "InvalidateAllApplicationControlCache"},              {402, nullptr, "RequestDownloadApplicationControlData"},              {403, nullptr, "GetMaxApplicationControlCacheCount"}, @@ -243,6 +246,65 @@ public:          RegisterHandlers(functions);      } + +    void GetApplicationControlData(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; +        const auto flag = rp.PopRaw<u64>(); +        LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); + +        const auto title_id = rp.PopRaw<u64>(); + +        const auto size = ctx.GetWriteBufferSize(); + +        const FileSys::PatchManager pm{title_id}; +        const auto control = pm.GetControlMetadata(); + +        std::vector<u8> out; + +        if (control.first != nullptr) { +            if (size < 0x4000) { +                LOG_ERROR(Service_NS, +                          "output buffer is too small! (actual={:016X}, expected_min=0x4000)", +                          size); +                IPC::ResponseBuilder rb{ctx, 2}; +                // TODO(DarkLordZach): Find a better error code for this. +                rb.Push(ResultCode(-1)); +                return; +            } + +            out.resize(0x4000); +            const auto bytes = control.first->GetRawBytes(); +            std::memcpy(out.data(), bytes.data(), bytes.size()); +        } else { +            LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", +                        title_id); +            out.resize(std::min<u64>(0x4000, size)); +        } + +        if (control.second != nullptr) { +            if (size < 0x4000 + control.second->GetSize()) { +                LOG_ERROR(Service_NS, +                          "output buffer is too small! (actual={:016X}, expected_min={:016X})", +                          size, 0x4000 + control.second->GetSize()); +                IPC::ResponseBuilder rb{ctx, 2}; +                // TODO(DarkLordZach): Find a better error code for this. +                rb.Push(ResultCode(-1)); +                return; +            } + +            out.resize(0x4000 + control.second->GetSize()); +            control.second->Read(out.data() + 0x4000, control.second->GetSize()); +        } else { +            LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", +                        title_id); +        } + +        ctx.WriteBuffer(out); + +        IPC::ResponseBuilder rb{ctx, 3}; +        rb.Push(RESULT_SUCCESS); +        rb.Push<u32>(static_cast<u32>(out.size())); +    }  };  class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { | 
