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.
This commit is contained in:
Michael Scire 2023-10-12 08:17:05 -07:00
parent 89a7b2df35
commit 337fcf07a4
2 changed files with 9 additions and 5 deletions

View file

@ -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));

View file

@ -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());