summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar David Marcec2018-08-08 22:26:42 +1000
committerGravatar David Marcec2018-08-08 22:26:42 +1000
commit6f691e71bfa30de8789327a969cb7c2fdd1669f2 (patch)
treec48798f2d3fdde5b0ff5ab2dc6d2a4f6fdc9b5c8 /src/core
parentSwitched uuids from u128 to new UUID struct (diff)
downloadyuzu-6f691e71bfa30de8789327a969cb7c2fdd1669f2.tar.gz
yuzu-6f691e71bfa30de8789327a969cb7c2fdd1669f2.tar.xz
yuzu-6f691e71bfa30de8789327a969cb7c2fdd1669f2.zip
began initial implementation of "ProfileManager"
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/acc/acc.cpp17
-rw-r--r--src/core/hle/service/acc/acc.h41
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp89
-rw-r--r--src/core/hle/service/acc/profile_manager.h97
5 files changed, 202 insertions, 44 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index cceb1564b..4d39ba409 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -114,6 +114,8 @@ add_library(core STATIC
114 hle/service/acc/acc_u0.h 114 hle/service/acc/acc_u0.h
115 hle/service/acc/acc_u1.cpp 115 hle/service/acc/acc_u1.cpp
116 hle/service/acc/acc_u1.h 116 hle/service/acc/acc_u1.h
117 hle/service/acc/profile_manager.cpp
118 hle/service/acc/profile_manager.h
117 hle/service/am/am.cpp 119 hle/service/am/am.cpp
118 hle/service/am/am.h 120 hle/service/am/am.h
119 hle/service/am/applet_ae.cpp 121 hle/service/am/applet_ae.cpp
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 1fb3d96f6..8efaf6171 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -28,7 +28,7 @@ struct UserData {
28static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size"); 28static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
29 29
30struct ProfileBase { 30struct ProfileBase {
31 u128 user_id; 31 UUID user_id;
32 u64 timestamp; 32 u64 timestamp;
33 std::array<u8, 0x20> username; 33 std::array<u8, 0x20> username;
34}; 34};
@@ -53,7 +53,7 @@ private:
53 void Get(Kernel::HLERequestContext& ctx) { 53 void Get(Kernel::HLERequestContext& ctx) {
54 LOG_WARNING(Service_ACC, "(STUBBED) called"); 54 LOG_WARNING(Service_ACC, "(STUBBED) called");
55 ProfileBase profile_base{}; 55 ProfileBase profile_base{};
56 profile_base.user_id = user_id.uuid; 56 profile_base.user_id = user_id;
57 if (Settings::values.username.size() > profile_base.username.size()) { 57 if (Settings::values.username.size() > profile_base.username.size()) {
58 std::copy_n(Settings::values.username.begin(), profile_base.username.size(), 58 std::copy_n(Settings::values.username.begin(), profile_base.username.size(),
59 profile_base.username.begin()); 59 profile_base.username.begin());
@@ -72,7 +72,7 @@ private:
72 72
73 // TODO(Subv): Retrieve this information from somewhere. 73 // TODO(Subv): Retrieve this information from somewhere.
74 ProfileBase profile_base{}; 74 ProfileBase profile_base{};
75 profile_base.user_id = user_id.uuid; 75 profile_base.user_id = user_id;
76 if (Settings::values.username.size() > profile_base.username.size()) { 76 if (Settings::values.username.size() > profile_base.username.size()) {
77 std::copy_n(Settings::values.username.begin(), profile_base.username.size(), 77 std::copy_n(Settings::values.username.begin(), profile_base.username.size(),
78 profile_base.username.begin()); 78 profile_base.username.begin());
@@ -122,17 +122,20 @@ private:
122}; 122};
123 123
124void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { 124void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
125 LOG_WARNING(Service_ACC, "(STUBBED) called"); 125 LOG_INFO(Service_ACC, "called");
126 IPC::ResponseBuilder rb{ctx, 3}; 126 IPC::ResponseBuilder rb{ctx, 3};
127 rb.Push(RESULT_SUCCESS); 127 rb.Push(RESULT_SUCCESS);
128 rb.Push<u32>(1); 128 rb.Push<u32>(static_cast<u32>(profile_manager->GetUserCount()));
129} 129}
130 130
131void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { 131void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
132 LOG_WARNING(Service_ACC, "(STUBBED) called"); 132 IPC::RequestParser rp{ctx};
133 UUID user_id = rp.PopRaw<UUID>();
134 LOG_INFO(Service_ACC, "called user_id={}", user_id.Format());
135
133 IPC::ResponseBuilder rb{ctx, 3}; 136 IPC::ResponseBuilder rb{ctx, 3};
134 rb.Push(RESULT_SUCCESS); 137 rb.Push(RESULT_SUCCESS);
135 rb.Push(true); // TODO: Check when this is supposed to return true and when not 138 rb.Push(profile_manager->UserExists(user_id));
136} 139}
137 140
138void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { 141void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index e392b3557..a9bea77ce 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -5,46 +5,10 @@
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8#include "profile_manager.h"
8 9
9namespace Service::Account { 10namespace Service::Account {
10 11
11struct UUID {
12 // UUIDs which are 0 are considered invalid!
13 u128 uuid{0, 0};
14 UUID() = default;
15 explicit UUID(const u128& id) {
16 uuid[0] = id[0];
17 uuid[1] = id[1];
18 };
19 explicit UUID(const u64& lo, const u64& hi) {
20 uuid[0] = lo;
21 uuid[1] = hi;
22 };
23 operator bool() const {
24 return uuid[0] != 0x0 && uuid[1] != 0x0;
25 }
26
27 bool operator==(const UUID& rhs) {
28 return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
29 }
30
31 bool operator!=(const UUID& rhs) {
32 return uuid[0] != rhs.uuid[0] || uuid[1] != rhs.uuid[1];
33 }
34
35 // TODO(ogniK): Properly generate uuids based on RFC-4122
36 const UUID& Generate() {
37 uuid[0] = (static_cast<u64>(std::rand()) << 32) | std::rand();
38 uuid[1] = (static_cast<u64>(std::rand()) << 32) | std::rand();
39 return *this;
40 }
41
42 std::string Format() {
43 return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]);
44 }
45};
46static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
47
48class Module final { 12class Module final {
49public: 13public:
50 class Interface : public ServiceFramework<Interface> { 14 class Interface : public ServiceFramework<Interface> {
@@ -60,6 +24,9 @@ public:
60 void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); 24 void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
61 void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); 25 void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx);
62 26
27 private:
28 std::unique_ptr<ProfileManager> profile_manager{};
29
63 protected: 30 protected:
64 std::shared_ptr<Module> module; 31 std::shared_ptr<Module> module;
65 }; 32 };
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
new file mode 100644
index 000000000..8819c5703
--- /dev/null
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -0,0 +1,89 @@
1#include "profile_manager.h"
2
3namespace Service::Account {
4// TODO(ogniK): Get actual error codes
5constexpr ResultCode ERROR_TOO_MANY_USERS(ErrorModule::Account, -1);
6constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20);
7
8size_t ProfileManager::AddToProfiles(const ProfileInfo& user) {
9 if (user_count >= MAX_USERS) {
10 return -1;
11 }
12 profiles[user_count] = std::move(user);
13 return user_count++;
14}
15
16bool ProfileManager::RemoveProfileAtIdx(size_t index) {
17 if (index >= MAX_USERS || index < 0 || index >= user_count)
18 return false;
19 profiles[index] = ProfileInfo{};
20 if (index < user_count - 1)
21 for (size_t i = index; i < user_count - 1; i++)
22 profiles[i] = profiles[i + 1]; // Shift upper profiles down
23 user_count--;
24 return true;
25}
26
27ResultCode ProfileManager::AddUser(ProfileInfo user) {
28 if (AddToProfiles(user) == -1) {
29 return ERROR_TOO_MANY_USERS;
30 }
31 return RESULT_SUCCESS;
32}
33
34ResultCode ProfileManager::CreateNewUser(UUID uuid, std::array<u8, 0x20> username) {
35 if (user_count == MAX_USERS)
36 return ERROR_TOO_MANY_USERS;
37 if (!uuid)
38 return ERROR_ARGUMENT_IS_NULL;
39 if (username[0] == 0x0)
40 return ERROR_ARGUMENT_IS_NULL;
41 ProfileInfo prof_inf;
42 prof_inf.user_uuid = uuid;
43 prof_inf.username = username;
44 prof_inf.data = std::array<u8, MAX_DATA>();
45 prof_inf.creation_time = 0x0;
46 return AddUser(prof_inf);
47}
48
49size_t ProfileManager::GetUserIndex(UUID uuid) {
50 for (unsigned i = 0; i < user_count; i++)
51 if (profiles[i].user_uuid == uuid)
52 return i;
53 return -1;
54}
55
56size_t ProfileManager::GetUserIndex(ProfileInfo user) {
57 return GetUserIndex(user.user_uuid);
58}
59
60bool ProfileManager::GetProfileBase(size_t index, ProfileBase& profile) {
61 if (index >= MAX_USERS) {
62 profile.Invalidate();
63 return false;
64 }
65 auto prof_info = profiles[index];
66 profile.user_uuid = prof_info.user_uuid;
67 profile.username = prof_info.username;
68 profile.timestamp = prof_info.creation_time;
69 return true;
70}
71
72bool ProfileManager::GetProfileBase(UUID uuid, ProfileBase& profile) {
73 auto idx = GetUserIndex(uuid);
74 return GetProfileBase(idx, profile);
75}
76
77bool ProfileManager::GetProfileBase(ProfileInfo user, ProfileBase& profile) {
78 return GetProfileBase(user.user_uuid, profile);
79}
80
81size_t ProfileManager::GetUserCount() {
82 return user_count;
83}
84
85bool ProfileManager::UserExists(UUID uuid) {
86 return (GetUserIndex(uuid) != -1);
87}
88
89}; // namespace Service::Account
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
new file mode 100644
index 000000000..5aa73a030
--- /dev/null
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -0,0 +1,97 @@
1#pragma once
2#include <array>
3#include "common/common_types.h"
4#include "common/swap.h"
5#include "core/hle/result.h"
6
7namespace Service::Account {
8constexpr size_t MAX_USERS = 8;
9constexpr size_t MAX_DATA = 128;
10
11struct UUID {
12 // UUIDs which are 0 are considered invalid!
13 u128 uuid{0, 0};
14 UUID() = default;
15 explicit UUID(const u128& id) {
16 uuid[0] = id[0];
17 uuid[1] = id[1];
18 };
19 explicit UUID(const u64& lo, const u64& hi) {
20 uuid[0] = lo;
21 uuid[1] = hi;
22 };
23 operator bool() const {
24 return uuid[0] != 0x0 && uuid[1] != 0x0;
25 }
26
27 bool operator==(const UUID& rhs) {
28 return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1];
29 }
30
31 bool operator!=(const UUID& rhs) {
32 return uuid[0] != rhs.uuid[0] || uuid[1] != rhs.uuid[1];
33 }
34
35 // TODO(ogniK): Properly generate uuids based on RFC-4122
36 const UUID& Generate() {
37 uuid[0] = (static_cast<u64>(std::rand()) << 32) | std::rand();
38 uuid[1] = (static_cast<u64>(std::rand()) << 32) | std::rand();
39 return *this;
40 }
41 void Invalidate() {
42 uuid[0] = 0;
43 uuid[1] = 0;
44 }
45 std::string Format() {
46 return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]);
47 }
48};
49static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
50
51/// This holds general information about a users profile. This is where we store all the information
52/// based on a specific user
53struct ProfileInfo {
54 UUID user_uuid;
55 std::array<u8, 0x20> username;
56 u64 creation_time;
57 std::array<u8, MAX_DATA> data;
58};
59
60struct ProfileBase {
61 UUID user_uuid;
62 u64_le timestamp;
63 std::array<u8, 0x20> username;
64
65 const void Invalidate() {
66 user_uuid.Invalidate();
67 timestamp = 0;
68 username.fill(0);
69 }
70};
71static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase is an invalid size");
72
73/// The profile manager is used for handling multiple user profiles at once. It keeps track of open
74/// users, all the accounts registered on the "system" as well as fetching individual "ProfileInfo"
75/// objects
76class ProfileManager {
77public:
78 ProfileManager() = default; // TODO(ogniK): Load from system save
79 ResultCode AddUser(ProfileInfo user);
80 ResultCode CreateNewUser(UUID uuid, std::array<u8, 0x20> username);
81 size_t GetUserIndex(UUID uuid);
82 size_t GetUserIndex(ProfileInfo user);
83 bool GetProfileBase(size_t index, ProfileBase& profile);
84 bool GetProfileBase(UUID uuid, ProfileBase& profile);
85 bool GetProfileBase(ProfileInfo user, ProfileBase& profile);
86 size_t GetUserCount();
87 bool UserExists(UUID uuid);
88
89private:
90 std::array<ProfileInfo, MAX_USERS> profiles{};
91 size_t user_count = 0;
92 size_t AddToProfiles(const ProfileInfo& profile);
93 bool RemoveProfileAtIdx(size_t index);
94};
95using ProfileManagerPtr = std::unique_ptr<ProfileManager>;
96
97}; // namespace Service::Account