IOS/ES: Implement ES_GetOwnedTitles
This commit is contained in:
parent
35995e98d7
commit
b1ffbef5ce
|
@ -383,10 +383,16 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
||||||
return GetTitleID(request);
|
return GetTitleID(request);
|
||||||
case IOCTL_ES_SETUID:
|
case IOCTL_ES_SETUID:
|
||||||
return SetUID(request);
|
return SetUID(request);
|
||||||
|
|
||||||
|
case IOCTL_ES_GETOWNEDTITLECNT:
|
||||||
|
return GetOwnedTitleCount(request);
|
||||||
|
case IOCTL_ES_GETOWNEDTITLES:
|
||||||
|
return GetOwnedTitles(request);
|
||||||
case IOCTL_ES_GETTITLECNT:
|
case IOCTL_ES_GETTITLECNT:
|
||||||
return GetTitleCount(request);
|
return GetTitleCount(request);
|
||||||
case IOCTL_ES_GETTITLES:
|
case IOCTL_ES_GETTITLES:
|
||||||
return GetTitles(request);
|
return GetTitles(request);
|
||||||
|
|
||||||
case IOCTL_ES_GETVIEWCNT:
|
case IOCTL_ES_GETVIEWCNT:
|
||||||
return GetViewCount(request);
|
return GetViewCount(request);
|
||||||
case IOCTL_ES_GETVIEWS:
|
case IOCTL_ES_GETVIEWS:
|
||||||
|
@ -435,8 +441,6 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
|
||||||
return GetBoot2Version(request);
|
return GetBoot2Version(request);
|
||||||
case IOCTL_ES_DIGETTICKETVIEW:
|
case IOCTL_ES_DIGETTICKETVIEW:
|
||||||
return DIGetTicketView(request);
|
return DIGetTicketView(request);
|
||||||
case IOCTL_ES_GETOWNEDTITLECNT:
|
|
||||||
return GetOwnedTitleCount(request);
|
|
||||||
default:
|
default:
|
||||||
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
|
request.DumpUnknown(GetDeviceName(), LogTypes::IOS);
|
||||||
break;
|
break;
|
||||||
|
@ -927,6 +931,47 @@ static std::vector<u64> GetInstalledTitles()
|
||||||
return title_ids;
|
return title_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a vector of title IDs for which there is a ticket.
|
||||||
|
static std::vector<u64> GetTitlesWithTickets()
|
||||||
|
{
|
||||||
|
const std::string titles_dir = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/ticket";
|
||||||
|
if (!File::IsDirectory(titles_dir))
|
||||||
|
{
|
||||||
|
ERROR_LOG(IOS_ES, "/ticket is not a directory");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u64> title_ids;
|
||||||
|
|
||||||
|
// The /ticket directory contains one directory per title type, and each of them contains
|
||||||
|
// one ticket per title (where the name is the low 32 bits of the title ID in %08x format).
|
||||||
|
const auto& entries = File::ScanDirectoryTree(titles_dir, true);
|
||||||
|
for (const File::FSTEntry& title_type : entries.children)
|
||||||
|
{
|
||||||
|
if (!title_type.isDirectory || !IsValidPartOfTitleID(title_type.virtualName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (title_type.children.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const File::FSTEntry& ticket : title_type.children)
|
||||||
|
{
|
||||||
|
const std::string name_without_ext = ticket.virtualName.substr(0, 8);
|
||||||
|
if (ticket.isDirectory || !IsValidPartOfTitleID(name_without_ext) ||
|
||||||
|
name_without_ext + ".tik" != ticket.virtualName)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 type = std::stoul(title_type.virtualName, nullptr, 16);
|
||||||
|
const u32 identifier = std::stoul(name_without_ext, nullptr, 16);
|
||||||
|
title_ids.push_back(static_cast<u64>(type) << 32 | identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return title_ids;
|
||||||
|
}
|
||||||
|
|
||||||
IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request)
|
IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request)
|
||||||
{
|
{
|
||||||
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
|
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
|
||||||
|
@ -1529,9 +1574,26 @@ IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request)
|
||||||
if (!request.HasNumberOfValidVectors(0, 1))
|
if (!request.HasNumberOfValidVectors(0, 1))
|
||||||
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
INFO_LOG(IOS_ES, "IOCTL_ES_GETOWNEDTITLECNT");
|
const std::vector<u64> titles = GetTitlesWithTickets();
|
||||||
// TODO: unimplemented.
|
Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
|
||||||
Memory::Write_U32(0, request.io_vectors[0].address);
|
|
||||||
|
INFO_LOG(IOS_ES, "GetOwnedTitleCount: %zu titles", titles.size());
|
||||||
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCCommandResult ES::GetOwnedTitles(const IOCtlVRequest& request)
|
||||||
|
{
|
||||||
|
if (!request.HasNumberOfValidVectors(1, 1))
|
||||||
|
return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT);
|
||||||
|
|
||||||
|
const std::vector<u64> titles = GetTitlesWithTickets();
|
||||||
|
|
||||||
|
const size_t max_count = Memory::Read_U32(request.in_vectors[0].address);
|
||||||
|
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
|
||||||
|
{
|
||||||
|
Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * 8);
|
||||||
|
INFO_LOG(IOS_ES, " title %016" PRIx64, titles[i]);
|
||||||
|
}
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,8 +167,12 @@ private:
|
||||||
IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request);
|
IPCCommandResult GetTitleDirectory(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetTitleID(const IOCtlVRequest& request);
|
IPCCommandResult GetTitleID(const IOCtlVRequest& request);
|
||||||
IPCCommandResult SetUID(const IOCtlVRequest& request);
|
IPCCommandResult SetUID(const IOCtlVRequest& request);
|
||||||
|
|
||||||
|
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
|
||||||
|
IPCCommandResult GetOwnedTitles(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetTitleCount(const IOCtlVRequest& request);
|
IPCCommandResult GetTitleCount(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetTitles(const IOCtlVRequest& request);
|
IPCCommandResult GetTitles(const IOCtlVRequest& request);
|
||||||
|
|
||||||
IPCCommandResult GetViewCount(const IOCtlVRequest& request);
|
IPCCommandResult GetViewCount(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetViews(const IOCtlVRequest& request);
|
IPCCommandResult GetViews(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetTMDViewSize(const IOCtlVRequest& request);
|
IPCCommandResult GetTMDViewSize(const IOCtlVRequest& request);
|
||||||
|
@ -195,7 +199,6 @@ private:
|
||||||
IPCCommandResult Sign(const IOCtlVRequest& request);
|
IPCCommandResult Sign(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
|
IPCCommandResult GetBoot2Version(const IOCtlVRequest& request);
|
||||||
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
|
IPCCommandResult DIGetTicketView(const IOCtlVRequest& request);
|
||||||
IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request);
|
|
||||||
|
|
||||||
static bool LaunchIOS(u64 ios_title_id);
|
static bool LaunchIOS(u64 ios_title_id);
|
||||||
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);
|
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);
|
||||||
|
|
|
@ -158,7 +158,7 @@ CNANDContentLoader::~CNANDContentLoader()
|
||||||
|
|
||||||
bool CNANDContentLoader::IsValid() const
|
bool CNANDContentLoader::IsValid() const
|
||||||
{
|
{
|
||||||
return m_Valid && m_tmd.IsValid();
|
return m_Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SNANDContent* CNANDContentLoader::GetContentByID(u32 id) const
|
const SNANDContent* CNANDContentLoader::GetContentByID(u32 id) const
|
||||||
|
|
Loading…
Reference in New Issue