mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-14 00:56:35 +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();
|
||||
}
|
||||
|
||||
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) {
|
||||
/* This initializes without an archive file. */
|
||||
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
||||
|
|
|
@ -21,9 +21,10 @@ namespace ams::ncm {
|
|||
struct ContentManagerConfig {
|
||||
bool build_system_database;
|
||||
bool import_database_from_system_on_sd;
|
||||
bool enable_integrated_system_content;
|
||||
|
||||
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 {
|
||||
|
@ -33,6 +34,10 @@ namespace ams::ncm {
|
|||
bool ShouldImportDatabaseFromSignedSystemPartitionOnSd() const {
|
||||
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_meta_utils.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>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
@ -69,10 +71,29 @@ namespace ams::ncm {
|
|||
};
|
||||
static_assert(util::is_pod<SystemSaveDataInfo>::value);
|
||||
|
||||
struct IntegratedContentStorageImpl;
|
||||
|
||||
class ContentManagerImpl {
|
||||
private:
|
||||
constexpr static size_t MaxContentStorageRoots = 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:
|
||||
struct ContentStorageRoot {
|
||||
NON_COPYABLE(ContentStorageRoot);
|
||||
|
@ -81,10 +102,42 @@ namespace ams::ncm {
|
|||
char mount_name[fs::MountNameLengthMax + 1];
|
||||
char path[128];
|
||||
StorageId storage_id;
|
||||
fs::ContentStorageId content_storage_id;
|
||||
util::optional<ContentStorageConfig> config;
|
||||
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 {
|
||||
|
@ -94,46 +147,100 @@ namespace ams::ncm {
|
|||
char mount_name[fs::MountNameLengthMax + 1];
|
||||
char path[128];
|
||||
StorageId storage_id;
|
||||
SystemSaveDataInfo info;
|
||||
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
|
||||
util::optional<ContentStorageConfig> storage_config;
|
||||
util::optional<SystemSaveDataInfo> save_data_info;
|
||||
util::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
|
||||
ContentMetaMemoryResource *memory_resource;
|
||||
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:
|
||||
os::SdkRecursiveMutex m_mutex;
|
||||
bool m_initialized;
|
||||
ContentStorageRoot m_content_storage_roots[MaxContentStorageRoots];
|
||||
ContentMetaDatabaseRoot m_content_meta_database_roots[MaxContentMetaDatabaseRoots];
|
||||
u32 m_num_content_storage_entries;
|
||||
u32 m_num_content_meta_entries;
|
||||
RightsIdCache m_rights_id_cache;
|
||||
RegisteredHostContent m_registered_host_content;
|
||||
os::SdkRecursiveMutex m_mutex{};
|
||||
bool m_initialized{false};
|
||||
IntegratedContentStorageRoot m_integrated_content_storage_roots[MaxIntegratedContentStorageRoots]{};
|
||||
ContentStorageRoot m_content_storage_roots[MaxContentStorageRoots]{};
|
||||
IntegratedContentMetaDatabaseRoot m_integrated_content_meta_database_roots[MaxIntegratedContentMetaDatabaseRoots]{};
|
||||
ContentMetaDatabaseRoot m_content_meta_database_roots[MaxContentMetaDatabaseRoots]{};
|
||||
IntegratedContentStorageConfig m_integrated_configs[MaxIntegratedConfigs]{};
|
||||
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:
|
||||
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();
|
||||
public:
|
||||
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:
|
||||
/* Helpers. */
|
||||
Result GetContentStorageRoot(ContentStorageRoot **out, StorageId id);
|
||||
Result GetContentMetaDatabaseRoot(ContentMetaDatabaseRoot **out, StorageId id);
|
||||
Result GetIntegratedContentStorageConfig(IntegratedContentStorageConfig **out, fs::ContentStorageId content_storage_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 InitializeGameCardContentStorageRoot(ContentStorageRoot *out);
|
||||
Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, util::optional<ContentStorageConfig> config);
|
||||
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 InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas, ContentMetaMemoryResource *mr);
|
||||
Result InitializeIntegratedContentStorageRoot(IntegratedContentStorageRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
|
||||
Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
|
||||
|
||||
Result BuildContentMetaDatabase(StorageId storage_id);
|
||||
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
||||
Result ImportContentMetaDatabaseImpl(StorageId storage_id, const char *import_mount_name, const char *path);
|
||||
|
||||
Result EnsureAndMountSystemSaveData(const char *mount, const SystemSaveDataInfo &info) const;
|
||||
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
|
||||
public:
|
||||
/* Actual commands. */
|
||||
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 GameCardMaxContentMetaCount = 0x800;
|
||||
constexpr inline s32 HostMaxContentMetaCount = 0x800;
|
||||
constexpr inline s32 UserMaxContentMetaCount = 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) { /* ... */ }
|
||||
public:
|
||||
/* Actual commands. */
|
||||
virtual Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out);
|
||||
virtual Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size);
|
||||
virtual Result DeletePlaceHolder(PlaceHolderId placeholder_id);
|
||||
virtual Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id);
|
||||
virtual Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data);
|
||||
virtual Result Register(PlaceHolderId placeholder_id, ContentId content_id);
|
||||
virtual Result Delete(ContentId content_id);
|
||||
virtual Result Has(sf::Out<bool> out, ContentId content_id);
|
||||
virtual Result GetPath(sf::Out<Path> out, ContentId content_id);
|
||||
virtual Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id);
|
||||
virtual Result CleanupAllPlaceHolder();
|
||||
virtual Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf);
|
||||
virtual Result GetContentCount(sf::Out<s32> out_count);
|
||||
virtual 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);
|
||||
virtual Result DisableForcibly();
|
||||
virtual Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id);
|
||||
virtual Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size);
|
||||
virtual 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);
|
||||
virtual 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);
|
||||
virtual 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);
|
||||
virtual 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);
|
||||
virtual Result GetFreeSpaceSize(sf::Out<s64> out_size);
|
||||
virtual Result GetTotalSpaceSize(sf::Out<s64> out_size);
|
||||
virtual Result FlushPlaceHolder();
|
||||
virtual Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id);
|
||||
virtual Result RepairInvalidFileAttribute();
|
||||
virtual 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);
|
||||
virtual Result RegisterPath(const ContentId &content_id, const Path &path);
|
||||
virtual Result ClearRegisteredPath();
|
||||
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<HostContentStorageImpl>);
|
||||
|
||||
|
|
Loading…
Reference in a new issue