diff options
Diffstat (limited to 'src/core/hle')
25 files changed, 591 insertions, 137 deletions
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index d09ca5992..51a1ec160 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -152,7 +152,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) { // Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the // end of the command such that only commands following this one are handled as domains if (convert_to_domain) { - ASSERT_MSG(domain_request_handlers.empty(), "already a domain"); + ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); domain_request_handlers = {hle_handler}; convert_to_domain = false; } diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 2bce54fee..1a88e66b9 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -97,7 +97,12 @@ public: /// Returns true if the session has been converted to a domain, otherwise False bool IsDomain() const { - return !domain_request_handlers.empty(); + return !IsSession(); + } + + /// Returns true if this session has not been converted to a domain, otherwise false. + bool IsSession() const { + return domain_request_handlers.empty(); } /// Converts the session to a domain at the end of the current command diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index b24f409b3..6be5c474e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -250,8 +250,11 @@ static ResultCode ArbitrateUnlock(VAddr mutex_addr) { } /// Break program execution -static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { - LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); +static void Break(u64 reason, u64 info1, u64 info2) { + LOG_CRITICAL( + Debug_Emulated, + "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", + reason, info1, info2); ASSERT(false); } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index a1a7867ce..cf4f94822 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -167,7 +167,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { } void Thread::CancelWakeupTimer() { - CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); + CoreTiming::UnscheduleEventThreadsafe(ThreadWakeupEventType, callback_handle); } static boost::optional<s32> GetNextProcessorId(u64 mask) { diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index f3c5b1b9c..979f2f892 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -3,7 +3,10 @@ // Refer to the license.txt file included. #include <array> +#include "common/common_types.h" #include "common/logging/log.h" +#include "common/swap.h" +#include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/acc/acc.h" #include "core/hle/service/acc/acc_aa.h" @@ -13,7 +16,6 @@ #include "core/settings.h" namespace Service::Account { - // TODO: RE this structure struct UserData { INSERT_PADDING_WORDS(1); @@ -25,19 +27,13 @@ struct UserData { }; static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size"); -struct ProfileBase { - u128 user_id; - u64 timestamp; - std::array<u8, 0x20> username; -}; -static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size"); - // TODO(ogniK): Generate a real user id based on username, md5(username) maybe? -static constexpr u128 DEFAULT_USER_ID{1ull, 0ull}; +static UUID DEFAULT_USER_ID{1ull, 0ull}; class IProfile final : public ServiceFramework<IProfile> { public: - explicit IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) { + explicit IProfile(UUID user_id, ProfileManager& profile_manager) + : ServiceFramework("IProfile"), user_id(user_id), profile_manager(profile_manager) { static const FunctionInfo functions[] = { {0, &IProfile::Get, "Get"}, {1, &IProfile::GetBase, "GetBase"}, @@ -49,38 +45,34 @@ public: private: void Get(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); + LOG_INFO(Service_ACC, "called user_id={}", user_id.Format()); ProfileBase profile_base{}; - profile_base.user_id = user_id; - if (Settings::values.username.size() > profile_base.username.size()) { - std::copy_n(Settings::values.username.begin(), profile_base.username.size(), - profile_base.username.begin()); + std::array<u8, MAX_DATA> data{}; + if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) { + ctx.WriteBuffer(data); + IPC::ResponseBuilder rb{ctx, 16}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(profile_base); } else { - std::copy(Settings::values.username.begin(), Settings::values.username.end(), - profile_base.username.begin()); + LOG_ERROR(Service_ACC, "Failed to get profile base and data for user={}", + user_id.Format()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); // TODO(ogniK): Get actual error code } - - IPC::ResponseBuilder rb{ctx, 16}; - rb.Push(RESULT_SUCCESS); - rb.PushRaw(profile_base); } void GetBase(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - - // TODO(Subv): Retrieve this information from somewhere. + LOG_INFO(Service_ACC, "called user_id={}", user_id.Format()); ProfileBase profile_base{}; - profile_base.user_id = user_id; - if (Settings::values.username.size() > profile_base.username.size()) { - std::copy_n(Settings::values.username.begin(), profile_base.username.size(), - profile_base.username.begin()); + if (profile_manager.GetProfileBase(user_id, profile_base)) { + IPC::ResponseBuilder rb{ctx, 16}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(profile_base); } else { - std::copy(Settings::values.username.begin(), Settings::values.username.end(), - profile_base.username.begin()); + LOG_ERROR(Service_ACC, "Failed to get profile base for user={}", user_id.Format()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(-1)); // TODO(ogniK): Get actual error code } - IPC::ResponseBuilder rb{ctx, 16}; - rb.Push(RESULT_SUCCESS); - rb.PushRaw(profile_base); } void LoadImage(Kernel::HLERequestContext& ctx) { @@ -104,7 +96,8 @@ private: rb.Push<u32>(jpeg_size); } - u128 user_id; ///< The user id this profile refers to. + const ProfileManager& profile_manager; + UUID user_id; ///< The user id this profile refers to. }; class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { @@ -141,44 +134,57 @@ private: }; void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); + LOG_INFO(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(1); + rb.Push<u32>(static_cast<u32>(profile_manager->GetUserCount())); } void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + UUID user_id = rp.PopRaw<UUID>(); + LOG_INFO(Service_ACC, "called user_id={}", user_id.Format()); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(true); // TODO: Check when this is supposed to return true and when not + rb.Push(profile_manager->UserExists(user_id)); } void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - // TODO(Subv): There is only one user for now. - const std::vector<u128> user_ids = {DEFAULT_USER_ID}; - ctx.WriteBuffer(user_ids); + LOG_INFO(Service_ACC, "called"); + ctx.WriteBuffer(profile_manager->GetAllUsers()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - // TODO(Subv): There is only one user for now. - const std::vector<u128> user_ids = {DEFAULT_USER_ID}; - ctx.WriteBuffer(user_ids); + LOG_INFO(Service_ACC, "called"); + ctx.WriteBuffer(profile_manager->GetOpenUsers()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } +void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { + LOG_INFO(Service_ACC, "called"); + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<UUID>(profile_manager->GetLastOpenedUser()); +} + void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u128 user_id = rp.PopRaw<u128>(); + UUID user_id = rp.PopRaw<UUID>(); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IProfile>(user_id); - LOG_DEBUG(Service_ACC, "called user_id=0x{:016X}{:016X}", user_id[1], user_id[0]); + rb.PushIpcInterface<IProfile>(user_id, *profile_manager); + LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); +} + +void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(profile_manager->CanSystemRegisterUser()); } void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { @@ -194,22 +200,18 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo LOG_DEBUG(Service_ACC, "called"); } -void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 6}; - rb.Push(RESULT_SUCCESS); - rb.PushRaw(DEFAULT_USER_ID); -} - -Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) - : ServiceFramework(name), module(std::move(module)) {} +Module::Interface::Interface(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager, const char* name) + : ServiceFramework(name), module(std::move(module)), + profile_manager(std::move(profile_manager)) {} void InstallInterfaces(SM::ServiceManager& service_manager) { auto module = std::make_shared<Module>(); - std::make_shared<ACC_AA>(module)->InstallAsService(service_manager); - std::make_shared<ACC_SU>(module)->InstallAsService(service_manager); - std::make_shared<ACC_U0>(module)->InstallAsService(service_manager); - std::make_shared<ACC_U1>(module)->InstallAsService(service_manager); + auto profile_manager = std::make_shared<ProfileManager>(); + std::make_shared<ACC_AA>(module, profile_manager)->InstallAsService(service_manager); + std::make_shared<ACC_SU>(module, profile_manager)->InstallAsService(service_manager); + std::make_shared<ACC_U0>(module, profile_manager)->InstallAsService(service_manager); + std::make_shared<ACC_U1>(module, profile_manager)->InstallAsService(service_manager); } } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index 88cabaa01..d7c6d2415 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -4,6 +4,7 @@ #pragma once +#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/service.h" namespace Service::Account { @@ -12,7 +13,8 @@ class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, const char* name); + explicit Interface(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager, const char* name); void GetUserCount(Kernel::HLERequestContext& ctx); void GetUserExistence(Kernel::HLERequestContext& ctx); @@ -22,9 +24,11 @@ public: void GetProfile(Kernel::HLERequestContext& ctx); void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); + void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); protected: std::shared_ptr<Module> module; + std::shared_ptr<ProfileManager> profile_manager; }; }; diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp index 280b3e464..9bd595a37 100644 --- a/src/core/hle/service/acc/acc_aa.cpp +++ b/src/core/hle/service/acc/acc_aa.cpp @@ -6,7 +6,8 @@ namespace Service::Account { -ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") { +ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) + : Module::Interface(std::move(module), std::move(profile_manager), "acc:aa") { static const FunctionInfo functions[] = { {0, nullptr, "EnsureCacheAsync"}, {1, nullptr, "LoadCache"}, diff --git a/src/core/hle/service/acc/acc_aa.h b/src/core/hle/service/acc/acc_aa.h index 796f7ef85..2e08c781a 100644 --- a/src/core/hle/service/acc/acc_aa.h +++ b/src/core/hle/service/acc/acc_aa.h @@ -10,7 +10,8 @@ namespace Service::Account { class ACC_AA final : public Module::Interface { public: - explicit ACC_AA(std::shared_ptr<Module> module); + explicit ACC_AA(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager); }; } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index 8b2a71f37..0218ee859 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp @@ -6,7 +6,8 @@ namespace Service::Account { -ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") { +ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) + : Module::Interface(std::move(module), std::move(profile_manager), "acc:su") { static const FunctionInfo functions[] = { {0, &ACC_SU::GetUserCount, "GetUserCount"}, {1, &ACC_SU::GetUserExistence, "GetUserExistence"}, @@ -15,7 +16,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(mod {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, {5, &ACC_SU::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, - {50, nullptr, "IsUserRegistrationRequestPermitted"}, + {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, {51, nullptr, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, nullptr, "GetUserRegistrationNotifier"}, diff --git a/src/core/hle/service/acc/acc_su.h b/src/core/hle/service/acc/acc_su.h index 3894a6991..79a47d88d 100644 --- a/src/core/hle/service/acc/acc_su.h +++ b/src/core/hle/service/acc/acc_su.h @@ -11,7 +11,8 @@ namespace Account { class ACC_SU final : public Module::Interface { public: - explicit ACC_SU(std::shared_ptr<Module> module); + explicit ACC_SU(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager); }; } // namespace Account diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index d84c8b2e1..84a4d05b8 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -6,7 +6,8 @@ namespace Service::Account { -ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") { +ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) + : Module::Interface(std::move(module), std::move(profile_manager), "acc:u0") { static const FunctionInfo functions[] = { {0, &ACC_U0::GetUserCount, "GetUserCount"}, {1, &ACC_U0::GetUserExistence, "GetUserExistence"}, @@ -15,7 +16,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(mod {4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"}, {5, &ACC_U0::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, - {50, nullptr, "IsUserRegistrationRequestPermitted"}, + {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, {51, nullptr, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h index 6ded596b3..e8a114f99 100644 --- a/src/core/hle/service/acc/acc_u0.h +++ b/src/core/hle/service/acc/acc_u0.h @@ -10,7 +10,8 @@ namespace Service::Account { class ACC_U0 final : public Module::Interface { public: - explicit ACC_U0(std::shared_ptr<Module> module); + explicit ACC_U0(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager); }; } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 0ceaf06b5..495693949 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp @@ -6,7 +6,8 @@ namespace Service::Account { -ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") { +ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) + : Module::Interface(std::move(module), std::move(profile_manager), "acc:u1") { static const FunctionInfo functions[] = { {0, &ACC_U1::GetUserCount, "GetUserCount"}, {1, &ACC_U1::GetUserExistence, "GetUserExistence"}, @@ -15,7 +16,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(mod {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, {5, &ACC_U1::GetProfile, "GetProfile"}, {6, nullptr, "GetProfileDigest"}, - {50, nullptr, "IsUserRegistrationRequestPermitted"}, + {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, {51, nullptr, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {100, nullptr, "GetUserRegistrationNotifier"}, diff --git a/src/core/hle/service/acc/acc_u1.h b/src/core/hle/service/acc/acc_u1.h index 5e3e7659b..a77520e6f 100644 --- a/src/core/hle/service/acc/acc_u1.h +++ b/src/core/hle/service/acc/acc_u1.h @@ -10,7 +10,8 @@ namespace Service::Account { class ACC_U1 final : public Module::Interface { public: - explicit ACC_U1(std::shared_ptr<Module> module); + explicit ACC_U1(std::shared_ptr<Module> module, + std::shared_ptr<ProfileManager> profile_manager); }; } // namespace Service::Account 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..62c2121fa --- /dev/null +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -0,0 +1,226 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <boost/optional.hpp> +#include "core/hle/service/acc/profile_manager.h" +#include "core/settings.h" + +namespace Service::Account { +// TODO(ogniK): Get actual error codes +constexpr ResultCode ERROR_TOO_MANY_USERS(ErrorModule::Account, -1); +constexpr ResultCode ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, -2); +constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20); + +ProfileManager::ProfileManager() { + // TODO(ogniK): Create the default user we have for now until loading/saving users is added + auto user_uuid = UUID{1, 0}; + CreateNewUser(user_uuid, Settings::values.username); + OpenUser(user_uuid); +} + +/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the +/// internal management of the users profiles +boost::optional<size_t> ProfileManager::AddToProfiles(const ProfileInfo& user) { + if (user_count >= MAX_USERS) { + return boost::none; + } + profiles[user_count] = std::move(user); + return user_count++; +} + +/// Deletes a specific profile based on it's profile index +bool ProfileManager::RemoveProfileAtIndex(size_t index) { + if (index >= MAX_USERS || index >= user_count) { + return false; + } + if (index < user_count - 1) { + std::rotate(profiles.begin() + index, profiles.begin() + index + 1, profiles.end()); + } + profiles.back() = {}; + user_count--; + return true; +} + +/// Helper function to register a user to the system +ResultCode ProfileManager::AddUser(ProfileInfo user) { + if (AddToProfiles(user) == boost::none) { + return ERROR_TOO_MANY_USERS; + } + return RESULT_SUCCESS; +} + +/// Create a new user on the system. If the uuid of the user already exists, the user is not +/// created. +ResultCode ProfileManager::CreateNewUser(UUID uuid, std::array<u8, 0x20>& username) { + if (user_count == MAX_USERS) { + return ERROR_TOO_MANY_USERS; + } + if (!uuid) { + return ERROR_ARGUMENT_IS_NULL; + } + if (username[0] == 0x0) { + return ERROR_ARGUMENT_IS_NULL; + } + if (std::any_of(profiles.begin(), profiles.end(), + [&uuid](const ProfileInfo& profile) { return uuid == profile.user_uuid; })) { + return ERROR_USER_ALREADY_EXISTS; + } + ProfileInfo profile; + profile.user_uuid = std::move(uuid); + profile.username = username; + profile.data = {}; + profile.creation_time = 0x0; + profile.is_open = false; + return AddUser(profile); +} + +/// Creates a new user on the system. This function allows a much simpler method of registration +/// specifically by allowing an std::string for the username. This is required specifically since +/// we're loading a string straight from the config +ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) { + std::array<u8, 0x20> username_output; + if (username.size() > username_output.size()) { + std::copy_n(username.begin(), username_output.size(), username_output.begin()); + } else { + std::copy(username.begin(), username.end(), username_output.begin()); + } + return CreateNewUser(uuid, username_output); +} + +/// Returns a users profile index based on their user id. +boost::optional<size_t> ProfileManager::GetUserIndex(const UUID& uuid) const { + if (!uuid) { + return boost::none; + } + auto iter = std::find_if(profiles.begin(), profiles.end(), + [&uuid](const ProfileInfo& p) { return p.user_uuid == uuid; }); + if (iter == profiles.end()) { + return boost::none; + } + return static_cast<size_t>(std::distance(profiles.begin(), iter)); +} + +/// Returns a users profile index based on their profile +boost::optional<size_t> ProfileManager::GetUserIndex(ProfileInfo user) const { + return GetUserIndex(user.user_uuid); +} + +/// Returns the data structure used by the switch when GetProfileBase is called on acc:* +bool ProfileManager::GetProfileBase(boost::optional<size_t> index, ProfileBase& profile) const { + if (index == boost::none || index >= MAX_USERS) { + return false; + } + const auto& prof_info = profiles[index.get()]; + profile.user_uuid = prof_info.user_uuid; + profile.username = prof_info.username; + profile.timestamp = prof_info.creation_time; + return true; +} + +/// Returns the data structure used by the switch when GetProfileBase is called on acc:* +bool ProfileManager::GetProfileBase(UUID uuid, ProfileBase& profile) const { + auto idx = GetUserIndex(uuid); + return GetProfileBase(idx, profile); +} + +/// Returns the data structure used by the switch when GetProfileBase is called on acc:* +bool ProfileManager::GetProfileBase(ProfileInfo user, ProfileBase& profile) const { + return GetProfileBase(user.user_uuid, profile); +} + +/// Returns the current user count on the system. We keep a variable which tracks the count so we +/// don't have to loop the internal profile array every call. +size_t ProfileManager::GetUserCount() const { + return user_count; +} + +/// Lists the current "opened" users on the system. Users are typically not open until they sign +/// into something or pick a profile. As of right now users should all be open until qlaunch is +/// booting +size_t ProfileManager::GetOpenUserCount() const { + return std::count_if(profiles.begin(), profiles.end(), + [](const ProfileInfo& p) { return p.is_open; }); +} + +/// Checks if a user id exists in our profile manager +bool ProfileManager::UserExists(UUID uuid) const { + return (GetUserIndex(uuid) != boost::none); +} + +/// Opens a specific user +void ProfileManager::OpenUser(UUID uuid) { + auto idx = GetUserIndex(uuid); + if (idx == boost::none) { + return; + } + profiles[idx.get()].is_open = true; + last_opened_user = uuid; +} + +/// Closes a specific user +void ProfileManager::CloseUser(UUID uuid) { + auto idx = GetUserIndex(uuid); + if (idx == boost::none) { + return; + } + profiles[idx.get()].is_open = false; +} + +/// Gets all valid user ids on the system +std::array<UUID, MAX_USERS> ProfileManager::GetAllUsers() const { + std::array<UUID, MAX_USERS> output; + std::transform(profiles.begin(), profiles.end(), output.begin(), + [](const ProfileInfo& p) { return p.user_uuid; }); + return output; +} + +/// Get all the open users on the system and zero out the rest of the data. This is specifically +/// needed for GetOpenUsers and we need to ensure the rest of the output buffer is zero'd out +std::array<UUID, MAX_USERS> ProfileManager::GetOpenUsers() const { + std::array<UUID, MAX_USERS> output; + std::transform(profiles.begin(), profiles.end(), output.begin(), [](const ProfileInfo& p) { + if (p.is_open) + return p.user_uuid; + return UUID{}; + }); + std::stable_partition(output.begin(), output.end(), [](const UUID& uuid) { return uuid; }); + return output; +} + +/// Returns the last user which was opened +UUID ProfileManager::GetLastOpenedUser() const { + return last_opened_user; +} + +/// Return the users profile base and the unknown arbitary data. +bool ProfileManager::GetProfileBaseAndData(boost::optional<size_t> index, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const { + if (GetProfileBase(index, profile)) { + std::memcpy(data.data(), profiles[index.get()].data.data(), MAX_DATA); + return true; + } + return false; +} + +/// Return the users profile base and the unknown arbitary data. +bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const { + auto idx = GetUserIndex(uuid); + return GetProfileBaseAndData(idx, profile, data); +} + +/// Return the users profile base and the unknown arbitary data. +bool ProfileManager::GetProfileBaseAndData(ProfileInfo user, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const { + return GetProfileBaseAndData(user.user_uuid, profile, data); +} + +/// Returns if the system is allowing user registrations or not +bool ProfileManager::CanSystemRegisterUser() const { + return false; // TODO(ogniK): Games shouldn't have + // access to user registration, when we + // emulate qlaunch. Update this to dynamically change. +} + +}; // 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..314bccbf9 --- /dev/null +++ b/src/core/hle/service/acc/profile_manager.h @@ -0,0 +1,124 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <array> +#include <random> +#include "boost/optional.hpp" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/result.h" + +namespace Service::Account { +constexpr size_t MAX_USERS = 8; +constexpr size_t MAX_DATA = 128; +static const u128 INVALID_UUID = {0, 0}; + +struct UUID { + // UUIDs which are 0 are considered invalid! + u128 uuid = INVALID_UUID; + UUID() = default; + explicit UUID(const u128& id) : uuid{id} {} + explicit UUID(const u64 lo, const u64 hi) { + uuid[0] = lo; + uuid[1] = hi; + }; + explicit operator bool() const { + return uuid[0] != INVALID_UUID[0] || uuid[1] != INVALID_UUID[1]; + } + + bool operator==(const UUID& rhs) const { + return std::tie(uuid[0], uuid[1]) == std::tie(rhs.uuid[0], rhs.uuid[1]); + } + + bool operator!=(const UUID& rhs) const { + return !operator==(rhs); + } + + // TODO(ogniK): Properly generate uuids based on RFC-4122 + const UUID& Generate() { + std::random_device device; + std::mt19937 gen(device()); + std::uniform_int_distribution<uint64_t> distribution(1, + std::numeric_limits<uint64_t>::max()); + uuid[0] = distribution(gen); + uuid[1] = distribution(gen); + return *this; + } + + // Set the UUID to {0,0} to be considered an invalid user + void Invalidate() { + uuid = INVALID_UUID; + } + std::string Format() const { + return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]); + } +}; +static_assert(sizeof(UUID) == 16, "UUID is an invalid size!"); + +/// This holds general information about a users profile. This is where we store all the information +/// based on a specific user +struct ProfileInfo { + UUID user_uuid; + std::array<u8, 0x20> username; + u64 creation_time; + std::array<u8, MAX_DATA> data; // TODO(ognik): Work out what this is + bool is_open; +}; + +struct ProfileBase { + UUID user_uuid; + u64_le timestamp; + std::array<u8, 0x20> username; + + // Zero out all the fields to make the profile slot considered "Empty" + void Invalidate() { + user_uuid.Invalidate(); + timestamp = 0; + username.fill(0); + } +}; +static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase is an invalid size"); + +/// The profile manager is used for handling multiple user profiles at once. It keeps track of open +/// users, all the accounts registered on the "system" as well as fetching individual "ProfileInfo" +/// objects +class ProfileManager { +public: + ProfileManager(); // TODO(ogniK): Load from system save + ResultCode AddUser(ProfileInfo user); + ResultCode CreateNewUser(UUID uuid, std::array<u8, 0x20>& username); + ResultCode CreateNewUser(UUID uuid, const std::string& username); + boost::optional<size_t> GetUserIndex(const UUID& uuid) const; + boost::optional<size_t> GetUserIndex(ProfileInfo user) const; + bool GetProfileBase(boost::optional<size_t> index, ProfileBase& profile) const; + bool GetProfileBase(UUID uuid, ProfileBase& profile) const; + bool GetProfileBase(ProfileInfo user, ProfileBase& profile) const; + bool GetProfileBaseAndData(boost::optional<size_t> index, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const; + bool GetProfileBaseAndData(UUID uuid, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const; + bool GetProfileBaseAndData(ProfileInfo user, ProfileBase& profile, + std::array<u8, MAX_DATA>& data) const; + size_t GetUserCount() const; + size_t GetOpenUserCount() const; + bool UserExists(UUID uuid) const; + void OpenUser(UUID uuid); + void CloseUser(UUID uuid); + std::array<UUID, MAX_USERS> GetOpenUsers() const; + std::array<UUID, MAX_USERS> GetAllUsers() const; + UUID GetLastOpenedUser() const; + + bool CanSystemRegisterUser() const; + +private: + std::array<ProfileInfo, MAX_USERS> profiles{}; + size_t user_count = 0; + boost::optional<size_t> AddToProfiles(const ProfileInfo& profile); + bool RemoveProfileAtIndex(size_t index); + UUID last_opened_user{0, 0}; +}; + +}; // namespace Service::Account diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 762763463..c524e7a48 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -145,8 +145,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger {51, nullptr, "ApproveToDisplay"}, {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, {61, nullptr, "SetMediaPlaybackState"}, - {62, nullptr, "SetIdleTimeDetectionExtension"}, - {63, nullptr, "GetIdleTimeDetectionExtension"}, + {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, + {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"}, {64, nullptr, "SetInputDetectionSourceSet"}, {65, nullptr, "ReportUserIsActive"}, {66, nullptr, "GetCurrentIlluminance"}, @@ -281,6 +281,23 @@ void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx) LOG_WARNING(Service_AM, "(STUBBED) called"); } +void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + idle_time_detection_extension = rp.Pop<u32>(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_AM, "(STUBBED) called"); +} + +void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(idle_time_detection_extension); + + LOG_WARNING(Service_AM, "(STUBBED) called"); +} + ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, @@ -306,7 +323,8 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter" {52, nullptr, "SwitchLcdBacklight"}, {55, nullptr, "IsInControllerFirmwareUpdateSection"}, {60, nullptr, "GetDefaultDisplayResolution"}, - {61, nullptr, "GetDefaultDisplayResolutionChangeEvent"}, + {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, + "GetDefaultDisplayResolutionChangeEvent"}, {62, nullptr, "GetHdcpAuthenticationState"}, {63, nullptr, "GetHdcpAuthenticationStateChangeEvent"}, }; @@ -341,6 +359,16 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); } +void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) { + event->Signal(); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(event); + + LOG_WARNING(Service_AM, "(STUBBED) called"); +} + void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { const bool use_docked_mode{Settings::values.use_docked_mode}; IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 862f338ac..b763aff6f 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -87,9 +87,12 @@ private: void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); void SetScreenShotPermission(Kernel::HLERequestContext& ctx); void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); + void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); + void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; Kernel::SharedPtr<Kernel::Event> launchable_event; + u32 idle_time_detection_extension = 0; }; class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { @@ -110,6 +113,7 @@ private: void GetEventHandle(Kernel::HLERequestContext& ctx); void ReceiveMessage(Kernel::HLERequestContext& ctx); void GetCurrentFocusState(Kernel::HLERequestContext& ctx); + void GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx); void GetOperationMode(Kernel::HLERequestContext& ctx); void GetPerformanceMode(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 5e416cde2..da658cbe6 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -226,6 +226,7 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( static std::unique_ptr<FileSys::RomFSFactory> romfs_factory; static std::unique_ptr<FileSys::SaveDataFactory> save_data_factory; static std::unique_ptr<FileSys::SDMCFactory> sdmc_factory; +static std::unique_ptr<FileSys::BISFactory> bis_factory; ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) { ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second RomFS"); @@ -248,6 +249,13 @@ ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) { return RESULT_SUCCESS; } +ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) { + ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS"); + bis_factory = std::move(factory); + LOG_DEBUG(Service_FS, "Registred BIS"); + return RESULT_SUCCESS; +} + ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id) { LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}", title_id); @@ -281,6 +289,14 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() { return sdmc_factory->Open(); } +std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() { + return bis_factory->GetSystemNANDContents(); +} + +std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() { + return bis_factory->GetUserNANDContents(); +} + void RegisterFileSystems(const FileSys::VirtualFilesystem& vfs) { romfs_factory = nullptr; save_data_factory = nullptr; @@ -291,6 +307,9 @@ void RegisterFileSystems(const FileSys::VirtualFilesystem& vfs) { auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite); + if (bis_factory == nullptr) + bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory); + auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); save_data_factory = std::move(savedata); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 462c13f20..1d6f922dd 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -6,6 +6,7 @@ #include <memory> #include "common/common_types.h" +#include "core/file_sys/bis_factory.h" #include "core/file_sys/directory.h" #include "core/file_sys/mode.h" #include "core/file_sys/romfs_factory.h" @@ -24,16 +25,15 @@ namespace FileSystem { ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory); ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory); ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory); +ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); -// TODO(DarkLordZach): BIS Filesystem -// ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id); ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct); ResultVal<FileSys::VirtualDir> OpenSDMC(); -// TODO(DarkLordZach): BIS Filesystem -// ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenBIS(); +std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents(); +std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents(); /// Registers all Filesystem services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs); diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 2e99ddf51..098da2a41 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -92,7 +92,11 @@ private: // Parse out log metadata u32 line{}; - std::string message, filename, function; + std::string module; + std::string message; + std::string filename; + std::string function; + std::string thread; while (addr < end_addr) { const Field field{static_cast<Field>(Memory::Read8(addr++))}; const size_t length{Memory::Read8(addr++)}; @@ -102,6 +106,8 @@ private: } switch (field) { + case Field::Skip: + break; case Field::Message: message = Memory::ReadCString(addr, length); break; @@ -114,6 +120,12 @@ private: case Field::Function: function = Memory::ReadCString(addr, length); break; + case Field::Module: + module = Memory::ReadCString(addr, length); + break; + case Field::Thread: + thread = Memory::ReadCString(addr, length); + break; } addr += length; @@ -128,12 +140,18 @@ private: if (!filename.empty()) { log_stream << filename << ':'; } + if (!module.empty()) { + log_stream << module << ':'; + } if (!function.empty()) { log_stream << function << ':'; } if (line) { log_stream << std::to_string(line) << ':'; } + if (!thread.empty()) { + log_stream << thread << ':'; + } if (log_stream.str().length() > 0 && log_stream.str().back() == ':') { log_stream << ' '; } @@ -142,7 +160,7 @@ private: if (header.IsTailLog()) { switch (header.severity) { case MessageHeader::Severity::Trace: - LOG_TRACE(Debug_Emulated, "{}", log_stream.str()); + LOG_DEBUG(Debug_Emulated, "{}", log_stream.str()); break; case MessageHeader::Severity::Info: LOG_INFO(Debug_Emulated, "{}", log_stream.str()); diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index 08f45b78a..7b91bb258 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp @@ -9,42 +9,63 @@ namespace Service::MM { -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<MM_U>()->InstallAsService(service_manager); -} +class MM_U final : public ServiceFramework<MM_U> { +public: + explicit MM_U() : ServiceFramework{"mm:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &MM_U::Initialize, "InitializeOld"}, + {1, &MM_U::Finalize, "FinalizeOld"}, + {2, &MM_U::SetAndWait, "SetAndWaitOld"}, + {3, &MM_U::Get, "GetOld"}, + {4, &MM_U::Initialize, "Initialize"}, + {5, &MM_U::Finalize, "Finalize"}, + {6, &MM_U::SetAndWait, "SetAndWait"}, + {7, &MM_U::Get, "Get"}, + }; + // clang-format on -void MM_U::Initialize(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} + RegisterHandlers(functions); + } -void MM_U::SetAndWait(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - min = rp.Pop<u32>(); - max = rp.Pop<u32>(); - current = min; +private: + void Initialize(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_MM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } - LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} + void Finalize(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_MM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } -void MM_U::Get(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_MM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(current); -} + void SetAndWait(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + min = rp.Pop<u32>(); + max = rp.Pop<u32>(); + current = min; -MM_U::MM_U() : ServiceFramework("mm:u") { - static const FunctionInfo functions[] = { - {0, nullptr, "InitializeOld"}, {1, nullptr, "FinalizeOld"}, - {2, nullptr, "SetAndWaitOld"}, {3, nullptr, "GetOld"}, - {4, &MM_U::Initialize, "Initialize"}, {5, nullptr, "Finalize"}, - {6, &MM_U::SetAndWait, "SetAndWait"}, {7, &MM_U::Get, "Get"}, - }; - RegisterHandlers(functions); + LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Get(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_MM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(current); + } + + u32 min{0}; + u32 max{0}; + u32 current{0}; +}; + +void InstallInterfaces(SM::ServiceManager& service_manager) { + std::make_shared<MM_U>()->InstallAsService(service_manager); } } // namespace Service::MM diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h index 79eeedf9c..5439fa653 100644 --- a/src/core/hle/service/mm/mm_u.h +++ b/src/core/hle/service/mm/mm_u.h @@ -8,21 +8,6 @@ namespace Service::MM { -class MM_U final : public ServiceFramework<MM_U> { -public: - MM_U(); - ~MM_U() = default; - -private: - void Initialize(Kernel::HLERequestContext& ctx); - void SetAndWait(Kernel::HLERequestContext& ctx); - void Get(Kernel::HLERequestContext& ctx); - - u32 min{0}; - u32 max{0}; - u32 current{0}; -}; - /// Registers all MM services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp index fcf1f3da3..6cc3b1992 100644 --- a/src/core/hle/service/pctl/module.cpp +++ b/src/core/hle/service/pctl/module.cpp @@ -14,7 +14,8 @@ public: IParentalControlService() : ServiceFramework("IParentalControlService") { static const FunctionInfo functions[] = { {1, &IParentalControlService::Initialize, "Initialize"}, - {1001, nullptr, "CheckFreeCommunicationPermission"}, + {1001, &IParentalControlService::CheckFreeCommunicationPermission, + "CheckFreeCommunicationPermission"}, {1002, nullptr, "ConfirmLaunchApplicationPermission"}, {1003, nullptr, "ConfirmResumeApplicationPermission"}, {1004, nullptr, "ConfirmSnsPostPermission"}, @@ -116,6 +117,12 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 0}; rb.Push(RESULT_SUCCESS); } + + void CheckFreeCommunicationPermission(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_PCTL, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } }; void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index 518a0cc46..1cef73216 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp @@ -10,7 +10,7 @@ namespace Service::SM { void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) { - ASSERT_MSG(!ctx.Session()->IsDomain(), "session is alread a domain"); + ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain"); ctx.Session()->ConvertToDomain(); IPC::ResponseBuilder rb{ctx, 3}; @@ -41,7 +41,7 @@ void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) { void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0x500); + rb.Push<u16>(0x500); LOG_WARNING(Service, "(STUBBED) called"); } |
