mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-12 23:16:40 +00:00
ncm: better detect + fix 17 brick after-the-fact
This adds detection for missing-save or empty-save, and rebuilds in either case.
This commit is contained in:
parent
13411902c9
commit
3a8cffef57
2 changed files with 63 additions and 17 deletions
|
@ -239,8 +239,12 @@ namespace ams::ncm {
|
||||||
Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *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 BuildContentMetaDatabase(StorageId storage_id);
|
||||||
|
Result BuildContentMetaDatabaseImpl(StorageId storage_id);
|
||||||
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
||||||
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
|
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
|
||||||
|
private:
|
||||||
|
/* Helpers for unofficial functionality. */
|
||||||
|
bool IsNeedRebuildSystemContentMetaDatabase();
|
||||||
public:
|
public:
|
||||||
/* Actual commands. */
|
/* Actual commands. */
|
||||||
Result CreateContentStorage(StorageId storage_id);
|
Result CreateContentStorage(StorageId storage_id);
|
||||||
|
|
|
@ -784,27 +784,31 @@ namespace ams::ncm {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ContentManagerImpl::BuildContentMetaDatabase(StorageId storage_id) {
|
Result ContentManagerImpl::BuildContentMetaDatabase(StorageId storage_id) {
|
||||||
/* NOTE: we build on 17.0.0+, to work around a change in Nintendo save handling behavior. */
|
if (hos::GetVersion() < hos::Version_5_0_0) {
|
||||||
if (hos::GetVersion() < hos::Version_5_0_0 || hos::GetVersion() >= hos::Version_17_0_0) {
|
/* On < 5.0.0, perform an actual build of the database. */
|
||||||
/* Temporarily activate the database. */
|
R_RETURN(this->BuildContentMetaDatabaseImpl(storage_id));
|
||||||
R_TRY(this->ActivateContentMetaDatabase(storage_id));
|
|
||||||
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); };
|
|
||||||
|
|
||||||
/* Open the content meta database and storage. */
|
|
||||||
ContentMetaDatabase meta_db;
|
|
||||||
ContentStorage storage;
|
|
||||||
R_TRY(ncm::OpenContentMetaDatabase(std::addressof(meta_db), storage_id));
|
|
||||||
R_TRY(ncm::OpenContentStorage(std::addressof(storage), storage_id));
|
|
||||||
|
|
||||||
/* Create a builder, and build. */
|
|
||||||
ContentMetaDatabaseBuilder builder(std::addressof(meta_db));
|
|
||||||
R_RETURN(builder.BuildFromStorage(std::addressof(storage)));
|
|
||||||
} else {
|
} else {
|
||||||
/* On 5.0.0+, building just performs an import. */
|
/* On 5.0.0+, building just performs an import. */
|
||||||
R_RETURN(this->ImportContentMetaDatabase(storage_id, false));
|
R_RETURN(this->ImportContentMetaDatabase(storage_id, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result ContentManagerImpl::BuildContentMetaDatabaseImpl(StorageId storage_id) {
|
||||||
|
/* Temporarily activate the database. */
|
||||||
|
R_TRY(this->ActivateContentMetaDatabase(storage_id));
|
||||||
|
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); };
|
||||||
|
|
||||||
|
/* Open the content meta database and storage. */
|
||||||
|
ContentMetaDatabase meta_db;
|
||||||
|
ContentStorage storage;
|
||||||
|
R_TRY(ncm::OpenContentMetaDatabase(std::addressof(meta_db), storage_id));
|
||||||
|
R_TRY(ncm::OpenContentStorage(std::addressof(storage), storage_id));
|
||||||
|
|
||||||
|
/* Create a builder, and build. */
|
||||||
|
ContentMetaDatabaseBuilder builder(std::addressof(meta_db));
|
||||||
|
R_RETURN(builder.BuildFromStorage(std::addressof(storage)));
|
||||||
|
}
|
||||||
|
|
||||||
Result ContentManagerImpl::ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition) {
|
Result ContentManagerImpl::ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition) {
|
||||||
/* Only support importing BuiltInSystem. */
|
/* Only support importing BuiltInSystem. */
|
||||||
AMS_ABORT_UNLESS(storage_id == StorageId::BuiltInSystem);
|
AMS_ABORT_UNLESS(storage_id == StorageId::BuiltInSystem);
|
||||||
|
@ -832,6 +836,31 @@ namespace ams::ncm {
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContentManagerImpl::IsNeedRebuildSystemContentMetaDatabase() {
|
||||||
|
/* TODO: Should hos::GetVersion() >= hos::Version_17_0_0 be checked? */
|
||||||
|
|
||||||
|
/* If we do not actually have a content meta db, we should re-build. */
|
||||||
|
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have a content meta db. Temporarily, activate it. */
|
||||||
|
if (R_FAILED(this->ActivateContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(StorageId::BuiltInSystem); };
|
||||||
|
|
||||||
|
/* Open the content meta database and storage. */
|
||||||
|
ContentMetaDatabase meta_db;
|
||||||
|
R_ABORT_UNLESS(ncm::OpenContentMetaDatabase(std::addressof(meta_db), StorageId::BuiltInSystem));
|
||||||
|
|
||||||
|
/* List the meta db's contents. */
|
||||||
|
const auto list_count = meta_db.ListContentMeta(nullptr, 0);
|
||||||
|
|
||||||
|
/* We need to rebuild if the db has zero entries. */
|
||||||
|
return list_count.total == 0;
|
||||||
|
}
|
||||||
|
|
||||||
Result ContentManagerImpl::Initialize(const ContentManagerConfig &config) {
|
Result ContentManagerImpl::Initialize(const ContentManagerConfig &config) {
|
||||||
/* Initialize based on whether integrated content is enabled. */
|
/* Initialize based on whether integrated content is enabled. */
|
||||||
if (config.IsIntegratedSystemContentEnabled()) {
|
if (config.IsIntegratedSystemContentEnabled()) {
|
||||||
|
@ -942,13 +971,26 @@ namespace ams::ncm {
|
||||||
}
|
}
|
||||||
R_TRY(this->ActivateContentStorage(StorageId::BuiltInSystem));
|
R_TRY(this->ActivateContentStorage(StorageId::BuiltInSystem));
|
||||||
|
|
||||||
|
/* NOTE: This logic is unofficial. */
|
||||||
|
/* Beginning with 17.0.0+, save management behavior changed. The primary symptom of this is either verify fail */
|
||||||
|
/* or an empty kvs, both of which we can fix by performing a rebuild. */
|
||||||
|
if (this->IsNeedRebuildSystemContentMetaDatabase()) {
|
||||||
|
/* Clean up the system content meta database, to ensure creation can succeed. */
|
||||||
|
this->CleanupContentMetaDatabase(StorageId::BuiltInSystem);
|
||||||
|
|
||||||
|
/* Create the content metadatabase. */
|
||||||
|
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||||
|
|
||||||
|
/* Rebuild the content meta database. */
|
||||||
|
R_TRY(this->BuildContentMetaDatabaseImpl(StorageId::BuiltInSystem));
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup the content meta database for system. */
|
/* Setup the content meta database for system. */
|
||||||
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||||
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||||
|
|
||||||
/* Try to build or import a database, depending on our configuration. */
|
/* Try to build or import a database, depending on our configuration. */
|
||||||
/* NOTE: To work around a change in save management behavior in 17.0.0+, we build the database if needed. */
|
if (manager_config.ShouldBuildDatabase()) {
|
||||||
if (manager_config.ShouldBuildDatabase() || hos::GetVersion() >= hos::Version_17_0_0) {
|
|
||||||
/* If we should build the database, do so. */
|
/* If we should build the database, do so. */
|
||||||
R_TRY(this->BuildContentMetaDatabase(StorageId::BuiltInSystem));
|
R_TRY(this->BuildContentMetaDatabase(StorageId::BuiltInSystem));
|
||||||
R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem));
|
R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem));
|
||||||
|
|
Loading…
Reference in a new issue