IOS/ES: Implement GetSharedContents (+ count)
Used by the system menu when importing a title from SD. These are probably the last two ioctlvs used by a major title.
This commit is contained in:
parent
1035a8b697
commit
b09561ece2
|
@ -356,6 +356,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
||||||
case IOCTL_ES_GETSTOREDCONTENTS:
|
case IOCTL_ES_GETSTOREDCONTENTS:
|
||||||
return GetTMDStoredContents(request);
|
return GetTMDStoredContents(request);
|
||||||
|
|
||||||
|
case IOCTL_ES_GETSHAREDCONTENTCNT:
|
||||||
|
return GetSharedContentsCount(request);
|
||||||
|
case IOCTL_ES_GETSHAREDCONTENTS:
|
||||||
|
return GetSharedContents(request);
|
||||||
|
|
||||||
case IOCTL_ES_GETVIEWCNT:
|
case IOCTL_ES_GETVIEWCNT:
|
||||||
return GetTicketViewCount(request);
|
return GetTicketViewCount(request);
|
||||||
case IOCTL_ES_GETVIEWS:
|
case IOCTL_ES_GETVIEWS:
|
||||||
|
|
|
@ -214,6 +214,8 @@ private:
|
||||||
IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request);
|
IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
|
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
|
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
|
||||||
|
IPCCommandResult GetSharedContentsCount(const IOCtlVRequest& request) const;
|
||||||
|
IPCCommandResult GetSharedContents(const IOCtlVRequest& request) const;
|
||||||
|
|
||||||
// Views for tickets and TMDs
|
// Views for tickets and TMDs
|
||||||
IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request);
|
IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request);
|
||||||
|
|
|
@ -385,6 +385,16 @@ std::string SharedContentMap::GetFilenameFromSHA1(const std::array<u8, 20>& sha1
|
||||||
return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str());
|
return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::array<u8, 20>> SharedContentMap::GetHashes() const
|
||||||
|
{
|
||||||
|
std::vector<std::array<u8, 20>> hashes;
|
||||||
|
hashes.reserve(m_entries.size());
|
||||||
|
for (const auto& content_entry : m_entries)
|
||||||
|
hashes.emplace_back(content_entry.sha1);
|
||||||
|
|
||||||
|
return hashes;
|
||||||
|
}
|
||||||
|
|
||||||
std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
|
std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
|
||||||
{
|
{
|
||||||
std::string filename = GetFilenameFromSHA1(sha1);
|
std::string filename = GetFilenameFromSHA1(sha1);
|
||||||
|
|
|
@ -204,6 +204,7 @@ public:
|
||||||
|
|
||||||
std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
||||||
std::string AddSharedContent(const std::array<u8, 20>& sha1);
|
std::string AddSharedContent(const std::array<u8, 20>& sha1);
|
||||||
|
std::vector<std::array<u8, 20>> GetHashes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Entry;
|
struct Entry;
|
||||||
|
|
|
@ -163,6 +163,23 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
|
||||||
return stored_contents;
|
return stored_contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetSharedContentsCount()
|
||||||
|
{
|
||||||
|
const std::string shared1_path = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/shared1";
|
||||||
|
const auto entries = File::ScanDirectoryTree(shared1_path, false);
|
||||||
|
return static_cast<u32>(
|
||||||
|
std::count_if(entries.children.begin(), entries.children.end(), [](const auto& entry) {
|
||||||
|
return !entry.isDirectory && entry.virtualName.size() == 12 &&
|
||||||
|
entry.virtualName.compare(8, 4, ".app") == 0;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::array<u8, 20>> GetSharedContents()
|
||||||
|
{
|
||||||
|
const IOS::ES::SharedContentMap map{Common::FROM_SESSION_ROOT};
|
||||||
|
return map.GetHashes();
|
||||||
|
}
|
||||||
|
|
||||||
bool InitImport(u64 title_id)
|
bool InitImport(u64 title_id)
|
||||||
{
|
{
|
||||||
const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT);
|
const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
@ -27,6 +28,9 @@ std::vector<u64> GetTitlesWithTickets();
|
||||||
|
|
||||||
std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd);
|
std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd);
|
||||||
|
|
||||||
|
u32 GetSharedContentsCount();
|
||||||
|
std::vector<std::array<u8, 20>> GetSharedContents();
|
||||||
|
|
||||||
// Start a title import.
|
// Start a title import.
|
||||||
bool InitImport(u64 title_id);
|
bool InitImport(u64 title_id);
|
||||||
// Clean up the import content directory and move it back to /title.
|
// Clean up the import content directory and move it back to /title.
|
||||||
|
|
|
@ -205,6 +205,35 @@ IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request)
|
||||||
Memory::Write_U32(4, request.io_vectors[0].address);
|
Memory::Write_U32(4, request.io_vectors[0].address);
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPCCommandResult ES::GetSharedContentsCount(const IOCtlVRequest& request) const
|
||||||
|
{
|
||||||
|
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
const u32 count = IOS::ES::GetSharedContentsCount();
|
||||||
|
Memory::Write_U32(count, request.io_vectors[0].address);
|
||||||
|
|
||||||
|
INFO_LOG(IOS_ES, "GetSharedContentsCount: %u contents", count);
|
||||||
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult ES::GetSharedContents(const IOCtlVRequest& request) const
|
||||||
|
{
|
||||||
|
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
if (request.io_vectors[0].size != 20 * max_count)
|
||||||
|
return GetDefaultReply(ES_EINVAL);
|
||||||
|
|
||||||
|
const std::vector<std::array<u8, 20>> hashes = IOS::ES::GetSharedContents();
|
||||||
|
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
|
||||||
|
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
|
||||||
|
|
||||||
|
INFO_LOG(IOS_ES, "GetSharedContents: %u contents (%u requested)", count, max_count);
|
||||||
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
}
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
|
Loading…
Reference in New Issue