mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
psel: Number of improvements. Added PselUiMode_NintendoAccountAuthorizationRequestContext. Various naming adjustments. Implemented pselShowUserSelector properly, and added pselShowUserSelectorForSystem/pselShowUserSelectorForLauncher. Use accountIsUserRegistrationRequestPermitted and accountTrySelectUserWithoutInteraction. Added PselUserSelectionPurpose, PselNintendoAccountStartupDialogType, PselUserSelectionSettings, and PselUserSelectionSettingsForSystemService.
This commit is contained in:
parent
bd04667eda
commit
bbcabee29f
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @file psel.h
|
||||
* @brief Wrapper for using playerSelect (user selection applet).
|
||||
* @brief Wrapper for using the playerSelect (user selection) LibraryApplet.
|
||||
* @author XorTroll, yellows8
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
@ -10,13 +10,13 @@
|
||||
|
||||
/// playerSelect UI modes.
|
||||
typedef enum {
|
||||
PselUiMode_UserSelector = 0, ///< Simple user selection (new users cannot be created).
|
||||
PselUiMode_UserCreator = 1, ///< User creation.
|
||||
PselUiMode_UserSelector = 0, ///< UserSelector
|
||||
PselUiMode_UserCreator = 1, ///< UserCreator
|
||||
PselUiMode_EnsureNetworkServiceAccountAvailable = 2, ///< EnsureNetworkServiceAccountAvailable
|
||||
PselUiMode_UserIconEditor = 3, ///< UserIconEditor
|
||||
PselUiMode_UserNicknameEditor = 4, ///< UserNicknameEditor
|
||||
PselUiMode_UserCreatorForStarter = 5, ///< Mode "starter" uses to register the console's first user on the initial setup.
|
||||
// TODO: Add mode 6.
|
||||
PselUiMode_UserCreatorForStarter = 5, ///< UserCreatorForStarter
|
||||
PselUiMode_NintendoAccountAuthorizationRequestContext = 6, ///< NintendoAccountAuthorizationRequestContext
|
||||
PselUiMode_IntroduceExternalNetworkServiceAccount = 7, ///< IntroduceExternalNetworkServiceAccount
|
||||
PselUiMode_IntroduceExternalNetworkServiceAccountForRegistration = 8, ///< [6.0.0+] IntroduceExternalNetworkServiceAccountForRegistration
|
||||
PselUiMode_NintendoAccountNnidLinker = 9, ///< [6.0.0+] NintendoAccountNnidLinker
|
||||
@ -25,29 +25,71 @@ typedef enum {
|
||||
PselUiMode_UserCreatorForImmediateNaLoginTest = 12, ///< [7.0.0+] UserCreatorForImmediateNaLoginTest
|
||||
} PselUiMode;
|
||||
|
||||
/// UI message text to display with ::PselUiMode_UserSelector. Invalid values are handled as ::PselUserSelectionPurpose_General.
|
||||
typedef enum {
|
||||
PselUserSelectionPurpose_General = 0, ///< "Select a user."
|
||||
PselUserSelectionPurpose_GameCardRegistration = 1, ///< [2.0.0+] "Who will receive the points?"
|
||||
PselUserSelectionPurpose_EShopLaunch = 2, ///< [2.0.0+] "Who is using Nintendo eShop?"
|
||||
PselUserSelectionPurpose_EShopItemShow = 3, ///< [2.0.0+] "Who is making this purchase?"
|
||||
PselUserSelectionPurpose_PicturePost = 4, ///< [2.0.0+] "Who is posting?"
|
||||
PselUserSelectionPurpose_NintendoAccountLinkage = 5, ///< [2.0.0+] "Select a user to link to a Nintendo Account."
|
||||
PselUserSelectionPurpose_SettingsUpdate = 6, ///< [2.0.0+] "Change settings for which user?"
|
||||
PselUserSelectionPurpose_SaveDataDeletion = 7, ///< [2.0.0+] "Format data for which user?"
|
||||
PselUserSelectionPurpose_UserMigration = 8, ///< [4.0.0+] "Which user will be transferred to another console?"
|
||||
PselUserSelectionPurpose_SaveDataTransfer = 9, ///< [8.0.0+] "Send save data for which user?"
|
||||
} PselUserSelectionPurpose;
|
||||
|
||||
/// NintendoAccountStartupDialogType
|
||||
typedef enum {
|
||||
PselNintendoAccountStartupDialogType_LoginAndCreate = 0, ///< LoginAndCreate
|
||||
PselNintendoAccountStartupDialogType_Login = 1, ///< Login
|
||||
PselNintendoAccountStartupDialogType_Create = 2, ///< Create
|
||||
} PselNintendoAccountStartupDialogType;
|
||||
|
||||
/// Base UI settings for playerSelect.
|
||||
typedef struct {
|
||||
u32 mode; ///< \ref PselUiMode
|
||||
u32 dialog_type; ///< Dialog type.
|
||||
AccountUid user_list[ACC_USER_LIST_SIZE]; ///< List of \ref AccountUid.
|
||||
u8 unk_x88[0x8]; ///< Unknown.
|
||||
u8 network_service_required; ///< Whether the user needs to be linked to a Nintendo account.
|
||||
u8 unk_x91[0x2]; ///< Unknown.
|
||||
u8 allow_user_creation; ///< (With ::PselUiMode_SelectUser) enables the option to create a new user.
|
||||
u8 skip_enabled; ///< Enables the option to skip user selection (a new button is shown)
|
||||
u8 unk_x95[0x3]; ///< Unknown.
|
||||
u32 pad; ///< Padding.
|
||||
AccountUid invalid_uid_list[ACC_USER_LIST_SIZE]; ///< List of \ref AccountUid. TODO: This is only correct for ::PselUiMode_UserSelector, for other modes this is a single uid, followed by mode-specific data (if any).
|
||||
u64 application_id; ///< ApplicationId with \ref pselShowUserSelectorForLauncher.
|
||||
u8 is_network_service_account_required; ///< PselUserSelectionSettings::is_network_service_account_required.
|
||||
u8 is_skip_enabled; ///< PselUserSelectionSettings::is_skip_enabled
|
||||
u8 unk_x92; ///< Set to value 1 by \ref pselShowUserSelectorForSystem / \ref pselShowUserSelectorForLauncher.
|
||||
u8 is_permitted; ///< isPermitted. With ::PselUiMode_UserSelector: enables the option to create a new user. Set to the output from \ref accountIsUserRegistrationRequestPermitted with pselShowUserSelector*. When not set, a dialog will be displayed when the user attempts to create an user.
|
||||
u8 show_skip_button; ///< PselUserSelectionSettings::show_skip_button
|
||||
u8 additional_select; ///< PselUserSelectionSettings::additional_select
|
||||
u8 unk_x96; ///< [2.0.0+] Set to PselUserSelectionSettingsForSystemService::enable_user_creation_button. \ref pselShowUserSelectorForLauncher / \ref pselShowUserSelector sets this to value 1.
|
||||
u8 unk_x97; ///< [6.0.0+] Set to PselUserSelectionSettings::is_unqualified_user_selectable ^ 1.
|
||||
} PselUiSettingsV1;
|
||||
|
||||
/// UI settings for versions starting with 0x10000.
|
||||
typedef struct {
|
||||
PselUiSettingsV1 settings; ///< \ref PselUiSettingsV1
|
||||
u8 unk_x98[0x8]; ///< Unknown.
|
||||
u32 unk_x98; ///< [2.0.0+] Set to PselUserSelectionSettingsForSystemService::purpose.
|
||||
u8 unk_x9c[0x4]; ///< Unknown.
|
||||
} PselUiSettings;
|
||||
|
||||
/// UserSelectionSettings
|
||||
typedef struct {
|
||||
AccountUid invalid_uid_list[ACC_USER_LIST_SIZE]; ///< invalidUidList.
|
||||
u8 is_skip_enabled; ///< isSkipEnabled. When set, the first user in invalid_uid_list must not be set, and additional_select must be 0. When enabled \ref accountTrySelectUserWithoutInteraction will be used to select the user, in this case the applet will only be launched if \ref accountTrySelectUserWithoutInteraction doesn't return an user.
|
||||
u8 is_network_service_account_required; ///< isNetworkServiceAccountRequired. Whether the user needs to be linked to a Nintendo account.
|
||||
u8 show_skip_button; ///< showSkipButton. Enables the option to skip user selection with a button.
|
||||
u8 additional_select; ///< additionalSelect.
|
||||
u8 is_unqualified_user_selectable; ///< [6.0.0+] isUnqualifiedUserSelectable
|
||||
} PselUserSelectionSettings;
|
||||
|
||||
/// [2.0.0+] UserSelectionSettingsForSystemService
|
||||
typedef struct {
|
||||
u32 purpose; ///< \ref PselUserSelectionPurpose
|
||||
u8 enable_user_creation_button; ///< Enables the user-creation button when set. Whether user-creation when pressing the button is actually allowed is controlled by PselUiSettingsV1::is_permitted.
|
||||
u8 pad[0x3]; ///< Padding.
|
||||
} PselUserSelectionSettingsForSystemService;
|
||||
|
||||
/// Return data sent after execution.
|
||||
typedef struct {
|
||||
Result res; ///< Result.
|
||||
AccountUid user_id; ///< Selected \ref AccountUid.
|
||||
Result res; ///< Result.
|
||||
AccountUid user_id; ///< Selected \ref AccountUid.
|
||||
} PselUiReturnArg;
|
||||
|
||||
/**
|
||||
@ -69,11 +111,11 @@ void pselUiAddUser(PselUiSettings *ui, AccountUid user_id);
|
||||
* @brief Sets whether users can be created in the applet.
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param flag Flag value.
|
||||
* @note Only used for ::PselUiMode_SelectUser
|
||||
* @note Only used for ::PselUiMode_SelectUser.
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetAllowUserCreation(PselUiSettings *ui, bool flag) {
|
||||
if(ui->settings.mode == PselUiMode_UserSelector) {
|
||||
ui->settings.allow_user_creation = flag;
|
||||
ui->settings.is_permitted = flag!=0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,16 +125,16 @@ NX_CONSTEXPR void pselUiSetAllowUserCreation(PselUiSettings *ui, bool flag) {
|
||||
* @param flag Flag value.
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetNetworkServiceRequired(PselUiSettings *ui, bool flag) {
|
||||
ui->settings.network_service_required = flag;
|
||||
ui->settings.is_network_service_account_required = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets whether selection can be skipped (with a new button).
|
||||
* @brief Sets whether selection can be skipped with a button.
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param flag Flag value.
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetSkipEnabled(PselUiSettings *ui, bool flag) {
|
||||
ui->settings.skip_enabled = flag;
|
||||
NX_CONSTEXPR void pselUiSetSkipButtonEnabled(PselUiSettings *ui, bool flag) {
|
||||
ui->settings.show_skip_button = flag!=0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,13 +146,34 @@ NX_CONSTEXPR void pselUiSetSkipEnabled(PselUiSettings *ui, bool flag) {
|
||||
Result pselUiShow(PselUiSettings *ui, AccountUid *out_user);
|
||||
|
||||
/**
|
||||
* @brief Shows the applet to select a user.
|
||||
* @brief This is the System version of \ref pselShowUserSelector.
|
||||
* @note This uses \ref accountIsUserRegistrationRequestPermitted, hence \ref accountInitialize must be used prior to this. See also the docs for PselUserSelectionSettings::is_skip_enabled.
|
||||
* @param[out] out_user Returned selected user ID.
|
||||
* @param[in] settings \ref PselUserSelectionSettings
|
||||
* @param[in] settings_system [2.0.0+] \ref PselUserSelectionSettingsForSystemService, ignored on prior versions.
|
||||
*/
|
||||
Result pselShowUserSelector(AccountUid *out_user);
|
||||
Result pselShowUserSelectorForSystem(AccountUid *out_user, const PselUserSelectionSettings *settings, const PselUserSelectionSettingsForSystemService *settings_system);
|
||||
|
||||
/**
|
||||
* @brief This is the Launcher version of \ref pselShowUserSelector.
|
||||
* @note This uses \ref accountIsUserRegistrationRequestPermitted, hence \ref accountInitialize must be used prior to this. See also the docs for PselUserSelectionSettings::is_skip_enabled.
|
||||
* @param[out] out_user Returned selected user ID.
|
||||
* @param[in] settings \ref PselUserSelectionSettings
|
||||
* @param[in] application_id ApplicationId
|
||||
*/
|
||||
Result pselShowUserSelectorForLauncher(AccountUid *out_user, const PselUserSelectionSettings *settings, u64 application_id);
|
||||
|
||||
/**
|
||||
* @brief Shows the applet to select a user.
|
||||
* @note This uses \ref accountIsUserRegistrationRequestPermitted, hence \ref accountInitialize must be used prior to this. See also the docs for PselUserSelectionSettings::is_skip_enabled.
|
||||
* @param[out] out_user Returned selected user ID.
|
||||
* @param[in] settings \ref PselUserSelectionSettings
|
||||
*/
|
||||
Result pselShowUserSelector(AccountUid *out_user, const PselUserSelectionSettings *settings);
|
||||
|
||||
/**
|
||||
* @brief Shows the applet to create a user.
|
||||
* @note This uses \ref accountIsUserRegistrationRequestPermitted, hence \ref accountInitialize must be used prior to this. If the output flag is 0, an error will be thrown.
|
||||
*/
|
||||
Result pselShowUserCreator(void);
|
||||
|
||||
|
@ -11,8 +11,8 @@ Result pselUiCreate(PselUiSettings *ui, PselUiMode mode) {
|
||||
|
||||
void pselUiAddUser(PselUiSettings *ui, AccountUid user_id) {
|
||||
for(u32 i=0; i<ACC_USER_LIST_SIZE; i++) {
|
||||
if(!accountUidIsValid(&ui->settings.user_list[i])) {
|
||||
ui->settings.user_list[i] = user_id;
|
||||
if(!accountUidIsValid(&ui->settings.invalid_uid_list[i])) {
|
||||
ui->settings.invalid_uid_list[i] = user_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,8 @@ Result pselUiShow(PselUiSettings *ui, AccountUid *out_user) {
|
||||
arg_size = sizeof(ui->settings);
|
||||
}
|
||||
|
||||
// TODO: Official sw supports pushing an optional additional storage from appletCreateTransferMemoryStorage with writable=0 using an input buffer, when that buffer is specified. However, sdknso itself doesn't use this besides a wrapper func. Figure out what this, and implement it?(libappletLaunch could no longer be used with this)
|
||||
|
||||
rc = libappletLaunch(AppletId_playerSelect, &args, arg_ptr, arg_size, &ret, sizeof(ret), &reply_size);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
@ -52,21 +54,100 @@ Result pselUiShow(PselUiSettings *ui, AccountUid *out_user) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserSelector(AccountUid *out_user) {
|
||||
static Result _pselUserSelectorCommonInit(PselUiSettings *ui, const PselUserSelectionSettings *settings) {
|
||||
Result rc=0;
|
||||
bool tmp=0;
|
||||
|
||||
rc = accountIsUserRegistrationRequestPermitted(&tmp);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
ui->settings.is_permitted = tmp!=0;
|
||||
|
||||
memcpy(&ui->settings.invalid_uid_list, settings->invalid_uid_list, sizeof(settings->invalid_uid_list));
|
||||
ui->settings.is_network_service_account_required = settings->is_network_service_account_required;
|
||||
ui->settings.is_skip_enabled = settings->is_skip_enabled;
|
||||
|
||||
ui->settings.show_skip_button = settings->show_skip_button;
|
||||
ui->settings.additional_select = settings->additional_select;
|
||||
if (hosversionAtLeast(6,0,0))
|
||||
ui->settings.unk_x97 = settings->is_unqualified_user_selectable ^ 1;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _pselShowUserSelectorCommon(PselUiSettings *ui, AccountUid *out_user) {
|
||||
Result rc=0;
|
||||
bool show_psel=1;
|
||||
|
||||
if (ui->settings.is_skip_enabled!=0) {
|
||||
if (accountUidIsValid(&ui->settings.invalid_uid_list[0]) || ui->settings.additional_select)
|
||||
rc = MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = accountTrySelectUserWithoutInteraction(out_user, ui->settings.is_network_service_account_required);
|
||||
if (R_SUCCEEDED(rc) && accountUidIsValid(out_user)) show_psel = 0;
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc) && show_psel)
|
||||
rc = pselUiShow(ui, out_user);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserSelectorForSystem(AccountUid *out_user, const PselUserSelectionSettings *settings, const PselUserSelectionSettingsForSystemService *settings_system) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserSelector);
|
||||
// TODO: This is missing the rest of the UiSettings setup done by official sw.
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = pselUiShow(&ui, out_user);
|
||||
rc = _pselUserSelectorCommonInit(&ui, settings);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
ui.settings.unk_x92 = 1;
|
||||
if (hosversionAtLeast(2,0,0)) {
|
||||
ui.settings.unk_x96 = settings_system->enable_user_creation_button;
|
||||
ui.unk_x98 = settings_system->purpose;
|
||||
}
|
||||
}
|
||||
|
||||
if(R_SUCCEEDED(rc)) rc = _pselShowUserSelectorCommon(&ui, out_user);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserSelectorForLauncher(AccountUid *out_user, const PselUserSelectionSettings *settings, u64 application_id) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserSelector);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = _pselUserSelectorCommonInit(&ui, settings);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
ui.settings.application_id = application_id;
|
||||
ui.settings.unk_x92 = 1;
|
||||
if (hosversionAtLeast(2,0,0))
|
||||
ui.settings.unk_x96 = 1;
|
||||
}
|
||||
|
||||
if(R_SUCCEEDED(rc)) rc = _pselShowUserSelectorCommon(&ui, out_user);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserSelector(AccountUid *out_user, const PselUserSelectionSettings *settings) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserSelector);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = _pselUserSelectorCommonInit(&ui, settings);
|
||||
if(R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0)) ui.settings.unk_x96 = 1;
|
||||
|
||||
if(R_SUCCEEDED(rc)) rc = _pselShowUserSelectorCommon(&ui, out_user);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserCreator(void) {
|
||||
PselUiSettings ui;
|
||||
bool tmp=0;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserCreator);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
rc = accountIsUserRegistrationRequestPermitted(&tmp);
|
||||
if(R_SUCCEEDED(rc) && tmp==0) rc = MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen);
|
||||
|
||||
if(R_SUCCEEDED(rc)) rc = pselUiShow(&ui, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user