diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6862627028..30eb9d82e3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -175,6 +175,7 @@ add_library(core STATIC hle/service/acc/acc_u0.h hle/service/acc/acc_u1.cpp hle/service/acc/acc_u1.h + hle/service/acc/errors.h hle/service/acc/profile_manager.cpp hle/service/acc/profile_manager.h hle/service/am/am.cpp diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 0cd8158dfd..c01ee3eda1 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -15,13 +15,18 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/service/acc/acc.h" #include "core/hle/service/acc/acc_aa.h" #include "core/hle/service/acc/acc_su.h" #include "core/hle/service/acc/acc_u0.h" #include "core/hle/service/acc/acc_u1.h" +#include "core/hle/service/acc/errors.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/manager.h" +#include "core/hle/service/sm/sm.h" #include "core/loader/loader.h" namespace Service::Account { @@ -217,10 +222,72 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon rb.Push(profile_manager->CanSystemRegisterUser()); } -void Module::Interface::InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); +void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto pid = rp.Pop(); + + LOG_DEBUG(Service_ACC, "called, process_id={}", pid); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); + rb.Push(InitializeApplicationInfoBase(pid)); +} + +void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto pid = rp.Pop(); + + LOG_WARNING(Service_ACC, "(Partial implementation) called, process_id={}", pid); + + // TODO(ogniK): We require checking if the user actually owns the title and what not. As of + // currently, we assume the user owns the title. InitializeApplicationInfoBase SHOULD be called + // first then we do extra checks if the game is a digital copy. + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(InitializeApplicationInfoBase(pid)); +} + +ResultCode Module::Interface::InitializeApplicationInfoBase(u64 process_id) { + if (application_info) { + LOG_ERROR(Service_ACC, "Application already initialized"); + return ERR_ACCOUNTINFO_ALREADY_INITIALIZED; + } + + const auto& list = system.Kernel().GetProcessList(); + const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { + return process->GetProcessID() == process_id; + }); + + if (iter == list.end()) { + LOG_ERROR(Service_ACC, "Failed to find process ID"); + application_info.application_type = ApplicationType::Unknown; + + return ERR_ACCOUNTINFO_BAD_APPLICATION; + } + + const auto launch_property = system.GetARPManager().GetLaunchProperty((*iter)->GetTitleID()); + + if (launch_property.Failed()) { + LOG_ERROR(Service_ACC, "Failed to get launch property"); + return ERR_ACCOUNTINFO_BAD_APPLICATION; + } + + switch (launch_property->base_game_storage_id) { + case FileSys::StorageId::GameCard: + application_info.application_type = ApplicationType::GameCard; + break; + case FileSys::StorageId::Host: + case FileSys::StorageId::NandUser: + case FileSys::StorageId::SdCard: + application_info.application_type = ApplicationType::Digital; + break; + default: + LOG_ERROR(Service_ACC, "Invalid game storage ID"); + return ERR_ACCOUNTINFO_BAD_APPLICATION; + } + + LOG_WARNING(Service_ACC, "ApplicationInfo init required"); + // TODO(ogniK): Actual initalization here + + return RESULT_SUCCESS; } void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index 350f123a08..f651773b7b 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/glue/manager.h" #include "core/hle/service/service.h" namespace Service::Account { @@ -25,12 +26,33 @@ public: void ListOpenUsers(Kernel::HLERequestContext& ctx); void GetLastOpenedUser(Kernel::HLERequestContext& ctx); void GetProfile(Kernel::HLERequestContext& ctx); - void InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx); + void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); + void InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx); void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx); + private: + ResultCode InitializeApplicationInfoBase(u64 process_id); + + enum class ApplicationType : u32_le { + GameCard = 0, + Digital = 1, + Unknown = 3, + }; + + struct ApplicationInfo { + Service::Glue::ApplicationLaunchProperty launch_property; + ApplicationType application_type; + + constexpr explicit operator bool() const { + return launch_property.title_id != 0x0; + } + }; + + ApplicationInfo application_info{}; + protected: std::shared_ptr module; std::shared_ptr profile_manager; diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 2f239e8c03..0ac19f4fff 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -22,7 +22,7 @@ ACC_U0::ACC_U0(std::shared_ptr module, std::shared_ptr p {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {99, nullptr, "DebugActivateOpenContextRetention"}, - {100, &ACC_U0::InitializeApplicationInfoOld, "InitializeApplicationInfoOld"}, + {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, {102, nullptr, "AuthenticateApplicationAsync"}, {103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, @@ -31,7 +31,7 @@ ACC_U0::ACC_U0(std::shared_ptr module, std::shared_ptr p {120, nullptr, "CreateGuestLoginRequest"}, {130, nullptr, "LoadOpenContext"}, {131, nullptr, "ListOpenContextStoredUsers"}, - {140, nullptr, "InitializeApplicationInfo"}, + {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, {141, nullptr, "ListQualifiedUsers"}, {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, }; diff --git a/src/core/hle/service/acc/errors.h b/src/core/hle/service/acc/errors.h new file mode 100644 index 0000000000..1f05772394 --- /dev/null +++ b/src/core/hle/service/acc/errors.h @@ -0,0 +1,14 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" + +namespace Service::Account { + +constexpr ResultCode ERR_ACCOUNTINFO_BAD_APPLICATION{ErrorModule::Account, 22}; +constexpr ResultCode ERR_ACCOUNTINFO_ALREADY_INITIALIZED{ErrorModule::Account, 41}; + +} // namespace Service::Account