mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
ncm: first pass at ContentManagerImpl refactor (missing the IntegratedImpls, won't link)
This commit is contained in:
parent
d64ab354ad
commit
668cabd4a2
9 changed files with 1190 additions and 364 deletions
|
@ -279,6 +279,23 @@ namespace ams::kvdb {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result InitializeForReadOnlyArchiveFile(const char *path, size_t capacity, MemoryResource *mr) {
|
||||||
|
/* Ensure that the passed path is a directory. */
|
||||||
|
fs::DirectoryEntryType entry_type;
|
||||||
|
R_TRY(fs::GetEntryType(std::addressof(entry_type), path));
|
||||||
|
R_UNLESS(entry_type == fs::DirectoryEntryType_File, fs::ResultPathNotFound());
|
||||||
|
|
||||||
|
/* Set paths. */
|
||||||
|
m_path.Assign(path);
|
||||||
|
m_temp_path.Assign("");
|
||||||
|
|
||||||
|
/* Initialize our index. */
|
||||||
|
R_TRY(m_index.Initialize(capacity, mr));
|
||||||
|
m_memory_resource = mr;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
Result Initialize(size_t capacity, MemoryResource *mr) {
|
Result Initialize(size_t capacity, MemoryResource *mr) {
|
||||||
/* This initializes without an archive file. */
|
/* This initializes without an archive file. */
|
||||||
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
||||||
|
|
|
@ -21,9 +21,10 @@ namespace ams::ncm {
|
||||||
struct ContentManagerConfig {
|
struct ContentManagerConfig {
|
||||||
bool build_system_database;
|
bool build_system_database;
|
||||||
bool import_database_from_system_on_sd;
|
bool import_database_from_system_on_sd;
|
||||||
|
bool enable_integrated_system_content;
|
||||||
|
|
||||||
bool HasAnyConfig() const {
|
bool HasAnyConfig() const {
|
||||||
return this->ShouldBuildDatabase() || this->import_database_from_system_on_sd;
|
return this->ShouldBuildDatabase() || this->import_database_from_system_on_sd || this->enable_integrated_system_content;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShouldBuildDatabase() const {
|
bool ShouldBuildDatabase() const {
|
||||||
|
@ -33,6 +34,10 @@ namespace ams::ncm {
|
||||||
bool ShouldImportDatabaseFromSignedSystemPartitionOnSd() const {
|
bool ShouldImportDatabaseFromSignedSystemPartitionOnSd() const {
|
||||||
return this->import_database_from_system_on_sd;
|
return this->import_database_from_system_on_sd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsIntegratedSystemContentEnabled() const {
|
||||||
|
return this->enable_integrated_system_content;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include <stratosphere/ncm/ncm_content_management_utils.hpp>
|
#include <stratosphere/ncm/ncm_content_management_utils.hpp>
|
||||||
#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
|
#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
|
||||||
#include <stratosphere/ncm/ncm_registered_host_content.hpp>
|
#include <stratosphere/ncm/ncm_registered_host_content.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_integrated_content_storage_impl.hpp>
|
||||||
#include <stratosphere/kvdb/kvdb_memory_key_value_store.hpp>
|
#include <stratosphere/kvdb/kvdb_memory_key_value_store.hpp>
|
||||||
|
|
||||||
namespace ams::ncm {
|
namespace ams::ncm {
|
||||||
|
@ -69,10 +71,29 @@ namespace ams::ncm {
|
||||||
};
|
};
|
||||||
static_assert(util::is_pod<SystemSaveDataInfo>::value);
|
static_assert(util::is_pod<SystemSaveDataInfo>::value);
|
||||||
|
|
||||||
|
struct IntegratedContentStorageImpl;
|
||||||
|
|
||||||
class ContentManagerImpl {
|
class ContentManagerImpl {
|
||||||
private:
|
private:
|
||||||
constexpr static size_t MaxContentStorageRoots = 8;
|
constexpr static size_t MaxContentStorageRoots = 8;
|
||||||
constexpr static size_t MaxContentMetaDatabaseRoots = 8;
|
constexpr static size_t MaxIntegratedContentStorageRoots = 8;
|
||||||
|
constexpr static size_t MaxContentMetaDatabaseRoots = 8;
|
||||||
|
constexpr static size_t MaxIntegratedContentMetaDatabaseRoots = 8;
|
||||||
|
constexpr static size_t MaxConfigs = 8;
|
||||||
|
constexpr static size_t MaxIntegratedConfigs = 8;
|
||||||
|
private:
|
||||||
|
struct ContentStorageConfig {
|
||||||
|
fs::ContentStorageId content_storage_id;
|
||||||
|
bool skip_verify_and_create;
|
||||||
|
bool skip_activate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntegratedContentStorageConfig {
|
||||||
|
ncm::StorageId storage_id;
|
||||||
|
fs::ContentStorageId content_storage_ids[MaxContentStorageRoots];
|
||||||
|
int num_content_storage_ids;
|
||||||
|
bool is_integrated;
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
struct ContentStorageRoot {
|
struct ContentStorageRoot {
|
||||||
NON_COPYABLE(ContentStorageRoot);
|
NON_COPYABLE(ContentStorageRoot);
|
||||||
|
@ -81,10 +102,42 @@ namespace ams::ncm {
|
||||||
char mount_name[fs::MountNameLengthMax + 1];
|
char mount_name[fs::MountNameLengthMax + 1];
|
||||||
char path[128];
|
char path[128];
|
||||||
StorageId storage_id;
|
StorageId storage_id;
|
||||||
fs::ContentStorageId content_storage_id;
|
util::optional<ContentStorageConfig> config;
|
||||||
sf::SharedPointer<IContentStorage> content_storage;
|
sf::SharedPointer<IContentStorage> content_storage;
|
||||||
|
|
||||||
ContentStorageRoot() : mount_name(), path(), storage_id(), content_storage_id(), content_storage() { /* ... */ }
|
ContentStorageRoot() : mount_name(), path(), storage_id(), config(util::nullopt), content_storage() { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntegratedContentStorageRoot {
|
||||||
|
NON_COPYABLE(IntegratedContentStorageRoot);
|
||||||
|
NON_MOVEABLE(IntegratedContentStorageRoot);
|
||||||
|
|
||||||
|
const IntegratedContentStorageConfig *m_config;
|
||||||
|
ContentStorageRoot *m_roots;
|
||||||
|
int m_num_roots;
|
||||||
|
sf::EmplacedRef<IContentStorage, IntegratedContentStorageImpl> m_integrated_content_storage;
|
||||||
|
|
||||||
|
IntegratedContentStorageRoot() : m_config(), m_roots(), m_num_roots(), m_integrated_content_storage() { /* ... */ }
|
||||||
|
|
||||||
|
Result Create();
|
||||||
|
Result Verify();
|
||||||
|
Result Open(sf::Out<sf::SharedPointer<IContentStorage>> out, RightsIdCache &rights_id_cache, RegisteredHostContent ®istered_host_content);
|
||||||
|
Result Activate(RightsIdCache &rights_id_cache, RegisteredHostContent ®istered_host_content);
|
||||||
|
Result Inactivate(RegisteredHostContent ®istered_host_content);
|
||||||
|
|
||||||
|
Result Activate(ContentStorageRoot &root, RightsIdCache &rights_id_cache, RegisteredHostContent ®istered_host_content);
|
||||||
|
|
||||||
|
Result Activate(RightsIdCache &rights_id_cache, RegisteredHostContent ®istered_host_content, fs::ContentStorageId content_storage_id);
|
||||||
|
|
||||||
|
ContentStorageRoot *GetRoot(fs::ContentStorageId storage_id) {
|
||||||
|
for (auto i = 0; i < m_num_roots; ++i) {
|
||||||
|
if (auto &root = m_roots[i]; root.config.has_value() && root.config->content_storage_id == storage_id) {
|
||||||
|
return std::addressof(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContentMetaDatabaseRoot {
|
struct ContentMetaDatabaseRoot {
|
||||||
|
@ -94,46 +147,100 @@ namespace ams::ncm {
|
||||||
char mount_name[fs::MountNameLengthMax + 1];
|
char mount_name[fs::MountNameLengthMax + 1];
|
||||||
char path[128];
|
char path[128];
|
||||||
StorageId storage_id;
|
StorageId storage_id;
|
||||||
SystemSaveDataInfo info;
|
util::optional<ContentStorageConfig> storage_config;
|
||||||
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
|
util::optional<SystemSaveDataInfo> save_data_info;
|
||||||
util::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
util::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||||
|
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
|
||||||
ContentMetaMemoryResource *memory_resource;
|
ContentMetaMemoryResource *memory_resource;
|
||||||
u32 max_content_metas;
|
u32 max_content_metas;
|
||||||
|
|
||||||
ContentMetaDatabaseRoot() : mount_name(), path(), storage_id(), info(), content_meta_database(), kvs(util::nullopt), memory_resource(), max_content_metas() { /* ... */ }
|
ContentMetaDatabaseRoot() : mount_name(), path(), storage_id(), storage_config(util::nullopt), save_data_info(util::nullopt), kvs(util::nullopt), content_meta_database(), memory_resource(), max_content_metas() { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntegratedContentMetaDatabaseRoot {
|
||||||
|
NON_COPYABLE(IntegratedContentMetaDatabaseRoot);
|
||||||
|
NON_MOVEABLE(IntegratedContentMetaDatabaseRoot);
|
||||||
|
|
||||||
|
const IntegratedContentStorageConfig *m_config;
|
||||||
|
ContentMetaDatabaseRoot *m_roots;
|
||||||
|
int m_num_roots;
|
||||||
|
sf::EmplacedRef<IContentMetaDatabase, IntegratedContentMetaDatabaseImpl> m_integrated_content_meta_database;
|
||||||
|
|
||||||
|
IntegratedContentMetaDatabaseRoot() : m_config(), m_roots(), m_num_roots(), m_integrated_content_meta_database() { /* ... */ }
|
||||||
|
|
||||||
|
Result Create();
|
||||||
|
Result Verify();
|
||||||
|
Result Open(sf::Out<sf::SharedPointer<IContentMetaDatabase>> out);
|
||||||
|
Result Cleanup();
|
||||||
|
Result Activate();
|
||||||
|
Result Inactivate();
|
||||||
|
|
||||||
|
Result Activate(ContentMetaDatabaseRoot &root);
|
||||||
|
|
||||||
|
Result Activate(fs::ContentStorageId content_storage_id);
|
||||||
|
|
||||||
|
ContentMetaDatabaseRoot *GetRoot(fs::ContentStorageId storage_id) {
|
||||||
|
for (auto i = 0; i < m_num_roots; ++i) {
|
||||||
|
if (auto &root = m_roots[i]; root.storage_config.has_value() && root.storage_config->content_storage_id == storage_id) {
|
||||||
|
return std::addressof(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
os::SdkRecursiveMutex m_mutex;
|
os::SdkRecursiveMutex m_mutex{};
|
||||||
bool m_initialized;
|
bool m_initialized{false};
|
||||||
ContentStorageRoot m_content_storage_roots[MaxContentStorageRoots];
|
IntegratedContentStorageRoot m_integrated_content_storage_roots[MaxIntegratedContentStorageRoots]{};
|
||||||
ContentMetaDatabaseRoot m_content_meta_database_roots[MaxContentMetaDatabaseRoots];
|
ContentStorageRoot m_content_storage_roots[MaxContentStorageRoots]{};
|
||||||
u32 m_num_content_storage_entries;
|
IntegratedContentMetaDatabaseRoot m_integrated_content_meta_database_roots[MaxIntegratedContentMetaDatabaseRoots]{};
|
||||||
u32 m_num_content_meta_entries;
|
ContentMetaDatabaseRoot m_content_meta_database_roots[MaxContentMetaDatabaseRoots]{};
|
||||||
RightsIdCache m_rights_id_cache;
|
IntegratedContentStorageConfig m_integrated_configs[MaxIntegratedConfigs]{};
|
||||||
RegisteredHostContent m_registered_host_content;
|
ContentStorageConfig m_configs[MaxConfigs]{};
|
||||||
|
u32 m_num_integrated_content_storage_entries{0};
|
||||||
|
u32 m_num_content_storage_entries{0};
|
||||||
|
u32 m_num_integrated_content_meta_entries{0};
|
||||||
|
u32 m_num_content_meta_entries{0};
|
||||||
|
u32 m_num_integrated_configs{0};
|
||||||
|
u32 m_num_configs{0};
|
||||||
|
RightsIdCache m_rights_id_cache{};
|
||||||
|
RegisteredHostContent m_registered_host_content{};
|
||||||
public:
|
public:
|
||||||
ContentManagerImpl() : m_mutex(), m_initialized(false), m_content_storage_roots(), m_content_meta_database_roots(), m_num_content_storage_entries(0), m_num_content_meta_entries(0), m_rights_id_cache(), m_registered_host_content() {
|
ContentManagerImpl() = default;
|
||||||
/* ... */
|
|
||||||
};
|
|
||||||
~ContentManagerImpl();
|
~ContentManagerImpl();
|
||||||
public:
|
public:
|
||||||
Result Initialize(const ContentManagerConfig &config);
|
Result Initialize(const ContentManagerConfig &config);
|
||||||
|
private:
|
||||||
|
Result Initialize(const ContentManagerConfig &manager_config, const IntegratedContentStorageConfig *integrated_configs, size_t num_integrated_configs, const ContentStorageConfig *configs, size_t num_configs, const ncm::StorageId *activated_storages, size_t num_activated_storages);
|
||||||
|
Result InitializeStorageBuiltInSystem(const ContentManagerConfig &manager_config);
|
||||||
|
Result InitializeStorage(ncm::StorageId storage_id);
|
||||||
|
|
||||||
|
const ContentStorageConfig &GetContentStorageConfig(fs::ContentStorageId content_storage_id) {
|
||||||
|
for (size_t i = 0; i < m_num_configs; ++i) {
|
||||||
|
if (m_configs[i].content_storage_id == content_storage_id) {
|
||||||
|
return m_configs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: Nintendo accesses out of bounds memory here. Should we explicitly abort? This is guaranteed by data to never happen. */
|
||||||
|
AMS_ASSUME(false);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
Result GetContentStorageRoot(ContentStorageRoot **out, StorageId id);
|
Result GetIntegratedContentStorageConfig(IntegratedContentStorageConfig **out, fs::ContentStorageId content_storage_id);
|
||||||
Result GetContentMetaDatabaseRoot(ContentMetaDatabaseRoot **out, StorageId id);
|
Result GetIntegratedContentStorageRoot(IntegratedContentStorageRoot **out, StorageId id);
|
||||||
|
Result GetIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot **out, StorageId id);
|
||||||
|
|
||||||
Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, fs::ContentStorageId content_storage_id);
|
Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, util::optional<ContentStorageConfig> config);
|
||||||
Result InitializeGameCardContentStorageRoot(ContentStorageRoot *out);
|
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, util::optional<ContentStorageConfig> storage_config);
|
||||||
|
|
||||||
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, const SystemSaveDataInfo &info, size_t max_content_metas, ContentMetaMemoryResource *mr);
|
Result InitializeIntegratedContentStorageRoot(IntegratedContentStorageRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
|
||||||
Result InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas, ContentMetaMemoryResource *mr);
|
Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
|
||||||
|
|
||||||
Result BuildContentMetaDatabase(StorageId storage_id);
|
Result BuildContentMetaDatabase(StorageId storage_id);
|
||||||
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
||||||
Result ImportContentMetaDatabaseImpl(StorageId storage_id, const char *import_mount_name, const char *path);
|
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
|
||||||
|
|
||||||
Result EnsureAndMountSystemSaveData(const char *mount, const SystemSaveDataInfo &info) const;
|
|
||||||
public:
|
public:
|
||||||
/* Actual commands. */
|
/* Actual commands. */
|
||||||
Result CreateContentStorage(StorageId storage_id);
|
Result CreateContentStorage(StorageId storage_id);
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_integrated_list.hpp>
|
||||||
|
|
||||||
|
namespace ams::ncm {
|
||||||
|
|
||||||
|
class IntegratedContentMetaDatabaseImpl {
|
||||||
|
NON_COPYABLE(IntegratedContentMetaDatabaseImpl);
|
||||||
|
NON_MOVEABLE(IntegratedContentMetaDatabaseImpl);
|
||||||
|
private:
|
||||||
|
using ListType = ncm::IntegratedList<ncm::IContentMetaDatabase, 2>;
|
||||||
|
using DataType = ListType::ListData;
|
||||||
|
private:
|
||||||
|
os::SdkMutex m_mutex;
|
||||||
|
ListType m_list;
|
||||||
|
bool m_disabled;
|
||||||
|
public:
|
||||||
|
IntegratedContentMetaDatabaseImpl() : m_mutex(), m_list(), m_disabled(false) { /* ... */ }
|
||||||
|
|
||||||
|
void Add(sf::SharedPointer<ncm::IContentMetaDatabase> p, u8 id) {
|
||||||
|
DataType data = {std::move(p), id};
|
||||||
|
m_list.Add(data);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/* Helpers. */
|
||||||
|
Result EnsureEnabled() const {
|
||||||
|
R_UNLESS(!m_disabled, ncm::ResultInvalidContentMetaDatabase());
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
Result Set(const ContentMetaKey &key, const sf::InBuffer &value);
|
||||||
|
Result Get(sf::Out<u64> out_size, const ContentMetaKey &key, const sf::OutBuffer &out_value);
|
||||||
|
Result Remove(const ContentMetaKey &key);
|
||||||
|
Result GetContentIdByType(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type);
|
||||||
|
Result ListContentInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentInfo> &out_info, const ContentMetaKey &key, s32 offset);
|
||||||
|
Result List(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaKey> &out_info, ContentMetaType meta_type, ApplicationId application_id, u64 min, u64 max, ContentInstallType install_type);
|
||||||
|
Result GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, u64 id);
|
||||||
|
Result ListApplication(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ApplicationContentMetaKey> &out_keys, ContentMetaType meta_type);
|
||||||
|
Result Has(sf::Out<bool> out, const ContentMetaKey &key);
|
||||||
|
Result HasAll(sf::Out<bool> out, const sf::InArray<ContentMetaKey> &keys);
|
||||||
|
Result GetSize(sf::Out<u64> out_size, const ContentMetaKey &key);
|
||||||
|
Result GetRequiredSystemVersion(sf::Out<u32> out_version, const ContentMetaKey &key);
|
||||||
|
Result GetPatchContentMetaId(sf::Out<u64> out_patch_id, const ContentMetaKey &key);
|
||||||
|
Result DisableForcibly();
|
||||||
|
Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids);
|
||||||
|
Result Commit();
|
||||||
|
Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id);
|
||||||
|
Result ListContentMetaInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, s32 offset);
|
||||||
|
Result GetAttributes(sf::Out<u8> out_attributes, const ContentMetaKey &key);
|
||||||
|
Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key);
|
||||||
|
Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset);
|
||||||
|
Result GetCount(sf::Out<u32> out_count);
|
||||||
|
Result GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key);
|
||||||
|
Result GetContentAccessibilities(sf::Out<u8> out_accessibilities, const ContentMetaKey &key);
|
||||||
|
Result GetContentInfoByType(sf::Out<ContentInfo> out_content_info, const ContentMetaKey &key, ContentType type);
|
||||||
|
Result GetContentInfoByTypeAndIdOffset(sf::Out<ContentInfo> out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset);
|
||||||
|
};
|
||||||
|
static_assert(ncm::IsIContentMetaDatabase<IntegratedContentMetaDatabaseImpl>);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_i_content_storage.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_integrated_list.hpp>
|
||||||
|
|
||||||
|
namespace ams::ncm {
|
||||||
|
|
||||||
|
class IntegratedContentStorageImpl {
|
||||||
|
NON_COPYABLE(IntegratedContentStorageImpl);
|
||||||
|
NON_MOVEABLE(IntegratedContentStorageImpl);
|
||||||
|
private:
|
||||||
|
using ListType = ncm::IntegratedList<ncm::IContentStorage, 2>;
|
||||||
|
using DataType = ListType::ListData;
|
||||||
|
private:
|
||||||
|
os::SdkMutex m_mutex;
|
||||||
|
ListType m_list;
|
||||||
|
bool m_disabled;
|
||||||
|
public:
|
||||||
|
IntegratedContentStorageImpl() : m_mutex(), m_list(), m_disabled(false) { /* ... */ }
|
||||||
|
|
||||||
|
void Add(sf::SharedPointer<ncm::IContentStorage> p, u8 id) {
|
||||||
|
DataType data = {std::move(p), id};
|
||||||
|
m_list.Add(data);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
/* Helpers. */
|
||||||
|
Result EnsureEnabled() const {
|
||||||
|
R_UNLESS(!m_disabled, ncm::ResultInvalidContentStorage());
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
/* Actual commands. */
|
||||||
|
Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out);
|
||||||
|
Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size);
|
||||||
|
Result DeletePlaceHolder(PlaceHolderId placeholder_id);
|
||||||
|
Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id);
|
||||||
|
Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data);
|
||||||
|
Result Register(PlaceHolderId placeholder_id, ContentId content_id);
|
||||||
|
Result Delete(ContentId content_id);
|
||||||
|
Result Has(sf::Out<bool> out, ContentId content_id);
|
||||||
|
Result GetPath(sf::Out<Path> out, ContentId content_id);
|
||||||
|
Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id);
|
||||||
|
Result CleanupAllPlaceHolder();
|
||||||
|
Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf);
|
||||||
|
Result GetContentCount(sf::Out<s32> out_count);
|
||||||
|
Result ListContentId(sf::Out<s32> out_count, const sf::OutArray<ContentId> &out_buf, s32 start_offset);
|
||||||
|
Result GetSizeFromContentId(sf::Out<s64> out_size, ContentId content_id);
|
||||||
|
Result DisableForcibly();
|
||||||
|
Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id);
|
||||||
|
Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size);
|
||||||
|
Result ReadContentIdFile(const sf::OutBuffer &buf, ContentId content_id, s64 offset);
|
||||||
|
Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
||||||
|
Result GetRightsIdFromPlaceHolderIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
||||||
|
Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, fs::ContentAttributes attr);
|
||||||
|
Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id);
|
||||||
|
Result GetRightsIdFromContentIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id);
|
||||||
|
Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id, fs::ContentAttributes attr);
|
||||||
|
Result WriteContentForDebug(ContentId content_id, s64 offset, const sf::InBuffer &data);
|
||||||
|
Result GetFreeSpaceSize(sf::Out<s64> out_size);
|
||||||
|
Result GetTotalSpaceSize(sf::Out<s64> out_size);
|
||||||
|
Result FlushPlaceHolder();
|
||||||
|
Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id);
|
||||||
|
Result RepairInvalidFileAttribute();
|
||||||
|
Result GetRightsIdFromPlaceHolderIdWithCacheDeprecated(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id);
|
||||||
|
Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr);
|
||||||
|
Result RegisterPath(const ContentId &content_id, const Path &path);
|
||||||
|
Result ClearRegisteredPath();
|
||||||
|
};
|
||||||
|
static_assert(ncm::IsIContentStorage<IntegratedContentStorageImpl>);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/sf/sf_shared_object.hpp>
|
||||||
|
|
||||||
|
namespace ams::ncm {
|
||||||
|
|
||||||
|
template<typename T, size_t N>
|
||||||
|
class IntegratedList {
|
||||||
|
static_assert(N <= std::numeric_limits<u8>::max());
|
||||||
|
public:
|
||||||
|
struct ListData {
|
||||||
|
sf::SharedPointer<T> interface;
|
||||||
|
u8 id;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
size_t m_count;
|
||||||
|
sf::SharedPointer<T> m_interfaces[N];
|
||||||
|
u8 m_ids[N];
|
||||||
|
public:
|
||||||
|
IntegratedList() : m_count(0), m_interfaces(), m_ids() { /* ... */ }
|
||||||
|
|
||||||
|
void Add(ListData &data) {
|
||||||
|
/* Find place to insert into the list. */
|
||||||
|
const size_t pos = std::distance(std::begin(m_ids), std::lower_bound(std::begin(m_ids), std::end(m_ids), data.id));
|
||||||
|
|
||||||
|
/* If we need to, move stuff to make space. */
|
||||||
|
if (m_ids[pos] > data.id) {
|
||||||
|
AMS_ABORT_UNLESS(m_count < N);
|
||||||
|
|
||||||
|
for (size_t i = m_count; i > pos; --i) {
|
||||||
|
m_ids[i] = std::move(m_ids[i - 1]);
|
||||||
|
m_interfaces[i] = std::move(m_interfaces[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're inserting somewhere in the middle, increment count. */
|
||||||
|
m_count++;
|
||||||
|
} else if (m_ids[pos] < data.id) {
|
||||||
|
/* If we're inserting at the end, increment count. */
|
||||||
|
AMS_ABORT_UNLESS(m_count < N);
|
||||||
|
m_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set at position. */
|
||||||
|
m_interfaces[pos] = data.interface;
|
||||||
|
m_ids[pos] = data.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListData Get(size_t idx) {
|
||||||
|
AMS_ABORT_UNLESS(idx < m_count);
|
||||||
|
|
||||||
|
return { m_interfaces[idx], m_ids[idx] };
|
||||||
|
}
|
||||||
|
|
||||||
|
Result TryEach(auto callback) {
|
||||||
|
Result result = ResultSuccess();
|
||||||
|
for (size_t i = 0; i < m_count; ++i) {
|
||||||
|
result = callback(this->Get(i));
|
||||||
|
if (R_SUCCEEDED(result)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R_RETURN(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ namespace ams::ncm {
|
||||||
|
|
||||||
constexpr inline s32 SystemMaxContentMetaCount = 0x800;
|
constexpr inline s32 SystemMaxContentMetaCount = 0x800;
|
||||||
constexpr inline s32 GameCardMaxContentMetaCount = 0x800;
|
constexpr inline s32 GameCardMaxContentMetaCount = 0x800;
|
||||||
|
constexpr inline s32 HostMaxContentMetaCount = 0x800;
|
||||||
constexpr inline s32 UserMaxContentMetaCount = 0x2000;
|
constexpr inline s32 UserMaxContentMetaCount = 0x2000;
|
||||||
constexpr inline s32 SdCardMaxContentMetaCount = 0x2000;
|
constexpr inline s32 SdCardMaxContentMetaCount = 0x2000;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,41 +42,41 @@ namespace ams::ncm {
|
||||||
HostContentStorageImpl(RegisteredHostContent *registered_content) : m_registered_content(registered_content), m_disabled(false) { /* ... */ }
|
HostContentStorageImpl(RegisteredHostContent *registered_content) : m_registered_content(registered_content), m_disabled(false) { /* ... */ }
|
||||||
public:
|
public:
|
||||||
/* Actual commands. */
|
/* Actual commands. */
|
||||||
virtual Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out);
|
Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out);
|
||||||
virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size);
|
Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size);
|
||||||
virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id);
|
Result DeletePlaceHolder(PlaceHolderId placeholder_id);
|
||||||
virtual Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id);
|
Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id);
|
||||||
virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data);
|
Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data);
|
||||||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id);
|
Result Register(PlaceHolderId placeholder_id, ContentId content_id);
|
||||||
virtual Result Delete(ContentId content_id);
|
Result Delete(ContentId content_id);
|
||||||
virtual Result Has(sf::Out<bool> out, ContentId content_id);
|
Result Has(sf::Out<bool> out, ContentId content_id);
|
||||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id);
|
Result GetPath(sf::Out<Path> out, ContentId content_id);
|
||||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id);
|
Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id);
|
||||||
virtual Result CleanupAllPlaceHolder();
|
Result CleanupAllPlaceHolder();
|
||||||
virtual Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf);
|
Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf);
|
||||||
virtual Result GetContentCount(sf::Out<s32> out_count);
|
Result GetContentCount(sf::Out<s32> out_count);
|
||||||
virtual Result ListContentId(sf::Out<s32> out_count, const sf::OutArray<ContentId> &out_buf, s32 start_offset);
|
Result ListContentId(sf::Out<s32> out_count, const sf::OutArray<ContentId> &out_buf, s32 start_offset);
|
||||||
virtual Result GetSizeFromContentId(sf::Out<s64> out_size, ContentId content_id);
|
Result GetSizeFromContentId(sf::Out<s64> out_size, ContentId content_id);
|
||||||
virtual Result DisableForcibly();
|
Result DisableForcibly();
|
||||||
virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id);
|
Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id);
|
||||||
virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size);
|
Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size);
|
||||||
virtual Result ReadContentIdFile(const sf::OutBuffer &buf, ContentId content_id, s64 offset);
|
Result ReadContentIdFile(const sf::OutBuffer &buf, ContentId content_id, s64 offset);
|
||||||
virtual Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
||||||
virtual Result GetRightsIdFromPlaceHolderIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
Result GetRightsIdFromPlaceHolderIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id);
|
||||||
virtual Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, fs::ContentAttributes attr);
|
Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, fs::ContentAttributes attr);
|
||||||
virtual Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id);
|
Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id);
|
||||||
virtual Result GetRightsIdFromContentIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id);
|
Result GetRightsIdFromContentIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id);
|
||||||
virtual Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id, fs::ContentAttributes attr);
|
Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id, fs::ContentAttributes attr);
|
||||||
virtual Result WriteContentForDebug(ContentId content_id, s64 offset, const sf::InBuffer &data);
|
Result WriteContentForDebug(ContentId content_id, s64 offset, const sf::InBuffer &data);
|
||||||
virtual Result GetFreeSpaceSize(sf::Out<s64> out_size);
|
Result GetFreeSpaceSize(sf::Out<s64> out_size);
|
||||||
virtual Result GetTotalSpaceSize(sf::Out<s64> out_size);
|
Result GetTotalSpaceSize(sf::Out<s64> out_size);
|
||||||
virtual Result FlushPlaceHolder();
|
Result FlushPlaceHolder();
|
||||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id);
|
Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id);
|
||||||
virtual Result RepairInvalidFileAttribute();
|
Result RepairInvalidFileAttribute();
|
||||||
virtual Result GetRightsIdFromPlaceHolderIdWithCacheDeprecated(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id);
|
Result GetRightsIdFromPlaceHolderIdWithCacheDeprecated(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id);
|
||||||
virtual Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr);
|
Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr);
|
||||||
virtual Result RegisterPath(const ContentId &content_id, const Path &path);
|
Result RegisterPath(const ContentId &content_id, const Path &path);
|
||||||
virtual Result ClearRegisteredPath();
|
Result ClearRegisteredPath();
|
||||||
};
|
};
|
||||||
static_assert(ncm::IsIContentStorage<HostContentStorageImpl>);
|
static_assert(ncm::IsIContentStorage<HostContentStorageImpl>);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue