From 791edf87a07bd24123500bcf1ad795404df89f1d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 30 Apr 2025 23:27:36 -0700 Subject: [PATCH] ncm: update to implement new ContentMetaDatabase function for 20.0.0 --- .../ncm/ncm_content_meta_database.hpp | 5 ++++ .../ncm/ncm_i_content_meta_database.hpp | 3 +- ..._integrated_content_meta_database_impl.hpp | 1 + .../ncm/ncm_content_meta_database_impl.cpp | 30 +++++++++++++++++++ .../ncm/ncm_content_meta_database_impl.hpp | 1 + .../ncm_content_meta_database_impl_base.hpp | 1 + ..._integrated_content_meta_database_impl.cpp | 24 +++++++++++++++ .../ncm_remote_content_meta_database_impl.hpp | 6 ++++ 8 files changed, 70 insertions(+), 1 deletion(-) 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 fde547802..6c6a8adec 100644 --- a/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp +++ b/libraries/libstratosphere/include/stratosphere/ncm/ncm_content_meta_database.hpp @@ -226,6 +226,11 @@ namespace ams::ncm { AMS_ASSERT(m_interface != nullptr); R_RETURN(m_interface->GetPlatform(out, key)); } + + Result HasAttributes(u8 *out, u8 attr_mask) { + AMS_ASSERT(m_interface != nullptr); + R_RETURN(m_interface->HasAttributes(out, attr_mask)); + } }; } 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 099de50fb..39c04cd03 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 @@ -44,7 +44,8 @@ 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, 26, Result, GetPlatform, (sf::Out out, const ncm::ContentMetaKey &key), (out, key), hos::Version_17_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_METHOD_INFO(C, H, 27, Result, HasAttributes, (sf::Out out, u8 attr_mask), (out, attr_mask), hos::Version_20_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_integrated_content_meta_database_impl.hpp b/libraries/libstratosphere/include/stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp index 38bfc154f..8d0e79ff0 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 @@ -72,6 +72,7 @@ namespace ams::ncm { 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); + Result HasAttributes(sf::Out out, u8 attr_mask); }; static_assert(ncm::IsIContentMetaDatabase); 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 da23ce454..4cf5175b2 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.cpp @@ -534,4 +534,34 @@ namespace ams::ncm { R_SUCCEED(); } + Result ContentMetaDatabaseImpl::HasAttributes(sf::Out out, u8 attribute_mask) { + R_TRY(this->EnsureEnabled()); + + /* Create a variable to hold the combined attributes. */ + u8 combined_attributes = 0; + + /* Iterate over all entries. */ + for (auto &entry : *m_kvs) { + /* Obtain the content meta for the key. */ + const void *meta; + size_t meta_size; + R_TRY(this->GetContentMetaPointer(&meta, &meta_size, entry.GetKey())); + + /* Create a reader. */ + ContentMetaReader reader(meta, meta_size); + + /* Accumulate the set attributes from the current entry. */ + combined_attributes |= (reader.GetHeader()->attributes) & attribute_mask; + + /* If all the attributes we're looking for have been found, we're done. */ + if ((combined_attributes & attribute_mask) == attribute_mask) { + break; + } + } + + /* Set the output. */ + *out = combined_attributes; + 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 9d6bcfb46..b4e3803d7 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_meta_database_impl.hpp @@ -65,6 +65,7 @@ namespace ams::ncm { 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; + virtual Result HasAttributes(sf::Out out, u8 attr_mask) 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 7c0d57c30..59d6130e9 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 @@ -81,6 +81,7 @@ namespace ams::ncm { 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; + virtual Result HasAttributes(sf::Out out, u8 attr_mask) = 0; }; static_assert(ncm::IsIContentMetaDatabase); 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 b498464cf..148471e86 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 @@ -463,4 +463,28 @@ namespace ams::ncm { })); } + Result IntegratedContentMetaDatabaseImpl::HasAttributes(sf::Out out, u8 attr_mask) { + /* Lock ourselves. */ + std::scoped_lock lk(m_mutex); + + /* Check that we're enabled. */ + R_TRY(this->EnsureEnabled()); + + /* Test whether we have the attributes on all databases. */ + u8 combined_attributes = 0; + R_TRY(m_list.ForAll([&](const auto &data) { + /* Check the current database. */ + u8 cur_attr = 0; + R_TRY(data.interface->HasAttributes(std::addressof(cur_attr), attr_mask)); + + /* Accumulate the attributes found in the current interface. */ + combined_attributes |= cur_attr; + R_SUCCEED(); + })); + + /* Set the output. */ + *out = combined_attributes; + R_SUCCEED(); + } + } 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 a0d8a4286..abba78c73 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 @@ -191,6 +191,12 @@ namespace ams::ncm { static_assert(sizeof(ncm::ContentMetaPlatform) == sizeof(u8)); R_RETURN(ncmContentMetaDatabaseGetPlatform(std::addressof(m_srv), reinterpret_cast(out.GetPointer()), Convert(key))); } + + Result HasAttributes(sf::Out out, u8 attr_mask) { + /* TODO: libnx bindings */ + AMS_UNUSED(out, attr_mask); + AMS_ABORT(); + } }; static_assert(ncm::IsIContentMetaDatabase); #endif