mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
psel: Various improvements, including proper version handling. Updated names. Renamed/added modes, with sysver docs. Don't use ptrs for input AccountUids. Added pselShowUserCreatorForStarter and pselShowNintendoAccountNnidLinker. Directly return the Result from PselUiReturnArg. Removed the output user param from pselShowUserCreator.
This commit is contained in:
parent
5182b57a1d
commit
4078de1eff
@ -1,71 +1,79 @@
|
||||
/**
|
||||
* @file psel.h
|
||||
* @brief Wrapper for using playerSelect (user selection applet).
|
||||
* @author XorTroll
|
||||
* @author XorTroll, yellows8
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include "../types.h"
|
||||
#include "../services/applet.h"
|
||||
#include "../services/acc.h"
|
||||
|
||||
/// playerSelect UI modes.
|
||||
typedef enum {
|
||||
PselUiMode_SelectUser = 0, ///< Simple user selection (new users cannot be created).
|
||||
PselUiMode_UserCreation = 1, ///< Only user creation (the user is later returned).
|
||||
PselUiMode_EnsureNsaAvailable = 2, ///< EnsureNsaAvailable
|
||||
PselUiMode_IconEditor = 3, ///< IconEditor
|
||||
PselUiMode_NicknameEditor = 4, ///< NicknameEditor
|
||||
PselUiMode_ForStarter = 5, ///< Mode "starter" uses to register the console's first user on the initial setup
|
||||
PselUiMode_NetworkServiceAccountRegistration = 8, ///< NetworkServiceAccountRegistration
|
||||
PselUiMode_NintendoAccountNnidLinker = 9, ///< NintendoAccountNnidLinker
|
||||
PselUiMode_LicenseRequirementsForNetworkService = 10, ///< LicenseRequirementsForNetworkService
|
||||
PselUiMode_NaLoginTest = 12, ///< NaLoginTest
|
||||
PselUiMode_UserSelector = 0, ///< Simple user selection (new users cannot be created).
|
||||
PselUiMode_UserCreator = 1, ///< User creation.
|
||||
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_IntroduceExternalNetworkServiceAccount = 7, ///< IntroduceExternalNetworkServiceAccount
|
||||
PselUiMode_IntroduceExternalNetworkServiceAccountForRegistration = 8, ///< [6.0.0+] IntroduceExternalNetworkServiceAccountForRegistration
|
||||
PselUiMode_NintendoAccountNnidLinker = 9, ///< [6.0.0+] NintendoAccountNnidLinker
|
||||
PselUiMode_LicenseRequirementsForNetworkService = 10, ///< [6.0.0+] LicenseRequirementsForNetworkService
|
||||
PselUiMode_LicenseRequirementsForNetworkServiceWithUserContextImpl = 11, ///< [7.0.0+] LicenseRequirementsForNetworkServiceWithUserContextImpl
|
||||
PselUiMode_UserCreatorForImmediateNaLoginTest = 12, ///< [7.0.0+] UserCreatorForImmediateNaLoginTest
|
||||
} PselUiMode;
|
||||
|
||||
/// UI settings for playerSelect.
|
||||
/// Base UI settings for playerSelect.
|
||||
typedef struct {
|
||||
u32 mode; ///< UI mode, see \ref PselUiMode.
|
||||
u32 dialogType; ///< Dialog type
|
||||
AccountUid invalidUserList[ACC_USER_LIST_SIZE]; ///< List of \ref AccountUid user IDs which will be disabled.
|
||||
u8 unk_x88[0x8]; ///< Unknown.
|
||||
u8 networkServiceRequired; ///< Whether the user needs to be linked to a Nintendo account.
|
||||
u8 unk_x91[0x2]; ///< Unknown.
|
||||
u8 allowUserCreation; ///< (With ::PselUiMode_SelectUser) enables the option to create a new user.
|
||||
u8 skipEnabled; ///< Enables the option to skip user selection (a new button is shown)
|
||||
u8 unk_x95[0xb]; ///< Unknown.
|
||||
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.
|
||||
} PselUiSettingsV1;
|
||||
|
||||
/// UI settings for versions starting with 0x10000.
|
||||
typedef struct {
|
||||
PselUiSettingsV1 settings; ///< \ref PselUiSettingsV1
|
||||
u8 unk_x98[0x8]; ///< Unknown.
|
||||
} PselUiSettings;
|
||||
|
||||
/// Result data sent after execution.
|
||||
/// Return data sent after execution.
|
||||
typedef struct {
|
||||
u32 result; ///< Result code.
|
||||
AccountUid userId; ///< Selected \ref AccountUid.
|
||||
} PselResult;
|
||||
Result res; ///< Result.
|
||||
AccountUid user_id; ///< Selected \ref AccountUid.
|
||||
} PselUiReturnArg;
|
||||
|
||||
/**
|
||||
* @brief Creates a new UI config for playerSelect applet with the specified mode.
|
||||
* @brief Creates a new UI config for the playerSelect applet with the specified mode.
|
||||
* @param ui PseluiSettings struct.
|
||||
* @param mode playerSelect UI mode.
|
||||
*/
|
||||
Result pselUiCreate(PselUiSettings *ui, PselUiMode mode);
|
||||
|
||||
/**
|
||||
* @brief Adds a user to the user list of the applet.
|
||||
* @brief Adds an user to the user list of the applet.
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param user_id user ID.
|
||||
* @param[in] user_id user ID.
|
||||
* @note The users will be treated as invalid users for user selection mode, and as the input user for other modes.
|
||||
*/
|
||||
void pselUiAddUser(PselUiSettings *ui, AccountUid *user_id);
|
||||
void pselUiAddUser(PselUiSettings *ui, AccountUid user_id);
|
||||
|
||||
/**
|
||||
* @brief Sets whether users can be created in the applet
|
||||
* @brief Sets whether users can be created in the applet.
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param flag Flag value.
|
||||
* @note Only used for ::PselUiMode_SelectUser
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetAllowUserCreation(PselUiSettings *ui, bool flag) {
|
||||
if(ui->mode == PselUiMode_SelectUser) {
|
||||
ui->allowUserCreation = flag;
|
||||
if(ui->settings.mode == PselUiMode_UserSelector) {
|
||||
ui->settings.allow_user_creation = flag;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,20 +83,20 @@ NX_CONSTEXPR void pselUiSetAllowUserCreation(PselUiSettings *ui, bool flag) {
|
||||
* @param flag Flag value.
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetNetworkServiceRequired(PselUiSettings *ui, bool flag) {
|
||||
ui->networkServiceRequired = flag;
|
||||
ui->settings.network_service_required = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets whether selection can be skipped (with a new button)
|
||||
* @brief Sets whether selection can be skipped (with a new button).
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param flag Flag value.
|
||||
*/
|
||||
NX_CONSTEXPR void pselUiSetSkipEnabled(PselUiSettings *ui, bool flag) {
|
||||
ui->skipEnabled = flag;
|
||||
ui->settings.skip_enabled = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Shows playerSelect applet with the specified UI settings.
|
||||
* @brief Shows the applet with the specified UI settings.
|
||||
* @param ui PselUiSettings struct.
|
||||
* @param out_user Selected user ID.
|
||||
* @note If user skips (see \ref pselUiSetSkipEnabled) this will return successfully but the output ID will be 0.
|
||||
@ -96,25 +104,36 @@ NX_CONSTEXPR void pselUiSetSkipEnabled(PselUiSettings *ui, bool flag) {
|
||||
Result pselUiShow(PselUiSettings *ui, AccountUid *out_user);
|
||||
|
||||
/**
|
||||
* @brief Shows playerSelect applet to select a user.
|
||||
* @param out_user Returned selected user ID.
|
||||
* @brief Shows the applet to select a user.
|
||||
* @param[out] out_user Returned selected user ID.
|
||||
*/
|
||||
Result pselShowUserSelector(AccountUid *out_user);
|
||||
|
||||
/**
|
||||
* @brief Shows playerSelect applet to create a user.
|
||||
* @param out_user Returned created user ID.
|
||||
* @brief Shows the applet to create a user.
|
||||
*/
|
||||
Result pselShowUserCreator(AccountUid *out_user);
|
||||
Result pselShowUserCreator(void);
|
||||
|
||||
/**
|
||||
* @brief Shows playerSelect applet to change a user's icon.
|
||||
* @param user Input user ID.
|
||||
* @brief Shows the applet to change a user's icon.
|
||||
* @param[in] user Input user ID.
|
||||
*/
|
||||
Result pselShowIconEditor(AccountUid *user);
|
||||
Result pselShowUserIconEditor(AccountUid user);
|
||||
|
||||
/**
|
||||
* @brief Shows playerSelect applet to change a user's nickname.
|
||||
* @param user Input user ID.
|
||||
* @brief Shows the applet to change a user's nickname.
|
||||
* @param[in] user Input user ID.
|
||||
*/
|
||||
Result pselShowNicknameEditor(AccountUid *user);
|
||||
Result pselShowUserNicknameEditor(AccountUid user);
|
||||
|
||||
/**
|
||||
* @brief Shows the applet to create a user. Used by the starter applet during system setup.
|
||||
*/
|
||||
Result pselShowUserCreatorForStarter(void);
|
||||
|
||||
/**
|
||||
* @brief Shows the applet for Nintendo Account Nnid linking.
|
||||
* @note Only available on [6.0.0+].
|
||||
* @param[in] user Input user ID.
|
||||
*/
|
||||
Result pselShowNintendoAccountNnidLinker(AccountUid user);
|
||||
|
@ -1,35 +1,29 @@
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "result.h"
|
||||
#include "services/applet.h"
|
||||
#include "services/acc.h"
|
||||
#include "applets/libapplet.h"
|
||||
#include "libapplet_internal.h"
|
||||
#include "applets/psel.h"
|
||||
#include "runtime/hosversion.h"
|
||||
|
||||
Result pselUiCreate(PselUiSettings *ui, PselUiMode mode) {
|
||||
memset(ui, 0, sizeof(PselUiSettings));
|
||||
ui->mode = mode;
|
||||
ui->settings.mode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pselUiAddUser(PselUiSettings *ui, AccountUid *user_id) {
|
||||
int i;
|
||||
for(i = 0; i < ACC_USER_LIST_SIZE; i++) {
|
||||
|
||||
if(!accountUidIsValid(&ui->invalidUserList[i])) {
|
||||
__builtin_memcpy(&ui->invalidUserList[i], user_id, sizeof(AccountUid));
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 _pselGetLaVersion() {
|
||||
u32 ver = 0;
|
||||
u32 hosver = hosversionGet();
|
||||
if(hosver >= MAKEHOSVERSION(9,0,0)) {
|
||||
u32 ver = 0x1; // [1.0.0]
|
||||
if (hosversionAtLeast(6,0,0))
|
||||
ver = 0x20000;
|
||||
}
|
||||
else if (hosversionAtLeast(2,0,0))
|
||||
ver = 0x10000;
|
||||
return ver;
|
||||
}
|
||||
|
||||
@ -38,16 +32,21 @@ Result pselUiShow(PselUiSettings *ui, AccountUid *out_user) {
|
||||
LibAppletArgs args;
|
||||
u32 la_ver = _pselGetLaVersion();
|
||||
libappletArgsCreate(&args, la_ver);
|
||||
PselResult res;
|
||||
PselUiReturnArg ret;
|
||||
size_t reply_size;
|
||||
const void* arg_ptr = ui;
|
||||
size_t arg_size = sizeof(*ui);
|
||||
|
||||
rc = libappletLaunch(AppletId_playerSelect, &args, ui, sizeof(PselUiSettings), &res, sizeof(res), &reply_size);
|
||||
if (la_ver == 0x1) { // [1.0.0]
|
||||
arg_ptr = &ui->settings;
|
||||
arg_size = sizeof(ui->settings);
|
||||
}
|
||||
|
||||
rc = libappletLaunch(AppletId_playerSelect, &args, arg_ptr, arg_size, &ret, sizeof(ret), &reply_size);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if (res.result != 0) rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
if(out_user) *out_user = res.userId;
|
||||
}
|
||||
rc = ret.res; // Official sw returns this directly.
|
||||
if (R_SUCCEEDED(rc) && out_user) *out_user = ret.user_id;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -55,25 +54,26 @@ Result pselUiShow(PselUiSettings *ui, AccountUid *out_user) {
|
||||
|
||||
Result pselShowUserSelector(AccountUid *out_user) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_SelectUser);
|
||||
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);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserCreator(AccountUid *out_user) {
|
||||
Result pselShowUserCreator(void) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserCreation);
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserCreator);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = pselUiShow(&ui, out_user);
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowIconEditor(AccountUid *user) {
|
||||
Result pselShowUserIconEditor(AccountUid user) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_IconEditor);
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserIconEditor);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
pselUiAddUser(&ui, user);
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
@ -81,9 +81,31 @@ Result pselShowIconEditor(AccountUid *user) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowNicknameEditor(AccountUid *user) {
|
||||
Result pselShowUserNicknameEditor(AccountUid user) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_NicknameEditor);
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserNicknameEditor);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
pselUiAddUser(&ui, user);
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowUserCreatorForStarter(void) {
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_UserCreatorForStarter);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result pselShowNintendoAccountNnidLinker(AccountUid user) {
|
||||
if (hosversionBefore(6,0,0))
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
|
||||
PselUiSettings ui;
|
||||
Result rc = pselUiCreate(&ui, PselUiMode_NintendoAccountNnidLinker);
|
||||
if(R_SUCCEEDED(rc)) {
|
||||
pselUiAddUser(&ui, user);
|
||||
rc = pselUiShow(&ui, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user