diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp index 10a344366..b52957d3f 100644 --- a/src/core/file_sys/archive_ncch.cpp +++ b/src/core/file_sys/archive_ncch.cpp @@ -63,7 +63,7 @@ ResultVal> NCCHArchive::OpenFile(const Path& path, std::memcpy(&openfile_path, binary.data(), sizeof(NCCHFilePath)); std::string file_path = - Service::AM::GetTitleContentPath(media_type, title_id, openfile_path.content_index); + Service::AM::GetTitleContentPath(media_type, title_id, openfile_path.content_index, false, true); auto ncch_container = NCCHContainer(file_path); Loader::ResultStatus result; diff --git a/src/core/file_sys/cia_container.cpp b/src/core/file_sys/cia_container.cpp index 69abbff23..f4bce8b02 100644 --- a/src/core/file_sys/cia_container.cpp +++ b/src/core/file_sys/cia_container.cpp @@ -201,7 +201,7 @@ u64 CIAContainer::GetTotalContentSize() const { u64 CIAContainer::GetContentSize(u16 index) const { // If the content doesn't exist in the CIA, it doesn't have a size. - if (!cia_header.isContentPresent(index)) + if (!cia_header.isContentPresent(cia_tmd.GetContentIndexByIndex(index))) return 0; return cia_tmd.GetContentSizeByIndex(index); diff --git a/src/core/file_sys/title_metadata.cpp b/src/core/file_sys/title_metadata.cpp index 8e0b6b30f..4122d5f8d 100644 --- a/src/core/file_sys/title_metadata.cpp +++ b/src/core/file_sys/title_metadata.cpp @@ -86,6 +86,7 @@ Loader::ResultStatus TitleMetadata::Load(const std::vector file_data, size_t memcpy(&chunk, &file_data[offset + body_end + (i * sizeof(ContentChunk))], sizeof(ContentChunk)); tmd_chunks.push_back(chunk); + content_index_to_index[chunk.index] = tmd_chunks.size() - 1; } return Loader::ResultStatus::Success; @@ -180,6 +181,10 @@ u32 TitleMetadata::GetContentIDByIndex(u16 index) const { return tmd_chunks[index].id; } +u16 TitleMetadata::GetContentIndexByIndex(u16 index) const { + return tmd_chunks[index].index; +} + u16 TitleMetadata::GetContentTypeByIndex(u16 index) const { return tmd_chunks[index].type; } @@ -188,6 +193,14 @@ u64 TitleMetadata::GetContentSizeByIndex(u16 index) const { return tmd_chunks[index].size; } +bool TitleMetadata::ContentIndexExists(u16 contentIndex) const { + return content_index_to_index.find(contentIndex) != content_index_to_index.end(); +} + +u16 TitleMetadata::ContentIndexToIndex(u16 contentIndex) const { + return content_index_to_index.at(contentIndex); +} + void TitleMetadata::SetTitleID(u64 title_id) { tmd_body.title_id = title_id; } @@ -206,6 +219,7 @@ void TitleMetadata::SetSystemVersion(u64 version) { void TitleMetadata::AddContentChunk(const ContentChunk& chunk) { tmd_chunks.push_back(chunk); + content_index_to_index[chunk.index] = tmd_chunks.size() - 1; } void TitleMetadata::Print() const { diff --git a/src/core/file_sys/title_metadata.h b/src/core/file_sys/title_metadata.h index 1d2302e0e..d9d32a5fe 100644 --- a/src/core/file_sys/title_metadata.h +++ b/src/core/file_sys/title_metadata.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include "common/common_types.h" @@ -106,8 +107,11 @@ public: u32 GetManualContentID() const; u32 GetDLPContentID() const; u32 GetContentIDByIndex(u16 index) const; + u16 GetContentIndexByIndex(u16 index) const; u16 GetContentTypeByIndex(u16 index) const; u64 GetContentSizeByIndex(u16 index) const; + bool ContentIndexExists(u16 contentIndex) const; + u16 ContentIndexToIndex(u16 contentIndex) const; void SetTitleID(u64 title_id); void SetTitleType(u32 type); @@ -122,6 +126,7 @@ private: u32_be signature_type; std::vector tmd_signature; std::vector tmd_chunks; + std::map content_index_to_index; }; } // namespace FileSys diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 89aa07ceb..ef38540ec 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -384,7 +384,7 @@ std::string GetTitleMetadataPath(Service::FS::MediaType media_type, u64 tid, boo } std::string GetTitleContentPath(Service::FS::MediaType media_type, u64 tid, u16 index, - bool update) { + bool update, bool contentIndex) { std::string content_path = GetTitlePath(media_type, tid) + "content/"; if (media_type == Service::FS::MediaType::GameCard) { @@ -399,6 +399,10 @@ std::string GetTitleContentPath(Service::FS::MediaType media_type, u64 tid, u16 u32 content_id = 0; FileSys::TitleMetadata tmd; if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) { + if(contentIndex && tmd.ContentIndexExists(index)) { + index = tmd.ContentIndexToIndex(index); + } + content_id = tmd.GetContentIDByIndex(index); // TODO(shinyquagsire23): how does DLC actually get this folder on hardware? @@ -525,14 +529,24 @@ void Module::Interface::FindDLCContentInfos(Kernel::HLERequestContext& ctx) { std::shared_ptr romfs_file; u64 romfs_offset = 0; + if (!tmd.ContentIndexExists(content_requested[i])) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); + rb.Push(-1); // TODO: Find the right error code + rb.PushMappedBuffer(content_requested_in); + rb.PushMappedBuffer(content_info_out); + return; + } + + u16 index = tmd.ContentIndexToIndex(content_requested[i]); + ContentInfo content_info = {}; content_info.index = static_cast(i); - content_info.type = tmd.GetContentTypeByIndex(content_requested[i]); - content_info.content_id = tmd.GetContentIDByIndex(content_requested[i]); - content_info.size = tmd.GetContentSizeByIndex(content_requested[i]); + content_info.type = tmd.GetContentTypeByIndex(index); + content_info.content_id = tmd.GetContentIDByIndex(index); + content_info.size = tmd.GetContentSizeByIndex(index); content_info.ownership = OWNERSHIP_OWNED; // TODO: Pull this from the ticket. - if (FileUtil::Exists(GetTitleContentPath(media_type, title_id, content_requested[i]))) { + if (FileUtil::Exists(GetTitleContentPath(media_type, title_id, index))) { content_info.ownership |= OWNERSHIP_DOWNLOADED; } @@ -917,7 +931,7 @@ void Module::Interface::CheckContentRights(Kernel::HLERequestContext& ctx) { // TODO(shinyquagsire23): Read tickets for this instead? bool has_rights = - FileUtil::Exists(GetTitleContentPath(Service::FS::MediaType::SDMC, tid, content_index)); + FileUtil::Exists(GetTitleContentPath(Service::FS::MediaType::SDMC, tid, content_index, false, true)); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); // No error @@ -933,7 +947,7 @@ void Module::Interface::CheckContentRightsIgnorePlatform(Kernel::HLERequestConte // TODO(shinyquagsire23): Read tickets for this instead? bool has_rights = - FileUtil::Exists(GetTitleContentPath(Service::FS::MediaType::SDMC, tid, content_index)); + FileUtil::Exists(GetTitleContentPath(Service::FS::MediaType::SDMC, tid, content_index, false, true)); IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); // No error diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 40414b6d6..53d8ea3a7 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -124,7 +124,7 @@ std::string GetTitleMetadataPath(Service::FS::MediaType media_type, u64 tid, boo * @returns string path to the .app file */ std::string GetTitleContentPath(Service::FS::MediaType media_type, u64 tid, u16 index = 0, - bool update = false); + bool update = false, bool contentIndex = false); /** * Get the folder for a title's installed content.