nimbus
nimbus copied to clipboard
[Enhancement]: Remove `account_checks.s`
Checked Existing
- [x] I have checked the repository for duplicate issues.
What enhancement would you like to see?
Nimbus is essentially just https://github.com/zaksabeast/3ds-Friend-Account-Manager with a fancier UI and some extra patches, which means we inherited a lot of the original patches from Zaks work. However due to the research done by @DaniElectra and @ZeroSkill1, some of this can be fixed up
The following is a copy-paste of the messages from @ZeroSkill1 and @TraceEntertains from the SpotPass Archival Discord server:
Trace:
Really random, and sorry to bother you, but can you check what checks this code patches? https://github.com/PretendoNetwork/nimbus/blob/main/patches/friends/src/account_checks.s
Zero:
0x102536 -> FRDA:CreateLocalAccount patches out the part that checks whether or not an account is already loaded, because you can't create an account when another is currently loaded (this is NOT the correct way to do this...)
0x101968 -> FRDA:LoadLocalAccount patches out the check whether another account is already loaded (again, NOT the correct way to do this) you are supposed to use FRDA:UnloadLocalAccount to unload the current account
you can also get the current local account id using FRDU:GetMyLocalAccountId to store ideally, it should be as follows:
- FRDU:GetMyLocalAccountId, to store as the "Nintendo" friends account id
- FRDA:UnloadLocalAccount, to unload the official account
- FRDA:CreateLocalAccount, to create an account to use for Pretendo
- FRDA:LoadLocalAccount, to load the Pretendo account
- FRDA:SaveLocalAccountData, to save these changes
Any other details to share? (OPTIONAL)
The exact steps mentioned by Zero would need to be modified a bit to fit our needs (they seem to assume the Nintendo account is always loaded first, and the steps create a new Pretendo account each time, neither of which are the case), but we should definitely look into moving into the correct ways to handle this rather than patching checks unnecessarily like we currently do
Hey there! I think my response came off a little aggressive, which was not really my intention. It's just that having seen the ins and outs of act/friends and the proper command usage, then seeing such a hacky workaround is a little off-putting lol. So yeah, sorry about that.
In any case, here are the proper steps to create/switch accounts, for each of act/friends. It's important that account creation/switching for friends is done first, as this affects account creation in act.
friends
The steps I mentioned in my initial response correspond to a time when a user has first installed nimbus, or in other words, when only the official account exists and the user switches to Pretendo:
(Note 1: The Nintendo friends local account ID will, by default, be 1) (Note 2: The loaded account is also the default account that will be loaded on startup)
- FRDA:UnloadLocalAccount, to unload the official account
- FRDA:CreateLocalAccount, to create an account to use with Pretendo Network
- This command allows specifying the account ID, and I recommend using a common one so nimbus can recognize which account is loaded.
- FRDA:LoadLocalAccount, to load the Pretendo account
- FRDA:SaveLocalAccountData, to save these changes to the system save data.
Steps for switching accounts:
- FRDU:GetMyLocalAccountId.
- ideally, display to the user which account is loaded.
- FRDA:UnloadLocalAccount
- FRDA:LoadLocalAccount with either the Nintendo/Pretendo account ID based on the user's choice.
- FRDA:SaveLocalAccountData
act
As far as I'm aware, nimbus currently attempts to "reset" (which is actually ACTA:UnloadLocalAccount) the currently loaded account. This will have unexpected consequences because act does not reset the FpLocalAccountId when unloading console accounts. This can potentially lead to a mismatch between the FpLocalAccountId stored in the act savedata and the currently loaded friends account (as I have been informed, this has caused issues with system transfers?)
Steps for initial account creation, similar to the above for friends:
(Note 1: the default Nintendo account slot will be 1) (Note 2: the "default" account is the account act loads on startup, which can be, but is not always, the currently loaded account)
- ACTA:UnloadConsoleAccount to unload the Nintendo console account.
- ACTA:CreateConsoleAccount to create the Pretendo console account.
- the Pretendo account slot is equal to the value gotten from ACTU:GetCommonInfo (before CreateConsoleAccount) with BlkId 0x2 + 1
- ACTA:CommitConsoleAccount using the Pretendo account slot. I have also noticed this patch for the act module. When a console account is created using ACTA:CreateConsoleAccount, the newly created account is set as "not committed" (i.e. act treats it as a temporary account and will delete it on startup). What the mentioned patch does is actually prevent act from deleting not committed accounts. Instead of this patch, one can use ACTA:CommitConsoleAccount to mark the newly created Pretendo console account as committed.
- ACTA:SetDefaultAccount using the Pretendo account slot.
- ACTA:LoadConsoleAccount using the Pretendo account slot, with all other parameters set to 0
- ACTU:Save to save these changes.
Steps for switching accounts:
- ACTA:UnloadConsoleAccount
- ACTA:SetDefaultAccount with either the Nintendo/Pretendo account slot
- ACTA:LoadConsoleAccount using the Nintendo/Pretendo account slot, all other params set to 0
- ACTU:Save to save these changes.
That is interesting, thanks for your insight!
You mention in your steps the need to save the changes with the respective commands. However, in our current code we don't do that, and we simply reboot the system, but the changes do get saved on the system savedata. Do we know if saving is actually required, or why it works in our use case?
Rebooting the system works in this case because act and friends both save pending changes to the system save when the system powers off (the modules perform some cleanup work when termination is requested, saving data is part of this). It is not strictly required to save the changes manually.
I completely forgot that a reboot is necessary for some of these patches. Thus, you can rely on the modules to save the data for you in this case.
My only concern about this at the moment is how to migrate accounts and updating the patches without breaking anything in the process (this is specifically about the ACT patches).
If we simply let users update the patches, the ACT accounts of Pretendo won't be commited, and when starting the console they will get deleted. I'm not sure what would happen when trying to boot the console into an uncommited account though. In the best case, ACT would simply delete it and make it again to boot into it. In worst case, this could lead to consoles crashing on startup. There's also a middle ground where the account gets deleted and falls back into the Nintendo ACT ccount, which would mean the console would be in a mixed state where the Friends account is for Pretendo but the ACT account is the one for Nintendo.
None of these cases seem like a good idea to handle, but the alternatives don't look great either. Ideally we would be able to commit the accounts before people update their systems. The issue is, how do we manage to do that? An announcement telling people to commit the accounts (with some custom app or by updating Nimbus but not the patches?) would cover the basis, but there may be cases where people aren't aware of this and will directly update (especially those using Universal-Updater) without knowing the risks involved.
Before we get deeper into the issue, I will ask @ZeroSkill1 if he knows more about what would happen when trying to boot into an uncommited account, so that we know what would really happen in this case and consider our options.
what would happen when trying to boot into an uncommited account
Isn't that what we're already doing? Our patches don't commit the accounts, but they also patch out the part that deletes them on startup. So currently whenever someone boots their 3DS while Nimbus has Pretendo selected, they're booting into an uncommitted account
My suggestion right now would be to update Nimbus to handle this proper and commit everything, but keep the "don't delete uncommitted accounts" patches in place for a while. Then after a good amount of time has passed (like, say a year or so), with regular reminder announcements, we remove the "don't delete uncommitted accounts" patches as well
That way we give buffer time for people to get themselves updated, and if someone is not paying attention to our announcements for over a year then I think we can safely "sacrifice" them (my understanding is that this would just delete the account and put them back into the Nintendo one, so the console is safe they just need to remake their NEX account)
That seems fair. We could update the friends patches and Nimbus and leave ACT for a later time
@DaniElectra Pretty much the first thing act does after reading the save data from the NAND is deleting uncommitted accounts. Therefore if the current account is uncommitted it will be deleted immediately.
act then attempts to load the default account. If the Pretendo console account was loaded and set as default, this will obviously fail because it was deleted due to being uncommitted.
When act fails to load the default account (either a) if no account was set by default, or b) if the default account was deleted, as in the case above), it will attempt to load the account in slot 1. By default this will be the Nintendo console account, as you correctly assumed above. (This will cause any subsequent NNID logins to fail as act will be using the NNID console account when the associated PNID's friends account is loaded.)
If that fails (and this will only happen if the act system save was deleted and recreated, e.g. on initial setup), it will create (and commit) a dummy account in slot 1 and will load that instead.
(This will cause any subsequent NNID logins to fail as act will be using the NNID console account when the associated PNID's friends account is loaded.)
I think this should be fine? The only time this would really be an issue is if someone got into this state without the intention of using our servers again. But the only time this state would happen (at least, in terms of stuff that has to do with us) is if someone updated our patches after we removed the "don't delete uncommitted accounts" patches, so I think in that case it's clear that the user intends to use our services again (as they've just gone through the trouble of updating the patches) and thus Nimbus would be used shortly after the uncommitted account is deleted, which should restore things to the correct state?
We can also add an information button to Nimbus explaining this if need be