From b04e39107fd947d59b76214747a81b8cb6fe92a8 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 28 Oct 2018 14:55:32 -0400 Subject: control_metadata: Add GetRawBytes function to NACP Returns the raw bytes of the NACP file. Needed for GetApplicationControlData which returns the raw, unprocessed NACP to the game. --- src/core/file_sys/control_metadata.cpp | 6 ++++++ src/core/file_sys/control_metadata.h | 1 + 2 files changed, 7 insertions(+) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index a012c2be9..c8fa912bf 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -66,4 +66,10 @@ std::string NACP::GetVersionString() const { return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), raw->version_string.size()); } + +std::vector NACP::GetRawBytes() const { + std::vector out(sizeof(RawNACP)); + std::memcpy(out.data(), raw.get(), sizeof(RawNACP)); + return out; +} } // namespace FileSys diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 141f7e056..bfaad46b4 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -81,6 +81,7 @@ public: u64 GetTitleId() const; u64 GetDLCBaseTitleId() const; std::string GetVersionString() const; + std::vector GetRawBytes() const; private: std::unique_ptr raw; -- cgit v1.2.3 From df264d2ccb39a4d7ffd4efd3158e66db3aa6952a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 28 Oct 2018 14:56:43 -0400 Subject: savedata_factory: Expose accessors for SaveDataSpace --- src/core/file_sys/savedata_factory.cpp | 32 +++++++++++++++----------- src/core/file_sys/savedata_factory.h | 3 +++ src/core/hle/service/filesystem/filesystem.cpp | 10 ++++++++ src/core/hle/service/filesystem/filesystem.h | 1 + 4 files changed, 32 insertions(+), 14 deletions(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index ef1aaebbb..1ec54c78f 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -83,28 +83,32 @@ ResultVal SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr return MakeResult(std::move(out)); } -std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, - u128 user_id, u64 save_id) { - // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should - // be interpreted as the title id of the current process. - if (type == SaveDataType::SaveData && title_id == 0) - title_id = Core::CurrentProcess()->GetTitleID(); - - std::string out; +VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) { + return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space)); +} +std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) { switch (space) { case SaveDataSpaceId::NandSystem: - out = "/system/"; - break; + return "/system/"; case SaveDataSpaceId::NandUser: - out = "/user/"; - break; + return "/user/"; case SaveDataSpaceId::TemporaryStorage: - out = "/temp/"; - break; + return "/temp/"; default: ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast(space)); + return "/unrecognized/"; ///< To prevent corruption when ignoring asserts. } +} + +std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, + u128 user_id, u64 save_id) { + // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should + // be interpreted as the title id of the current process. + if (type == SaveDataType::SaveData && title_id == 0) + title_id = Core::CurrentProcess()->GetTitleID(); + + std::string out = GetSaveDataSpaceIdPath(space); switch (type) { case SaveDataType::SystemSaveData: diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index d69ef6741..024a305d3 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h @@ -52,6 +52,9 @@ public: ResultVal Open(SaveDataSpaceId space, SaveDataDescriptor meta); + VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space); + + static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, u128 user_id, u64 save_id); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index e32a7c48e..ea8fd965a 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -309,6 +309,16 @@ ResultVal OpenSaveData(FileSys::SaveDataSpaceId space, return save_data_factory->Open(space, save_struct); } +ResultVal OpenSaveDataSpace(FileSys::SaveDataSpaceId space) { + LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", static_cast(space)); + + if (save_data_factory == nullptr) { + return ResultCode(ErrorModule::FS, FileSys::ErrCodes::TitleNotFound); + } + + return MakeResult(save_data_factory->GetSaveDataSpaceDirectory(space)); +} + ResultVal OpenSDMC() { LOG_TRACE(Service_FS, "Opening SDMC"); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 6ca5c5636..2cbb70c87 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -45,6 +45,7 @@ ResultVal OpenRomFS(u64 title_id, FileSys::StorageId stora FileSys::ContentRecordType type); ResultVal OpenSaveData(FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct); +ResultVal OpenSaveDataSpace(FileSys::SaveDataSpaceId space); ResultVal OpenSDMC(); std::unique_ptr GetUnionContents(); -- cgit v1.2.3 From bdaa76c0dbcf6811ae83bbca61ae103e06e93c27 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 29 Oct 2018 16:20:10 -0400 Subject: 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. --- src/core/file_sys/savedata_factory.cpp | 2 +- src/core/file_sys/savedata_factory.h | 2 +- src/core/hle/service/filesystem/fsp_srv.cpp | 24 +++++------ src/core/hle/service/ns/ns.cpp | 64 ++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 17 deletions(-) (limited to 'src/core/file_sys') 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 SaveDataFactory::Open(SaveDataSpaceId space, SaveDataDescr return MakeResult(std::move(out)); } -VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) { +VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) const { return dir->GetDirectoryRelative(GetSaveDataSpaceIdPath(space)); } 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: ResultVal Open(SaveDataSpaceId space, SaveDataDescriptor meta); - VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space); + VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); 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: // 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(static_cast(actual_entries)); } private: @@ -498,15 +498,6 @@ private: return Common::swap64(out); } - static std::array ArraySwap(const std::array& in) { - std::array 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(); + LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); + + const auto title_id = rp.PopRaw(); + + const auto size = ctx.GetWriteBufferSize(); + + const FileSys::PatchManager pm{title_id}; + const auto control = pm.GetControlMetadata(); + + std::vector 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(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(static_cast(out.size())); + } }; class IApplicationVersionInterface final : public ServiceFramework { -- cgit v1.2.3