service: am: Improve profile select applet

This commit is contained in:
Narr the Reg 2023-03-28 20:55:06 -06:00 committed by german77
parent 8bdc51b620
commit 668eb5b8da
8 changed files with 270 additions and 34 deletions

View file

@ -11,7 +11,8 @@ ProfileSelectApplet::~ProfileSelectApplet() = default;
void DefaultProfileSelectApplet::Close() const {}
void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback) const {
void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback,
const ProfileSelectParameters& parameters) const {
Service::Account::ProfileManager manager;
callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{}));
LOG_INFO(Service_ACC, "called, selecting current user instead of prompting...");

View file

@ -5,25 +5,35 @@
#include <functional>
#include <optional>
#include "common/uuid.h"
#include "common/uuid.h"
#include "core/frontend/applets/applet.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
namespace Core::Frontend {
struct ProfileSelectParameters {
Service::AM::Applets::UiMode mode;
std::array<Common::UUID, 8> invalid_uid_list;
Service::AM::Applets::UiSettingsDisplayOptions display_options;
Service::AM::Applets::UserSelectionPurpose purpose;
};
class ProfileSelectApplet : public Applet {
public:
using SelectProfileCallback = std::function<void(std::optional<Common::UUID>)>;
virtual ~ProfileSelectApplet();
virtual void SelectProfile(SelectProfileCallback callback) const = 0;
virtual void SelectProfile(SelectProfileCallback callback,
const ProfileSelectParameters& parameters) const = 0;
};
class DefaultProfileSelectApplet final : public ProfileSelectApplet {
public:
void Close() const override;
void SelectProfile(SelectProfileCallback callback) const override;
void SelectProfile(SelectProfileCallback callback,
const ProfileSelectParameters& parameters) const override;
};
} // namespace Core::Frontend

View file

@ -25,13 +25,29 @@ void ProfileSelect::Initialize() {
final_data.clear();
Applet::Initialize();
profile_select_version = ProfileSelectAppletVersion{common_args.library_version};
const auto user_config_storage = broker.PopNormalDataToApplet();
ASSERT(user_config_storage != nullptr);
const auto& user_config = user_config_storage->GetData();
ASSERT(user_config.size() >= sizeof(UserSelectionConfig));
std::memcpy(&config, user_config.data(), sizeof(UserSelectionConfig));
LOG_INFO(Service_AM, "Initializing Profile Select Applet with version={}",
profile_select_version);
switch (profile_select_version) {
case ProfileSelectAppletVersion::Version1:
ASSERT(user_config.size() == sizeof(UiSettingsV1));
std::memcpy(&config_old, user_config.data(), sizeof(UiSettingsV1));
break;
case ProfileSelectAppletVersion::Version2:
case ProfileSelectAppletVersion::Version3:
ASSERT(user_config.size() == sizeof(UiSettings));
std::memcpy(&config, user_config.data(), sizeof(UiSettings));
break;
default:
UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version);
break;
}
}
bool ProfileSelect::TransactionComplete() const {
@ -52,11 +68,37 @@ void ProfileSelect::Execute() {
return;
}
frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); });
Core::Frontend::ProfileSelectParameters parameters{};
switch (profile_select_version) {
case ProfileSelectAppletVersion::Version1:
parameters = {
.mode = config_old.mode,
.invalid_uid_list = config_old.invalid_uid_list,
.display_options = config_old.display_options,
.purpose = UserSelectionPurpose::General,
};
break;
case ProfileSelectAppletVersion::Version2:
case ProfileSelectAppletVersion::Version3:
parameters = {
.mode = config.mode,
.invalid_uid_list = config.invalid_uid_list,
.display_options = config.display_options,
.purpose = config.purpose,
};
break;
default:
UNIMPLEMENTED_MSG("Unknown profile_select_version = {}", profile_select_version);
break;
}
frontend.SelectProfile([this](std::optional<Common::UUID> uuid) { SelectionComplete(uuid); },
parameters);
}
void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
UserSelectionOutput output{};
UiReturnArg output{};
if (uuid.has_value() && uuid->IsValid()) {
output.result = 0;
@ -67,7 +109,7 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) {
output.uuid_selected = Common::InvalidUUID;
}
final_data = std::vector<u8>(sizeof(UserSelectionOutput));
final_data = std::vector<u8>(sizeof(UiReturnArg));
std::memcpy(final_data.data(), &output, final_data.size());
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
broker.SignalStateChanged();

View file

@ -16,19 +16,100 @@ class System;
namespace Service::AM::Applets {
struct UserSelectionConfig {
// TODO(DarkLordZach): RE this structure
// It seems to be flags and the like that determine the UI of the applet on the switch... from
// my research this is safe to ignore for now.
INSERT_PADDING_BYTES(0xA0);
enum class ProfileSelectAppletVersion : u32 {
Version1 = 0x1, // 1.0.0+
Version2 = 0x10000, // 2.0.0+
Version3 = 0x20000, // 6.0.0+
};
static_assert(sizeof(UserSelectionConfig) == 0xA0, "UserSelectionConfig has incorrect size.");
struct UserSelectionOutput {
// This is nn::account::UiMode
enum class UiMode {
UserSelector,
UserCreator,
EnsureNetworkServiceAccountAvailable,
UserIconEditor,
UserNicknameEditor,
UserCreatorForStarter,
NintendoAccountAuthorizationRequestContext,
IntroduceExternalNetworkServiceAccount,
IntroduceExternalNetworkServiceAccountForRegistration,
NintendoAccountNnidLinker,
LicenseRequirementsForNetworkService,
LicenseRequirementsForNetworkServiceWithUserContextImpl,
UserCreatorForImmediateNaLoginTest,
UserQualificationPromoter,
};
// This is nn::account::UserSelectionPurpose
enum class UserSelectionPurpose {
General,
GameCardRegistration,
EShopLaunch,
EShopItemShow,
PicturePost,
NintendoAccountLinkage,
SettingsUpdate,
SaveDataDeletion,
UserMigration,
SaveDataTransfer,
};
// This is nn::account::NintendoAccountStartupDialogType
enum class NintendoAccountStartupDialogType {
LoginAndCreate,
Login,
Create,
};
// This is nn::account::UserSelectionSettingsForSystemService
struct UserSelectionSettingsForSystemService {
UserSelectionPurpose purpose;
bool enable_user_creation;
INSERT_PADDING_BYTES(0x3);
};
static_assert(sizeof(UserSelectionSettingsForSystemService) == 0x8,
"UserSelectionSettingsForSystemService has incorrect size.");
struct UiSettingsDisplayOptions {
bool is_network_service_account_required;
bool is_skip_enabled;
bool is_system_or_launcher;
bool is_registration_permitted;
bool show_skip_button;
bool aditional_select;
bool show_user_selector;
bool is_unqualified_user_selectable;
};
static_assert(sizeof(UiSettingsDisplayOptions) == 0x8,
"UiSettingsDisplayOptions has incorrect size.");
struct UiSettingsV1 {
UiMode mode;
INSERT_PADDING_BYTES(0x4);
std::array<Common::UUID, 8> invalid_uid_list;
u64 application_id;
UiSettingsDisplayOptions display_options;
};
static_assert(sizeof(UiSettingsV1) == 0x98, "UiSettings has incorrect size.");
// This is nn::account::UiSettings
struct UiSettings {
UiMode mode;
INSERT_PADDING_BYTES(0x4);
std::array<Common::UUID, 8> invalid_uid_list;
u64 application_id;
UiSettingsDisplayOptions display_options;
UserSelectionPurpose purpose;
INSERT_PADDING_BYTES(0x4);
};
static_assert(sizeof(UiSettings) == 0xA0, "UiSettings has incorrect size.");
// This is nn::account::UiReturnArg
struct UiReturnArg {
u64 result;
Common::UUID uuid_selected;
};
static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has incorrect size.");
static_assert(sizeof(UiReturnArg) == 0x18, "UiReturnArg has incorrect size.");
class ProfileSelect final : public Applet {
public:
@ -49,7 +130,10 @@ public:
private:
const Core::Frontend::ProfileSelectApplet& frontend;
UserSelectionConfig config;
UiSettings config;
UiSettingsV1 config_old;
ProfileSelectAppletVersion profile_select_version;
bool complete = false;
Result status = ResultSuccess;
std::vector<u8> final_data;