From 337fcf07a40c55c3f506b4a922773a0547d949a6 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 12 Oct 2023 08:17:05 -0700 Subject: [PATCH] ncm: work around change in Nintendo save handling behavior Static save files do not require an entry in the save data indexer to mount. Prior to 17.0.0, save data files were considered static if userid was 0. In 17.0.0+, only 8000000000000000 is static. However, some users using cfw do not have an entry for 8000000000000120 in the indexer, for various reasons (but mostly manual nand-restore, I think). Thus, on boot of 17.0.0+, FS will say 8000000000000120 is not present (not in indexer), and NCM will create it anew. The 8000000000000120 save will then be empty, and then the firmware can't boot. To workaround this, logic has been re-enabled on 17.0.0+ for building the content meta database. Thus, if the user encounters this error, the 8000000000000120 save will be emptied, but then it will be automatically reconstructed, fixing the problem. --- .../source/ncm/ncm_content_manager_impl.cpp | 6 ++++-- stratosphere/ncm/source/ncm_main.cpp | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp b/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp index 655a2cba1..43a497557 100644 --- a/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp +++ b/libraries/libstratosphere/source/ncm/ncm_content_manager_impl.cpp @@ -784,7 +784,8 @@ namespace ams::ncm { } Result ContentManagerImpl::BuildContentMetaDatabase(StorageId storage_id) { - if (hos::GetVersion() < hos::Version_5_0_0) { + /* 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 || hos::GetVersion() >= hos::Version_17_0_0) { /* Temporarily activate the database. */ R_TRY(this->ActivateContentMetaDatabase(storage_id)); ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); }; @@ -946,7 +947,8 @@ namespace ams::ncm { R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem)); /* Try to build or import a database, depending on our configuration. */ - if (manager_config.ShouldBuildDatabase()) { + /* NOTE: To work around a change in save management behavior in 17.0.0+, we build the database if needed. */ + if (manager_config.ShouldBuildDatabase() || hos::GetVersion() >= hos::Version_17_0_0) { /* If we should build the database, do so. */ R_TRY(this->BuildContentMetaDatabase(StorageId::BuiltInSystem)); R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem)); diff --git a/stratosphere/ncm/source/ncm_main.cpp b/stratosphere/ncm/source/ncm_main.cpp index e1fe85c59..a5f1688cc 100644 --- a/stratosphere/ncm/source/ncm_main.cpp +++ b/stratosphere/ncm/source/ncm_main.cpp @@ -170,16 +170,18 @@ namespace ams { fs::SetAllocator(Allocate, Deallocate); fs::SetEnabledAutoAbort(false); + /* Initialize ncm api. */ + /* NOTE: Nintendo does this after initializing and starting threads. */ + ncm::InitializeWithObject(g_ncm_manager_service_object.GetShared()); + /* Create and initialize the content manager. */ R_ABORT_UNLESS(g_ncm_manager_service_object.GetImpl().Initialize(ManagerConfig)); + /* Initialize ncm's server and start threads. */ R_ABORT_UNLESS(g_ncm_server_manager.Initialize()); R_ABORT_UNLESS(g_ncm_server_manager.StartThreads()); - /* Initialize ncm api. */ - ncm::InitializeWithObject(g_ncm_manager_service_object.GetShared()); - /* Initialize lr's server and start threads. */ R_ABORT_UNLESS(g_lr_server_manager.Initialize()); R_ABORT_UNLESS(g_lr_server_manager.StartThreads());