diff --git a/libraries/libstratosphere/include/stratosphere/fs.hpp b/libraries/libstratosphere/include/stratosphere/fs.hpp index 7aafab832..13b7603d1 100644 --- a/libraries/libstratosphere/include/stratosphere/fs.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs.hpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_program_id.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_program_id.hpp new file mode 100644 index 000000000..e2f000002 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_program_id.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include + +namespace ams::fs { + + /* ACCURATE_TO_VERSION: 17.5.0.0 */ + Result GetProgramId(ncm::ProgramId *out, const char *path, fs::ContentAttributes attr); + +} \ No newline at end of file diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp index c05920cc8..0ddba8f7c 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp @@ -104,6 +104,7 @@ namespace ams::fssrv { Result GetRightsId(ams::sf::Out out, ncm::ProgramId program_id, ncm::StorageId storage_id); Result RegisterExternalKey(const fs::RightsId &rights_id, const spl::AccessKey &access_key); Result UnregisterAllExternalKey(); + Result GetProgramId(ams::sf::Out out, const fssrv::sf::FspPath &path, fs::ContentAttributes attr); Result GetRightsIdByPath(ams::sf::Out out, const fssrv::sf::FspPath &path); Result GetRightsIdAndKeyGenerationByPathObsolete(ams::sf::Out out, ams::sf::Out out_key_generation, const fssrv::sf::FspPath &path); Result GetRightsIdAndKeyGenerationByPath(ams::sf::Out out, ams::sf::Out out_key_generation, const fssrv::sf::FspPath &path, fs::ContentAttributes attr); diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp index 5e8fade2f..ba41abb80 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/sf/fssrv_sf_i_file_system_proxy.hpp @@ -115,6 +115,7 @@ AMS_SF_METHOD_INFO(C, H, 615, Result, QuerySaveDataInternalStorageTotalSize, (), (), hos::Version_5_0_0) \ AMS_SF_METHOD_INFO(C, H, 616, Result, GetSaveDataCommitId, (), (), hos::Version_6_0_0) \ AMS_SF_METHOD_INFO(C, H, 617, Result, UnregisterExternalKey, (const fs::RightsId &rights_id), (rights_id), hos::Version_7_0_0) \ + AMS_SF_METHOD_INFO(C, H, 618, Result, GetProgramId, (ams::sf::Out out, const fssrv::sf::FspPath &path, fs::ContentAttributes attr), (out, path, attr), hos::Version_17_0_0) \ AMS_SF_METHOD_INFO(C, H, 620, Result, SetSdCardEncryptionSeed, (const fs::EncryptionSeed &seed), (seed), hos::Version_2_0_0) \ AMS_SF_METHOD_INFO(C, H, 630, Result, SetSdCardAccessibility, (bool accessible), (accessible), hos::Version_4_0_0) \ AMS_SF_METHOD_INFO(C, H, 631, Result, IsSdCardAccessible, (ams::sf::Out out), (out), hos::Version_4_0_0) \ diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp index b00fe8cb1..4b7ac2ba8 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta.hpp @@ -16,6 +16,7 @@ #pragma once #include #include +#include #include #include #include @@ -58,7 +59,7 @@ namespace ams::ncm { u16 content_count; u16 content_meta_count; u8 attributes; - StorageId storage_id; + ContentMetaPlatform platform; }; static_assert(sizeof(ContentMetaHeader) == 0x8); @@ -67,7 +68,7 @@ namespace ams::ncm { u64 id; u32 version; ContentMetaType type; - u8 reserved_0D; + ContentMetaPlatform platform; u16 extended_header_size; u16 content_count; u16 content_meta_count; @@ -79,7 +80,6 @@ namespace ams::ncm { u8 reserved_1C[4]; }; static_assert(sizeof(PackagedContentMetaHeader) == 0x20); - static_assert(AMS_OFFSETOF(PackagedContentMetaHeader, reserved_0D) == 0x0D); static_assert(AMS_OFFSETOF(PackagedContentMetaHeader, reserved_1C) == 0x1C); using InstallContentMetaHeader = PackagedContentMetaHeader; diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp index 947fbfaad..fde547802 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp @@ -221,6 +221,11 @@ namespace ams::ncm { AMS_ASSERT(m_interface != nullptr); R_RETURN(m_interface->GetContentInfoByTypeAndIdOffset(out_content_info, key, type, id_offset)); } + + Result GetPlatform(ContentMetaPlatform *out, const ContentMetaKey &key) { + AMS_ASSERT(m_interface != nullptr); + R_RETURN(m_interface->GetPlatform(out, key)); + } }; } diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_platform.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_platform.hpp new file mode 100644 index 000000000..2a08d8419 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_platform.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::ncm { + + enum class ContentMetaPlatform : u8 { + Nx = 0x0, + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp index a7ad71aca..64512681b 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_storage.hpp @@ -207,6 +207,11 @@ namespace ams::ncm { R_RETURN(m_interface->GetRightsIdFromPlaceHolderIdWithCacheDeprecated(out_rights_id, cache_content_id, placeholder_id)); } } + + Result GetProgramId(ncm::ProgramId *out, ContentId content_id, fs::ContentAttributes attr) { + AMS_ASSERT(m_interface != nullptr); + R_RETURN(m_interface->GetProgramId(out, content_id, attr)); + } }; } diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_meta_database.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_meta_database.hpp index 411701b79..099de50fb 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_meta_database.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_meta_database.hpp @@ -43,7 +43,8 @@ AMS_SF_METHOD_INFO(C, H, 22, Result, GetOwnerApplicationId, (sf::Out out_id, const ncm::ContentMetaKey &key), (out_id, key), hos::Version_10_0_0) \ AMS_SF_METHOD_INFO(C, H, 23, Result, GetContentAccessibilities, (sf::Out out_accessibilities, const ncm::ContentMetaKey &key), (out_accessibilities, key), hos::Version_15_0_0) \ AMS_SF_METHOD_INFO(C, H, 24, Result, GetContentInfoByType, (sf::Out out_content_info, const ncm::ContentMetaKey &key, ncm::ContentType type), (out_content_info, key, type), hos::Version_15_0_0) \ - AMS_SF_METHOD_INFO(C, H, 25, Result, GetContentInfoByTypeAndIdOffset, (sf::Out out_content_info, const ncm::ContentMetaKey &key, ncm::ContentType type, u8 id_offset), (out_content_info, key, type, id_offset), hos::Version_15_0_0) + AMS_SF_METHOD_INFO(C, H, 25, Result, GetContentInfoByTypeAndIdOffset, (sf::Out out_content_info, const ncm::ContentMetaKey &key, ncm::ContentType type, u8 id_offset), (out_content_info, key, type, id_offset), hos::Version_15_0_0) \ + AMS_SF_METHOD_INFO(C, H, 26, Result, GetPlatform, (sf::Out out, const ncm::ContentMetaKey &key), (out, key), hos::Version_17_0_0) AMS_SF_DEFINE_INTERFACE(ams::ncm, IContentMetaDatabase, AMS_NCM_I_CONTENT_META_DATABASE_INTERFACE_INFO, 0x58021FEC) diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp index 250e84dc9..3ea0b73fb 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_i_content_storage.hpp @@ -58,6 +58,7 @@ AMS_SF_METHOD_INFO(C, H, 27, Result, GetRightsIdFromPlaceHolderIdWithCacheDeprecated, (sf::Out out_rights_id, ncm::ContentId cache_content_id, ncm::PlaceHolderId placeholder_id), (out_rights_id, cache_content_id, placeholder_id), hos::Version_8_0_0, hos::Version_15_0_1) \ AMS_SF_METHOD_INFO(C, H, 27, Result, GetRightsIdFromPlaceHolderIdWithCache, (sf::Out out_rights_id, ncm::PlaceHolderId placeholder_id, ncm::ContentId cache_content_id, fs::ContentAttributes attr), (out_rights_id, placeholder_id, cache_content_id, attr), hos::Version_16_0_0) \ AMS_SF_METHOD_INFO(C, H, 28, Result, RegisterPath, (const ncm::ContentId &content_id, const ncm::Path &path), (content_id, path), hos::Version_13_0_0) \ - AMS_SF_METHOD_INFO(C, H, 29, Result, ClearRegisteredPath, (), (), hos::Version_13_0_0) + AMS_SF_METHOD_INFO(C, H, 29, Result, ClearRegisteredPath, (), (), hos::Version_13_0_0) \ + AMS_SF_METHOD_INFO(C, H, 30, Result, GetProgramId, (sf::Out out, ncm::ContentId content_id, fs::ContentAttributes attr), (out, content_id, attr), hos::Version_17_0_0) AMS_SF_DEFINE_INTERFACE(ams::ncm, IContentStorage, AMS_NCM_I_CONTENT_STORAGE_INTERFACE_INFO, 0xFEAE3DD1) diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp index 05ebe160d..38bfc154f 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp @@ -71,6 +71,7 @@ namespace ams::ncm { Result GetContentAccessibilities(sf::Out out_accessibilities, const ContentMetaKey &key); Result GetContentInfoByType(sf::Out out_content_info, const ContentMetaKey &key, ContentType type); Result GetContentInfoByTypeAndIdOffset(sf::Out out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset); + Result GetPlatform(sf::Out out, const ContentMetaKey &key); }; static_assert(ncm::IsIContentMetaDatabase); diff --git a/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_storage_impl.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_storage_impl.hpp index f29c3e0f4..40a3063d0 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_storage_impl.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_storage_impl.hpp @@ -79,6 +79,7 @@ namespace ams::ncm { Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr); Result RegisterPath(const ContentId &content_id, const Path &path); Result ClearRegisteredPath(); + Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr); /* 16.0.0 Alignment change hacks. */ Result CreatePlaceHolder_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id, s64 size) { R_RETURN(this->CreatePlaceHolder(placeholder_id, content_id, size)); } diff --git a/libraries/libstratosphere/source/fs/fs_program_id.cpp b/libraries/libstratosphere/source/fs/fs_program_id.cpp new file mode 100644 index 000000000..3ef64dae7 --- /dev/null +++ b/libraries/libstratosphere/source/fs/fs_program_id.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include "impl/fs_file_system_proxy_service_object.hpp" + +namespace ams::fs { + + Result GetProgramId(ncm::ProgramId *out, const char *path, fs::ContentAttributes attr) { + AMS_FS_R_UNLESS(out != nullptr, fs::ResultNullptrArgument()); + AMS_FS_R_UNLESS(path != nullptr, fs::ResultNullptrArgument()); + + /* Convert the path for fsp. */ + fssrv::sf::FspPath sf_path; + R_TRY(fs::ConvertToFspPath(std::addressof(sf_path), path)); + + auto fsp = impl::GetFileSystemProxyServiceObject(); + AMS_FS_R_TRY(fsp->GetProgramId(out, sf_path, attr)); + + R_SUCCEED(); + } + +} \ No newline at end of file diff --git a/libraries/libstratosphere/source/fs/fs_remote_file_system_proxy.hpp b/libraries/libstratosphere/source/fs/fs_remote_file_system_proxy.hpp index f7eda97ad..ae9b8b492 100644 --- a/libraries/libstratosphere/source/fs/fs_remote_file_system_proxy.hpp +++ b/libraries/libstratosphere/source/fs/fs_remote_file_system_proxy.hpp @@ -320,6 +320,10 @@ namespace ams::fs { AMS_ABORT("TODO"); } + Result GetProgramId(ams::sf::Out out, const fssrv::sf::FspPath &path, fs::ContentAttributes attr) { + static_assert(sizeof(ncm::ProgramId) == sizeof(u64)); + R_RETURN(fsGetProgramId(reinterpret_cast(out.GetPointer()), path.str, static_cast<::FsContentAttributes>(static_cast(attr)))); + } Result GetRightsIdByPath(ams::sf::Out out, const fssrv::sf::FspPath &path) { static_assert(sizeof(RightsId) == sizeof(::FsRightsId)); diff --git a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp index c1e99b108..2922a2c1c 100644 --- a/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp +++ b/libraries/libstratosphere/source/fs/impl/fs_id_string_impl.os.generic.cpp @@ -21,7 +21,7 @@ namespace ams::fs::impl { #define ADD_ENUM_CASE(v) case v: return #v template<> const char *IdString::ToString(pkg1::KeyGeneration id) { - static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_16_0_0); + static_assert(pkg1::KeyGeneration_Current == pkg1::KeyGeneration_17_0_0); switch (id) { using enum pkg1::KeyGeneration; case KeyGeneration_1_0_0: return "1.0.0-2.3.0"; @@ -39,7 +39,8 @@ namespace ams::fs::impl { case KeyGeneration_13_0_0: return "13.0.0-13.2.1"; case KeyGeneration_14_0_0: return "14.0.0-14.1.2"; case KeyGeneration_15_0_0: return "15.0.0-15.0.1"; - case KeyGeneration_16_0_0: return "16.0.0-"; + case KeyGeneration_16_0_0: return "16.0.0-16.0.3"; + case KeyGeneration_17_0_0: return "17.0.0-"; default: return "Unknown"; } } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_meta.cpp b/libraries/libstratosphere/source/ncm/ncm_content_meta.cpp index c505ecbd8..02f648a50 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta.cpp @@ -26,6 +26,7 @@ namespace ams::ncm { .content_count = src.content_count, .content_meta_count = src.content_meta_count, .attributes = src.attributes, + .platform = src.platform, }; } @@ -42,6 +43,7 @@ namespace ams::ncm { .content_count = src.content_count, .content_meta_count = src.content_meta_count, .attributes = src.attributes, + .platform = src.platform, }; } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp index 8b84f9114..da23ce454 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp @@ -518,4 +518,20 @@ namespace ams::ncm { R_RETURN(this->GetContentInfoImpl(out_content_info.GetPointer(), key, type, util::make_optional(id_offset))); } + Result ContentMetaDatabaseImpl::GetPlatform(sf::Out out, const ContentMetaKey &key) { + R_TRY(this->EnsureEnabled()); + + /* Obtain the content meta for the key. */ + const void *meta; + size_t meta_size; + R_TRY(this->GetContentMetaPointer(&meta, &meta_size, key)); + + /* Create a reader. */ + ContentMetaReader reader(meta, meta_size); + + /* Set the ouput value. */ + out.SetValue(reader.GetHeader()->platform); + R_SUCCEED(); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp index 7b51783cc..9d6bcfb46 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp @@ -64,6 +64,7 @@ namespace ams::ncm { virtual Result GetContentAccessibilities(sf::Out out_accessibilities, const ContentMetaKey &key) override; virtual Result GetContentInfoByType(sf::Out out_content_info, const ContentMetaKey &key, ContentType type) override; virtual Result GetContentInfoByTypeAndIdOffset(sf::Out out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset) override; + virtual Result GetPlatform(sf::Out out, const ContentMetaKey &key) override; }; } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl_base.hpp b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl_base.hpp index d89483d80..7c0d57c30 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl_base.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl_base.hpp @@ -80,6 +80,7 @@ namespace ams::ncm { virtual Result GetContentAccessibilities(sf::Out out_accessibilities, const ContentMetaKey &key) = 0; virtual Result GetContentInfoByType(sf::Out out_content_info, const ContentMetaKey &key, ContentType type) = 0; virtual Result GetContentInfoByTypeAndIdOffset(sf::Out out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset) = 0; + virtual Result GetPlatform(sf::Out out, const ContentMetaKey &key) = 0; }; static_assert(ncm::IsIContentMetaDatabase); diff --git a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp index 0a8359d93..db0387503 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.cpp @@ -918,4 +918,19 @@ namespace ams::ncm { R_THROW(ncm::ResultInvalidOperation()); } + Result ContentStorageImpl::GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) { + R_TRY(this->EnsureEnabled()); + + /* Get the path of the content. */ + Path path; + R_TRY(this->GetPath(std::addressof(path), content_id)); + + /* Obtain the program id for the content. */ + ncm::ProgramId program_id; + R_TRY(fs::GetProgramId(std::addressof(program_id), path.str, attr)); + + out.SetValue(program_id); + R_SUCCEED(); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.hpp index b9b9b7455..5f9ae6904 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl.hpp @@ -105,6 +105,7 @@ namespace ams::ncm { virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr) override; virtual Result RegisterPath(const ContentId &content_id, const Path &path) override; virtual Result ClearRegisteredPath() override; + virtual Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) override; }; } diff --git a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl_base.hpp b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl_base.hpp index 52f21022b..945d41683 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_storage_impl_base.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_storage_impl_base.hpp @@ -79,6 +79,7 @@ namespace ams::ncm { virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr) = 0; virtual Result RegisterPath(const ContentId &content_id, const Path &path) = 0; virtual Result ClearRegisteredPath() = 0; + virtual Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) = 0; /* 16.0.0 Alignment change hacks. */ Result CreatePlaceHolder_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id, s64 size) { R_RETURN(this->CreatePlaceHolder(placeholder_id, content_id, size)); } diff --git a/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.cpp index 3ae075e09..592a2df3f 100644 --- a/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.cpp @@ -224,4 +224,27 @@ namespace ams::ncm { R_SUCCEED(); } + Result HostContentStorageImpl::GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) { + R_TRY(this->EnsureEnabled()); + + /* Get the content path. */ + Path path; + R_TRY(m_registered_content->GetPath(std::addressof(path), content_id)); + + /* Check for correct extension. */ + const auto path_len = std::strlen(path.str); + const char *extension = path.str + path_len - 1; + if (*extension == '/') { + --extension; + } + R_UNLESS(path_len >= 4 && std::memcmp(extension - 4, ".ncd", 4) == 0, ncm::ResultInvalidContentMetaDirectory()); + + /* Obtain the program id for the content. */ + ncm::ProgramId program_id; + R_TRY(fs::GetProgramId(std::addressof(program_id), path.str, attr)); + + out.SetValue(program_id); + R_SUCCEED(); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.hpp index 7b4472c74..4a54063b3 100644 --- a/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_host_content_storage_impl.hpp @@ -77,6 +77,7 @@ namespace ams::ncm { Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr); Result RegisterPath(const ContentId &content_id, const Path &path); Result ClearRegisteredPath(); + Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr); /* 16.0.0 Alignment change hacks. */ Result CreatePlaceHolder_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id, s64 size) { R_RETURN(this->CreatePlaceHolder(placeholder_id, content_id, size)); } diff --git a/libraries/libstratosphere/source/ncm/ncm_integrated_content_meta_database_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_integrated_content_meta_database_impl.cpp index 2a0ca8f51..b498464cf 100644 --- a/libraries/libstratosphere/source/ncm/ncm_integrated_content_meta_database_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_integrated_content_meta_database_impl.cpp @@ -446,4 +446,21 @@ namespace ams::ncm { })); } + Result IntegratedContentMetaDatabaseImpl::GetPlatform(sf::Out out, const ContentMetaKey &key) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Check that we're enabled. */ + R_TRY(this->EnsureEnabled()); + + /* Check that our list has interfaces to check. */ + R_UNLESS(m_list.GetCount() > 0, ncm::ResultContentMetaNotFound()); + + /* Check each interface in turn. */ + R_RETURN(m_list.TryEach([&](const auto &data) { + /* Try the current interface. */ + R_RETURN(data.interface->GetPlatform(out, key)); + })); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_integrated_content_storage_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_integrated_content_storage_impl.cpp index 6c7436f44..1853e6b89 100644 --- a/libraries/libstratosphere/source/ncm/ncm_integrated_content_storage_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_integrated_content_storage_impl.cpp @@ -326,4 +326,31 @@ namespace ams::ncm { R_THROW(ncm::ResultInvalidOperation()); } + Result IntegratedContentStorageImpl::GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Check that we're enabled. */ + R_TRY(this->EnsureEnabled()); + + /* Check that our list has interfaces to check. */ + R_UNLESS(m_list.GetCount() > 0, ncm::ResultContentNotFound()); + + /* Check each interface in turn. */ + R_TRY(m_list.TryEach([&](const auto &data) { + /* Check if the current interface has it. */ + bool has; + R_TRY(data.interface->Has(std::addressof(has), content_id)); + + /* If it doesn't, continue on. */ + R_UNLESS(has, ncm::ResultContentNotFound()); + + + /* If it does, read the file. */ + R_RETURN(data.interface->GetProgramId(out, content_id, attr)); + })); + + R_SUCCEED(); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.cpp index 635730585..a25f23b1d 100644 --- a/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.cpp @@ -297,4 +297,19 @@ namespace ams::ncm { R_THROW(ncm::ResultInvalidOperation()); } + Result ReadOnlyContentStorageImpl::GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) { + R_TRY(this->EnsureEnabled()); + + /* Get the path of the content. */ + Path path; + R_TRY(this->GetPath(std::addressof(path), content_id)); + + /* Obtain the program id for the content. */ + ncm::ProgramId program_id; + R_TRY(fs::GetProgramId(std::addressof(program_id), path.str, attr)); + + out.SetValue(program_id); + R_SUCCEED(); + } + } diff --git a/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.hpp index f42c630da..c00a3ae11 100644 --- a/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_read_only_content_storage_impl.hpp @@ -58,6 +58,7 @@ namespace ams::ncm { virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr) override; virtual Result RegisterPath(const ContentId &content_id, const Path &path) override; virtual Result ClearRegisteredPath() override; + virtual Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) override; }; } diff --git a/libraries/libstratosphere/source/ncm/ncm_remote_content_meta_database_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_remote_content_meta_database_impl.hpp index 0919d6d45..a0d8a4286 100644 --- a/libraries/libstratosphere/source/ncm/ncm_remote_content_meta_database_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_remote_content_meta_database_impl.hpp @@ -186,6 +186,11 @@ namespace ams::ncm { AMS_UNUSED(out_content_info, key, type, id_offset); AMS_ABORT(); } + + Result GetPlatform(sf::Out out, const ContentMetaKey &key) { + static_assert(sizeof(ncm::ContentMetaPlatform) == sizeof(u8)); + R_RETURN(ncmContentMetaDatabaseGetPlatform(std::addressof(m_srv), reinterpret_cast(out.GetPointer()), Convert(key))); + } }; static_assert(ncm::IsIContentMetaDatabase); #endif diff --git a/libraries/libstratosphere/source/ncm/ncm_remote_content_storage_impl.hpp b/libraries/libstratosphere/source/ncm/ncm_remote_content_storage_impl.hpp index ac809a5e6..87c88bbdc 100644 --- a/libraries/libstratosphere/source/ncm/ncm_remote_content_storage_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_remote_content_storage_impl.hpp @@ -219,6 +219,11 @@ namespace ams::ncm { R_RETURN(ncmContentStorageClearRegisteredPath(std::addressof(m_srv))); } + Result GetProgramId(sf::Out out, ContentId content_id, fs::ContentAttributes attr) { + static_assert(sizeof(ncm::ProgramId) == sizeof(u64)); + R_RETURN(ncmContentStorageGetProgramId(std::addressof(m_srv), reinterpret_cast(out.GetPointer()), Convert(content_id), Convert(attr))); + } + /* 16.0.0 Alignment change hacks. */ Result CreatePlaceHolder_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id, s64 size) { R_RETURN(this->CreatePlaceHolder(placeholder_id, content_id, size)); } Result Register_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id) { R_RETURN(this->Register(placeholder_id, content_id)); } diff --git a/libraries/libvapours/include/vapours/results/ncm_results.hpp b/libraries/libvapours/include/vapours/results/ncm_results.hpp index 45d7c3a0a..2092cf0ce 100644 --- a/libraries/libvapours/include/vapours/results/ncm_results.hpp +++ b/libraries/libvapours/include/vapours/results/ncm_results.hpp @@ -54,6 +54,8 @@ namespace ams::ncm { R_DEFINE_ERROR_RESULT(InvalidContentMetaFileSize, 390); R_DEFINE_ERROR_RESULT(InvalidAddOnContentMetaExtendedHeader, 400); + R_DEFINE_ERROR_RESULT(InvalidContentMetaDirectory, 430); + R_DEFINE_ERROR_RANGE(ContentStorageNotActive, 250, 258); R_DEFINE_ERROR_RESULT(GameCardContentStorageNotActive, 251); R_DEFINE_ERROR_RESULT(BuiltInSystemContentStorageNotActive, 252);