diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | src/core/core.cpp | 66 | ||||
| -rw-r--r-- | src/core/core.h | 8 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 10 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.h | 9 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.cpp | 14 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/arp/arp.cpp | 75 | ||||
| -rw-r--r-- | src/core/hle/service/arp/arp.h | 16 | ||||
| -rw-r--r-- | src/core/hle/service/glue/arp.cpp | 297 | ||||
| -rw-r--r-- | src/core/hle/service/glue/arp.h | 43 | ||||
| -rw-r--r-- | src/core/hle/service/glue/bgtc.cpp | 50 | ||||
| -rw-r--r-- | src/core/hle/service/glue/bgtc.h | 23 | ||||
| -rw-r--r-- | src/core/hle/service/glue/errors.h | 16 | ||||
| -rw-r--r-- | src/core/hle/service/glue/glue.cpp | 25 | ||||
| -rw-r--r-- | src/core/hle/service/glue/glue.h | 16 | ||||
| -rw-r--r-- | src/core/hle/service/glue/manager.cpp | 78 | ||||
| -rw-r--r-- | src/core/hle/service/glue/manager.h | 63 | ||||
| -rw-r--r-- | src/core/hle/service/service.cpp | 4 | 
19 files changed, 730 insertions, 97 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index cdb3bf6ab..d65659b44 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -209,8 +209,6 @@ add_library(core STATIC      hle/service/apm/apm.h      hle/service/apm/interface.cpp      hle/service/apm/interface.h -    hle/service/arp/arp.cpp -    hle/service/arp/arp.h      hle/service/audio/audctl.cpp      hle/service/audio/audctl.h      hle/service/audio/auddbg.cpp @@ -276,6 +274,15 @@ add_library(core STATIC      hle/service/friend/friend.h      hle/service/friend/interface.cpp      hle/service/friend/interface.h +    hle/service/glue/arp.cpp +    hle/service/glue/arp.h +    hle/service/glue/bgtc.cpp +    hle/service/glue/bgtc.h +    hle/service/glue/errors.h +    hle/service/glue/glue.cpp +    hle/service/glue/glue.h +    hle/service/glue/manager.cpp +    hle/service/glue/manager.h      hle/service/grc/grc.cpp      hle/service/grc/grc.h      hle/service/hid/hid.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index c00dfd33c..df26eb109 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,6 +25,7 @@  #include "core/hle/kernel/scheduler.h"  #include "core/hle/kernel/thread.h"  #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/glue/manager.h"  #include "core/hle/service/service.h"  #include "core/hle/service/sm/sm.h"  #include "core/loader/loader.h" @@ -33,12 +34,37 @@  #include "core/settings.h"  #include "core/telemetry_session.h"  #include "file_sys/cheat_engine.h" +#include "file_sys/patch_manager.h"  #include "video_core/debug_utils/debug_utils.h"  #include "video_core/renderer_base.h"  #include "video_core/video_core.h"  namespace Core { +namespace { + +FileSys::StorageId GetStorageIdForFrontendSlot( +    std::optional<FileSys::ContentProviderUnionSlot> slot) { +    if (!slot.has_value()) { +        return FileSys::StorageId::None; +    } + +    switch (*slot) { +    case FileSys::ContentProviderUnionSlot::UserNAND: +        return FileSys::StorageId::NandUser; +    case FileSys::ContentProviderUnionSlot::SysNAND: +        return FileSys::StorageId::NandSystem; +    case FileSys::ContentProviderUnionSlot::SDMC: +        return FileSys::StorageId::SdCard; +    case FileSys::ContentProviderUnionSlot::FrontendManual: +        return FileSys::StorageId::Host; +    default: +        return FileSys::StorageId::None; +    } +} + +} // Anonymous namespace +  /*static*/ System System::s_instance;  FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, @@ -110,6 +136,9 @@ struct System::Impl {          /// Create default implementations of applets if one is not provided.          applet_manager.SetDefaultAppletsIfMissing(); +        /// Reset all glue registrations +        arp_manager.ResetAll(); +          telemetry_session = std::make_unique<Core::TelemetrySession>();          service_manager = std::make_shared<Service::SM::ServiceManager>(); @@ -161,6 +190,7 @@ struct System::Impl {              return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +                                               static_cast<u32>(load_result));          } +        AddGlueRegistrationForProcess(*app_loader, *main_process);          kernel.MakeCurrentProcess(main_process.get());          // Main process has been loaded and been made current. @@ -219,6 +249,31 @@ struct System::Impl {          return app_loader->ReadTitle(out);      } +    void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::Process& process) { +        std::vector<u8> nacp_data; +        FileSys::NACP nacp; +        if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) { +            nacp_data = nacp.GetRawBytes(); +        } else { +            nacp_data.resize(sizeof(FileSys::RawNACP)); +        } + +        Service::Glue::ApplicationLaunchProperty launch{}; +        launch.title_id = process.GetTitleID(); + +        FileSys::PatchManager pm{launch.title_id}; +        launch.version = pm.GetGameVersion().value_or(0); + +        // TODO(DarkLordZach): When FSController/Game Card Support is added, if +        // current_process_game_card use correct StorageId +        launch.base_game_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( +            launch.title_id, FileSys::ContentRecordType::Program)); +        launch.update_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( +            FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); + +        arp_manager.Register(launch.title_id, launch, std::move(nacp_data)); +    } +      void SetStatus(ResultStatus new_status, const char* details = nullptr) {          status = new_status;          if (details) { @@ -249,6 +304,9 @@ struct System::Impl {      /// Frontend applets      Service::AM::Applets::AppletManager applet_manager; +    /// Glue services +    Service::Glue::ARPManager arp_manager; +      /// Service manager      std::shared_ptr<Service::SM::ServiceManager> service_manager; @@ -500,6 +558,14 @@ const Reporter& System::GetReporter() const {      return impl->reporter;  } +Service::Glue::ARPManager& System::GetARPManager() { +    return impl->arp_manager; +} + +const Service::Glue::ARPManager& System::GetARPManager() const { +    return impl->arp_manager; +} +  System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {      return impl->Init(*this, emu_window);  } diff --git a/src/core/core.h b/src/core/core.h index 226ef4630..70adb7af9 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -43,6 +43,10 @@ struct AppletFrontendSet;  class AppletManager;  } // namespace AM::Applets +namespace Glue { +class ARPManager; +} +  namespace SM {  class ServiceManager;  } // namespace SM @@ -288,6 +292,10 @@ public:      const Reporter& GetReporter() const; +    Service::Glue::ARPManager& GetARPManager(); + +    const Service::Glue::ARPManager& GetARPManager() const; +  private:      System(); diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index da823c37b..a8f80e2c6 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -493,6 +493,16 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam      return out;  } +std::optional<u32> PatchManager::GetGameVersion() const { +    const auto& installed = Core::System::GetInstance().GetContentProvider(); +    const auto update_tid = GetUpdateTitleID(title_id); +    if (installed.HasEntry(update_tid, ContentRecordType::Program)) { +        return installed.GetEntryVersion(update_tid); +    } + +    return installed.GetEntryVersion(title_id); +} +  std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {      const auto& installed = Core::System::GetInstance().GetContentProvider(); diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 769f8c6f0..a363c6577 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -66,8 +66,13 @@ public:      std::map<std::string, std::string, std::less<>> GetPatchVersionNames(          VirtualFile update_raw = nullptr) const; -    // Given title_id of the program, attempts to get the control data of the update and parse it, -    // falling back to the base control data. +    // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, +    // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be +    // std::nullopt +    std::optional<u32> GetGameVersion() const; + +    // Given title_id of the program, attempts to get the control data of the update and parse +    // it, falling back to the base control data.      std::pair<std::unique_ptr<NACP>, VirtualFile> GetControlMetadata() const;      // Version of GetControlMetadata that takes an arbitrary NCA diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 58917e094..4608490e0 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -645,6 +645,20 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional<ContentProviderUnion      return out;  } +std::optional<ContentProviderUnionSlot> ContentProviderUnion::GetSlotForEntry( +    u64 title_id, ContentRecordType type) const { +    const auto iter = +        std::find_if(providers.begin(), providers.end(), [title_id, type](const auto& provider) { +            return provider.second != nullptr && provider.second->HasEntry(title_id, type); +        }); + +    if (iter == providers.end()) { +        return std::nullopt; +    } + +    return iter->first; +} +  ManualContentProvider::~ManualContentProvider() = default;  void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type, diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index ec9052653..4398d63e1 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h @@ -199,6 +199,9 @@ public:          std::optional<TitleType> title_type = {}, std::optional<ContentRecordType> record_type = {},          std::optional<u64> title_id = {}) const; +    std::optional<ContentProviderUnionSlot> GetSlotForEntry(u64 title_id, +                                                            ContentRecordType type) const; +  private:      std::map<ContentProviderUnionSlot, ContentProvider*> providers;  }; diff --git a/src/core/hle/service/arp/arp.cpp b/src/core/hle/service/arp/arp.cpp deleted file mode 100644 index e675b0188..000000000 --- a/src/core/hle/service/arp/arp.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <memory> - -#include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/hle_ipc.h" -#include "core/hle/service/arp/arp.h" -#include "core/hle/service/service.h" -#include "core/hle/service/sm/sm.h" - -namespace Service::ARP { - -class ARP_R final : public ServiceFramework<ARP_R> { -public: -    explicit ARP_R() : ServiceFramework{"arp:r"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "GetApplicationLaunchProperty"}, -            {1, nullptr, "GetApplicationLaunchPropertyWithApplicationId"}, -            {2, nullptr, "GetApplicationControlProperty"}, -            {3, nullptr, "GetApplicationControlPropertyWithApplicationId"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } -}; - -class IRegistrar final : public ServiceFramework<IRegistrar> { -public: -    explicit IRegistrar() : ServiceFramework{"IRegistrar"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "Issue"}, -            {1, nullptr, "SetApplicationLaunchProperty"}, -            {2, nullptr, "SetApplicationControlProperty"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } -}; - -class ARP_W final : public ServiceFramework<ARP_W> { -public: -    explicit ARP_W() : ServiceFramework{"arp:w"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, -            {1, nullptr, "DeleteProperties"}, -        }; -        // clang-format on - -        RegisterHandlers(functions); -    } - -private: -    void AcquireRegistrar(Kernel::HLERequestContext& ctx) { -        LOG_DEBUG(Service_ARP, "called"); - -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(RESULT_SUCCESS); -        rb.PushIpcInterface<IRegistrar>(); -    } -}; - -void InstallInterfaces(SM::ServiceManager& sm) { -    std::make_shared<ARP_R>()->InstallAsService(sm); -    std::make_shared<ARP_W>()->InstallAsService(sm); -} - -} // namespace Service::ARP diff --git a/src/core/hle/service/arp/arp.h b/src/core/hle/service/arp/arp.h deleted file mode 100644 index 9d100187c..000000000 --- a/src/core/hle/service/arp/arp.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -namespace Service::SM { -class ServiceManager; -} - -namespace Service::ARP { - -/// Registers all ARP services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); - -} // namespace Service::ARP diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp new file mode 100644 index 000000000..b591ce31b --- /dev/null +++ b/src/core/hle/service/glue/arp.cpp @@ -0,0 +1,297 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <memory> + +#include "common/logging/log.h" +#include "core/file_sys/control_metadata.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/errors.h" +#include "core/hle/service/glue/manager.h" +#include "core/hle/service/service.h" + +namespace Service::Glue { + +namespace { +std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 process_id) { +    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()) { +        return std::nullopt; +    } + +    return (*iter)->GetTitleID(); +} +} // Anonymous namespace + +ARP_R::ARP_R(const Core::System& system, const ARPManager& manager) +    : ServiceFramework{"arp:r"}, system(system), manager(manager) { +    // clang-format off +        static const FunctionInfo functions[] = { +            {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"}, +            {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, +            {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, +            {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, +        }; +    // clang-format on + +    RegisterHandlers(functions); +} + +ARP_R::~ARP_R() = default; + +void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto process_id = rp.PopRaw<u64>(); + +    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + +    const auto title_id = GetTitleIDForProcessID(system, process_id); +    if (!title_id.has_value()) { +        LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(ERR_NOT_REGISTERED); +        return; +    } + +    const auto res = manager.GetLaunchProperty(*title_id); + +    if (res.Failed()) { +        LOG_ERROR(Service_ARP, "Failed to get launch property!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code()); +        return; +    } + +    IPC::ResponseBuilder rb{ctx, 6}; +    rb.Push(RESULT_SUCCESS); +    rb.PushRaw(*res); +} + +void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto title_id = rp.PopRaw<u64>(); + +    LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + +    const auto res = manager.GetLaunchProperty(title_id); + +    if (res.Failed()) { +        LOG_ERROR(Service_ARP, "Failed to get launch property!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code()); +        return; +    } + +    IPC::ResponseBuilder rb{ctx, 6}; +    rb.Push(RESULT_SUCCESS); +    rb.PushRaw(*res); +} + +void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto process_id = rp.PopRaw<u64>(); + +    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + +    const auto title_id = GetTitleIDForProcessID(system, process_id); +    if (!title_id.has_value()) { +        LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(ERR_NOT_REGISTERED); +        return; +    } + +    const auto res = manager.GetControlProperty(*title_id); + +    if (res.Failed()) { +        LOG_ERROR(Service_ARP, "Failed to get control property!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code()); +        return; +    } + +    ctx.WriteBuffer(*res); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(RESULT_SUCCESS); +} + +void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto title_id = rp.PopRaw<u64>(); + +    LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); + +    const auto res = manager.GetControlProperty(title_id); + +    if (res.Failed()) { +        LOG_ERROR(Service_ARP, "Failed to get control property!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code()); +        return; +    } + +    ctx.WriteBuffer(*res); + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(RESULT_SUCCESS); +} + +class IRegistrar final : public ServiceFramework<IRegistrar> { +    friend class ARP_W; + +public: +    explicit IRegistrar( +        std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issuer) +        : ServiceFramework{"IRegistrar"}, issue_process_id(std::move(issuer)) { +        // clang-format off +        static const FunctionInfo functions[] = { +            {0, &IRegistrar::Issue, "Issue"}, +            {1, &IRegistrar::SetApplicationLaunchProperty, "SetApplicationLaunchProperty"}, +            {2, &IRegistrar::SetApplicationControlProperty, "SetApplicationControlProperty"}, +        }; +        // clang-format on + +        RegisterHandlers(functions); +    } + +private: +    void Issue(Kernel::HLERequestContext& ctx) { +        IPC::RequestParser rp{ctx}; +        const auto process_id = rp.PopRaw<u64>(); + +        LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + +        if (process_id == 0) { +            LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); +            IPC::ResponseBuilder rb{ctx, 2}; +            rb.Push(ERR_INVALID_PROCESS_ID); +            return; +        } + +        if (issued) { +            LOG_ERROR(Service_ARP, +                      "Attempted to issue registrar, but registrar is already issued!"); +            IPC::ResponseBuilder rb{ctx, 2}; +            rb.Push(ERR_INVALID_ACCESS); +            return; +        } + +        issue_process_id(process_id, launch, std::move(control)); +        issued = true; + +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(RESULT_SUCCESS); +    } + +    void SetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { +        LOG_DEBUG(Service_ARP, "called"); + +        if (issued) { +            LOG_ERROR( +                Service_ARP, +                "Attempted to set application launch property, but registrar is already issued!"); +            IPC::ResponseBuilder rb{ctx, 2}; +            rb.Push(ERR_INVALID_ACCESS); +            return; +        } + +        IPC::RequestParser rp{ctx}; +        launch = rp.PopRaw<ApplicationLaunchProperty>(); + +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(RESULT_SUCCESS); +    } + +    void SetApplicationControlProperty(Kernel::HLERequestContext& ctx) { +        LOG_DEBUG(Service_ARP, "called"); + +        if (issued) { +            LOG_ERROR( +                Service_ARP, +                "Attempted to set application control property, but registrar is already issued!"); +            IPC::ResponseBuilder rb{ctx, 2}; +            rb.Push(ERR_INVALID_ACCESS); +            return; +        } + +        control = ctx.ReadBuffer(); + +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(RESULT_SUCCESS); +    } + +    std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id; +    bool issued = false; +    ApplicationLaunchProperty launch; +    std::vector<u8> control; +}; + +ARP_W::ARP_W(const Core::System& system, ARPManager& manager) +    : ServiceFramework{"arp:w"}, system(system), manager(manager) { +    // clang-format off +        static const FunctionInfo functions[] = { +            {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, +            {1, &ARP_W::DeleteProperties, "DeleteProperties"}, +        }; +    // clang-format on + +    RegisterHandlers(functions); +} + +ARP_W::~ARP_W() = default; + +void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { +    LOG_DEBUG(Service_ARP, "called"); + +    registrar = std::make_shared<IRegistrar>( +        [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) { +            const auto res = GetTitleIDForProcessID(system, process_id); +            if (!res.has_value()) { +                return ERR_NOT_REGISTERED; +            } + +            return manager.Register(*res, launch, std::move(control)); +        }); + +    IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +    rb.Push(RESULT_SUCCESS); +    rb.PushIpcInterface(registrar); +} + +void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto process_id = rp.PopRaw<u64>(); + +    LOG_DEBUG(Service_ARP, "called, process_id={:016X}", process_id); + +    if (process_id == 0) { +        LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(ERR_INVALID_PROCESS_ID); +        return; +    } + +    const auto title_id = GetTitleIDForProcessID(system, process_id); + +    if (!title_id.has_value()) { +        LOG_ERROR(Service_ARP, "No title ID for process ID!"); +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(ERR_NOT_REGISTERED); +        return; +    } + +    IPC::ResponseBuilder rb{ctx, 2}; +    rb.Push(manager.Unregister(*title_id)); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h new file mode 100644 index 000000000..d5f8a7e7a --- /dev/null +++ b/src/core/hle/service/glue/arp.h @@ -0,0 +1,43 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::Glue { + +class ARPManager; +class IRegistrar; + +class ARP_R final : public ServiceFramework<ARP_R> { +public: +    explicit ARP_R(const Core::System& system, const ARPManager& manager); +    ~ARP_R() override; + +private: +    void GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx); +    void GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestContext& ctx); +    void GetApplicationControlProperty(Kernel::HLERequestContext& ctx); +    void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx); + +    const Core::System& system; +    const ARPManager& manager; +}; + +class ARP_W final : public ServiceFramework<ARP_W> { +public: +    explicit ARP_W(const Core::System& system, ARPManager& manager); +    ~ARP_W() override; + +private: +    void AcquireRegistrar(Kernel::HLERequestContext& ctx); +    void DeleteProperties(Kernel::HLERequestContext& ctx); + +    const Core::System& system; +    ARPManager& manager; +    std::shared_ptr<IRegistrar> registrar; +}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp new file mode 100644 index 000000000..cd89d088f --- /dev/null +++ b/src/core/hle/service/glue/bgtc.cpp @@ -0,0 +1,50 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/glue/bgtc.h" + +namespace Service::Glue { + +BGTC_T::BGTC_T() : ServiceFramework{"bgtc:t"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {1, nullptr, "NotifyTaskStarting"}, +        {2, nullptr, "NotifyTaskFinished"}, +        {3, nullptr, "GetTriggerEvent"}, +        {4, nullptr, "IsInHalfAwake"}, +        {5, nullptr, "NotifyClientName"}, +        {6, nullptr, "IsInFullAwake"}, +        {11, nullptr, "ScheduleTask"}, +        {12, nullptr, "GetScheduledTaskInterval"}, +        {13, nullptr, "UnscheduleTask"}, +        {14, nullptr, "GetScheduleEvent"}, +        {15, nullptr, "SchedulePeriodicTask"}, +        {101, nullptr, "GetOperationMode"}, +        {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, +        {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +BGTC_T::~BGTC_T() = default; + +BGTC_SC::BGTC_SC() : ServiceFramework{"bgtc:sc"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {1, nullptr, "GetState"}, +        {2, nullptr, "GetStateChangedEvent"}, +        {3, nullptr, "NotifyEnteringHalfAwake"}, +        {4, nullptr, "NotifyLeavingHalfAwake"}, +        {5, nullptr, "SetIsUsingSleepUnsupportedDevices"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +BGTC_SC::~BGTC_SC() = default; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h new file mode 100644 index 000000000..81844f03e --- /dev/null +++ b/src/core/hle/service/glue/bgtc.h @@ -0,0 +1,23 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service::Glue { + +class BGTC_T final : public ServiceFramework<BGTC_T> { +public: +    BGTC_T(); +    ~BGTC_T() override; +}; + +class BGTC_SC final : public ServiceFramework<BGTC_SC> { +public: +    BGTC_SC(); +    ~BGTC_SC() override; +}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h new file mode 100644 index 000000000..c2874c585 --- /dev/null +++ b/src/core/hle/service/glue/errors.h @@ -0,0 +1,16 @@ +// 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::Glue { + +constexpr ResultCode ERR_INVALID_RESOURCE{ErrorModule::ARP, 0x1E}; +constexpr ResultCode ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 0x1F}; +constexpr ResultCode ERR_INVALID_ACCESS{ErrorModule::ARP, 0x2A}; +constexpr ResultCode ERR_NOT_REGISTERED{ErrorModule::ARP, 0x66}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp new file mode 100644 index 000000000..c728e815c --- /dev/null +++ b/src/core/hle/service/glue/glue.cpp @@ -0,0 +1,25 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <memory> +#include "core/core.h" +#include "core/hle/service/glue/arp.h" +#include "core/hle/service/glue/bgtc.h" +#include "core/hle/service/glue/glue.h" + +namespace Service::Glue { + +void InstallInterfaces(Core::System& system) { +    // ARP +    std::make_shared<ARP_R>(system, system.GetARPManager()) +        ->InstallAsService(system.ServiceManager()); +    std::make_shared<ARP_W>(system, system.GetARPManager()) +        ->InstallAsService(system.ServiceManager()); + +    // BackGround Task Controller +    std::make_shared<BGTC_T>()->InstallAsService(system.ServiceManager()); +    std::make_shared<BGTC_SC>()->InstallAsService(system.ServiceManager()); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/glue.h b/src/core/hle/service/glue/glue.h new file mode 100644 index 000000000..112cd238b --- /dev/null +++ b/src/core/hle/service/glue/glue.h @@ -0,0 +1,16 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Core { +class System; +} // namespace Core + +namespace Service::Glue { + +/// Registers all Glue services with the specified service manager. +void InstallInterfaces(Core::System& system); + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/manager.cpp b/src/core/hle/service/glue/manager.cpp new file mode 100644 index 000000000..6da52d2d6 --- /dev/null +++ b/src/core/hle/service/glue/manager.cpp @@ -0,0 +1,78 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/glue/errors.h" +#include "core/hle/service/glue/manager.h" + +namespace Service::Glue { + +struct ARPManager::MapEntry { +    ApplicationLaunchProperty launch; +    std::vector<u8> control; +}; + +ARPManager::ARPManager() = default; + +ARPManager::~ARPManager() = default; + +ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const { +    if (title_id == 0) { +        return ERR_INVALID_PROCESS_ID; +    } + +    const auto iter = entries.find(title_id); +    if (iter == entries.end()) { +        return ERR_NOT_REGISTERED; +    } + +    return MakeResult<ApplicationLaunchProperty>(iter->second.launch); +} + +ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const { +    if (title_id == 0) { +        return ERR_INVALID_PROCESS_ID; +    } + +    const auto iter = entries.find(title_id); +    if (iter == entries.end()) { +        return ERR_NOT_REGISTERED; +    } + +    return MakeResult<std::vector<u8>>(iter->second.control); +} + +ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, +                                std::vector<u8> control) { +    if (title_id == 0) { +        return ERR_INVALID_PROCESS_ID; +    } + +    const auto iter = entries.find(title_id); +    if (iter != entries.end()) { +        return ERR_INVALID_ACCESS; +    } + +    entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)}); +    return RESULT_SUCCESS; +} + +ResultCode ARPManager::Unregister(u64 title_id) { +    if (title_id == 0) { +        return ERR_INVALID_PROCESS_ID; +    } + +    const auto iter = entries.find(title_id); +    if (iter == entries.end()) { +        return ERR_NOT_REGISTERED; +    } + +    entries.erase(iter); +    return RESULT_SUCCESS; +} + +void ARPManager::ResetAll() { +    entries.clear(); +} + +} // namespace Service::Glue diff --git a/src/core/hle/service/glue/manager.h b/src/core/hle/service/glue/manager.h new file mode 100644 index 000000000..a7f5ce3ee --- /dev/null +++ b/src/core/hle/service/glue/manager.h @@ -0,0 +1,63 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <map> +#include <vector> +#include "common/common_types.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/romfs_factory.h" +#include "core/hle/result.h" + +namespace Service::Glue { + +struct ApplicationLaunchProperty { +    u64 title_id; +    u32 version; +    FileSys::StorageId base_game_storage_id; +    FileSys::StorageId update_storage_id; +    u8 program_index; +    u8 reserved; +}; +static_assert(sizeof(ApplicationLaunchProperty) == 0x10, +              "ApplicationLaunchProperty has incorrect size."); + +// A class to manage state related to the arp:w and arp:r services, specifically the registration +// and unregistration of launch and control properties. +class ARPManager { +public: +    ARPManager(); +    ~ARPManager(); + +    // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was +    // previously registered, otherwise ERR_NOT_REGISTERED if it was never registered or +    // ERR_INVALID_PROCESS_ID if the title ID is 0. +    ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const; + +    // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to +    // the provided title ID if it was previously registered, otherwise ERR_NOT_REGISTERED if it was +    // never registered or ERR_INVALID_PROCESS_ID if the title ID is 0. +    ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const; + +    // Adds a new entry to the internal database with the provided parameters, returning +    // ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister +    // step, and ERR_INVALID_PROCESS_ID if the title ID is 0. +    ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control); + +    // Removes the registration for the provided title ID from the database, returning +    // ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the +    // title ID is 0. +    ResultCode Unregister(u64 title_id); + +    // Removes all entries from the database, always succeeds. Should only be used when resetting +    // system state. +    void ResetAll(); + +private: +    struct MapEntry; +    std::map<u64, MapEntry> entries; +}; + +} // namespace Service::Glue diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b2954eb34..beae9c510 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -19,7 +19,6 @@  #include "core/hle/service/am/am.h"  #include "core/hle/service/aoc/aoc_u.h"  #include "core/hle/service/apm/apm.h" -#include "core/hle/service/arp/arp.h"  #include "core/hle/service/audio/audio.h"  #include "core/hle/service/bcat/module.h"  #include "core/hle/service/bpc/bpc.h" @@ -33,6 +32,7 @@  #include "core/hle/service/fgm/fgm.h"  #include "core/hle/service/filesystem/filesystem.h"  #include "core/hle/service/friend/friend.h" +#include "core/hle/service/glue/glue.h"  #include "core/hle/service/grc/grc.h"  #include "core/hle/service/hid/hid.h"  #include "core/hle/service/lbl/lbl.h" @@ -207,7 +207,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,      AM::InstallInterfaces(*sm, nv_flinger);      AOC::InstallInterfaces(*sm);      APM::InstallInterfaces(*sm); -    ARP::InstallInterfaces(*sm);      Audio::InstallInterfaces(*sm);      BCAT::InstallInterfaces(*sm);      BPC::InstallInterfaces(*sm); @@ -221,6 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,      FGM::InstallInterfaces(*sm);      FileSystem::InstallInterfaces(*sm, vfs);      Friend::InstallInterfaces(*sm); +    Glue::InstallInterfaces(system);      GRC::InstallInterfaces(*sm);      HID::InstallInterfaces(*sm);      LBL::InstallInterfaces(*sm); | 
