/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2024 Xenia Canary. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_KERNEL_XAM_PROFILE_MANAGER_H_ #define XENIA_KERNEL_XAM_PROFILE_MANAGER_H_ #include #include #include #include #include "third_party/fmt/include/fmt/format.h" #include "xenia/base/string.h" #include "xenia/kernel/title_id_utils.h" #include "xenia/kernel/xam/user_profile.h" #include "xenia/xbox.h" namespace xe { namespace kernel { class KernelState; } // namespace kernel } // namespace xe namespace xe { namespace kernel { namespace xam { class UserTracker; } // namespace xam } // namespace kernel } // namespace xe namespace xe { namespace kernel { namespace xam { inline const std::string kDashboardStringID = fmt::format("{:08X}", kDashboardID); constexpr std::string_view kDefaultMountFormat = "User_{:016X}"; const static inline uint64_t GenerateXuid() { std::random_device rd; std::mt19937 gen(rd()); return ((uint64_t)0xE03 << 52) + (gen() % (1 << 31)); } class ProfileManager { public: static bool DecryptAccountFile(const uint8_t* data, X_XAMACCOUNTINFO* output, bool devkit = false); static void EncryptAccountFile(const X_XAMACCOUNTINFO* input, uint8_t* output, bool devkit = false); // Profile: // - Account // - GPDs (Dashboard, titles) // Loading Profile means load everything // Loading Account means load basic data ProfileManager(KernelState* kernel_state, UserTracker* user_tracker); ~ProfileManager() = default; bool CreateProfile(const std::string gamertag, bool autologin, bool default_xuid = false); bool CreateProfile(const X_XAMACCOUNTINFO* account_info, uint64_t xuid); bool DeleteProfile(const uint64_t xuid); bool MountProfile(const uint64_t xuid, std::string mount_path = ""); bool DismountProfile(const uint64_t xuid); void Login(const uint64_t xuid, const uint8_t user_index = XUserIndexAny, bool notify = true); void Logout(const uint8_t user_index, bool notify = true); void LoginMultiple(const std::map& profiles); bool LoadAccount(const uint64_t xuid); void ReloadProfiles(); void ReloadProfile(const uint64_t xuid); UserProfile* GetProfile(const uint64_t xuid) const; UserProfile* GetProfile(const uint8_t user_index) const; uint8_t GetUserIndexAssignedToProfile(const uint64_t xuid) const; const std::map* GetAccounts() { return &accounts_; } const X_XAMACCOUNTINFO* GetAccount(const uint64_t xuid); uint32_t GetAccountCount() const { return static_cast(accounts_.size()); } bool IsAnyProfileSignedIn() const { return !logged_profiles_.empty(); } std::filesystem::path GetProfileContentPath( const uint64_t xuid, const uint32_t title_id = -1, const XContentType content_type = XContentType::kInvalid) const; bool UpdateAccount(const uint64_t xuid, const X_XAMACCOUNTINFO* account); static bool IsGamertagValid(const std::string gamertag); private: void UpdateConfig(const uint64_t xuid, const uint8_t slot); bool CreateAccount(const uint64_t xuid, const std::string gamertag); bool CreateAccount(const uint64_t xuid, const X_XAMACCOUNTINFO* account); std::filesystem::path GetProfilePath(const uint64_t xuid) const; std::filesystem::path GetProfilePath(const std::string xuid) const; std::vector FindProfiles() const; uint8_t FindFirstFreeProfileSlot() const; std::bitset GetUsedUserSlots() const; std::map accounts_; std::map> logged_profiles_; KernelState* kernel_state_; UserTracker* user_tracker_; }; } // namespace xam } // namespace kernel } // namespace xe #endif // XENIA_KERNEL_XAM_PROFILE_MANAGER_H_