Luma3DS icon indicating copy to clipboard operation
Luma3DS copied to clipboard

[Feature request] Stub `FS::Get[This]SaveDataSecureValue` to always allow loading of saves

Open duckfromdiscord opened this issue 1 year ago • 10 comments

Some 3DS games like "Rusty's Real Deal Baseball" won't load their saves after they've been restored by a save manager such as Checkpoint. I tried for weeks to figure out why, and apparently the IPC calls responsible for this issue are GetThisSaveDataSecureValue and GetSaveDataSecureValue. There's a flag there that, if set incorrectly, will prevent these games from loading their saves. I found this out because Citra had this issue: https://github.com/citra-emu/citra/pull/7191. Is it possible for us to stub these IPC calls in Luma3DS, or somehow using a patch?

If this is not possible, let me know, and I will continue researching into patching the individual games. But since there's at least two of these games that currently won't load a modified save because of this IPC, I think it may be better to fix them all at once.

duckfromdiscord avatar Jan 08 '24 15:01 duckfromdiscord

Why shouldn't Checkpoint set the flag?

eku avatar Jan 09 '24 06:01 eku

As far as i'm aware the way save managers handle secure values is to just delete them because in most games this triggers the game to just create a new secure value and move on. A way to get around this would be restoring secure values along with the savegame they match to.

profi200 avatar Jan 09 '24 11:01 profi200

Why shouldn't Checkpoint set the flag?

Is the flag returned by the system process or is it set as a part of the secure value itself? I don't quite understand how this flag is determined.

Anyway, myself and one other person in the Checkpoint Discord server asked for help last week but there has been no response yet. The last stable Checkpoint release for 3DS was released 5 years ago, in 2019. A newer release caused instability, causing development to stop.

A way to get around this would be restoring secure values along with the savegame they match to.

Up until now, all backup saves in existence won't have the secure values since the save managers that have been in use aren't saving them yet, only the save files themselves. We can start saving them and restore them with saves right now, but that won't fix old backups.

Fixing the problem at the source by patching the system process would allow all saves to pass the check. Perhaps this should be added, but optional.

duckfromdiscord avatar Jan 09 '24 16:01 duckfromdiscord

Anyway, myself and one other person in the Checkpoint Discord server asked for help last week but there has been no response yet. The last stable Checkpoint release for 3DS was released 5 years ago, in 2019. A newer release caused instability, causing development to stop.

Did you try JKSM?

Fixing the problem at the source by patching the system process

Let's leave it to the developers of Luma to decide whether they want to correct errors from savemanagers in their code.

eku avatar Jan 10 '24 06:01 eku

This is the responsibility of the save manager. I looked it up and the "exists" flag is literally that. The game checks if the secure value exists. If Luma would patch this the check would fail anyway because there is no valid secure value (the save manager deleted it).

profi200 avatar Jan 10 '24 14:01 profi200

Did you try JKSM?

I'm on the latest version (05.08.2020) and just tried restoring a save, but the game still rejects it. The latest commit was more recent, though; only 3 years ago, and I don't think development there has stopped entirely. I could open an issue there.

I looked it up and the "exists" flag is literally that.

What do you mean by "exists" flag? Is that the flag in question that only these three games are looking for?

This is the responsibility of the save manager.

So, assuming we can get JKSM and/or Checkpoint on board with backing up the secure value, how will we deal with old saves?

If Luma would patch this the check would fail anyway because there is no valid secure value (the save manager deleted it).

Can't we just do what Citra does and provide a 0 for the (now non-existent) secure value?

rb.Push(RESULT_SUCCESS);
rb.Push<bool>(false); // indicates that the secure value doesn't exist
rb.Push<bool>(true);  // seems to override checking the validity so should be true
rb.Push<u64>(0);      // the secure value

The game I tried started working in the emulator after the release with this commit came out, so assuming we patch the IPC to return those values, they should work on the console as well.

I know for a fact it works because I wasn't able to load saves in the emulator either until I updated.

EDIT: I accidentally posted the entire diff, instead of just the new code. This is fixed now.

duckfromdiscord avatar Jan 11 '24 02:01 duckfromdiscord

With that code, all games should load saves unconditionally. The IPC will correctly indicate that there is no secure value (and return 0 for it accordingly), set a flag to bypass the check entirely, and also account for this other flag that only these three games check.

duckfromdiscord avatar Jan 11 '24 03:01 duckfromdiscord

I have researched the FS module further. The unknown value seems to be hardcoded to be set to true if the requester process is a gamecard, otherwise it is set to false.

PabloMK7 avatar Jan 15 '24 16:01 PabloMK7

Very interesting. My guess is Nintendo decided it would be too difficult for a user to edit save data on a gamecard, and as such they might as well bypass the check.

What doesn't make sense is that the games in question using this flag are eShop games, not cartridges. Unless I'm getting two different flags confused.

EDIT: Though I suppose there is probably other logic that happens for eShop games.

duckfromdiscord avatar Jan 15 '24 20:01 duckfromdiscord

You are probably getting the idea wrong. The secure value is stored in NAND, while the save data is on the SD or the game card itself. It doesn't make sense to have a secure value for game cards because you can put the game card on another console which may have a different secure value.

Also, the SDK (and therefore, the function that checks the secure value) is the same for digital and physical games.

PabloMK7 avatar Jan 15 '24 20:01 PabloMK7