From 1a8f5bfb8e5caf5db56be40c25b33e5781e6f1cd Mon Sep 17 00:00:00 2001 From: mailwl Date: Sat, 3 Feb 2018 00:03:40 +0300 Subject: [PATCH] Service/am: Add AppletAE service (#153) * Add AppletAE, step 1: move common interfaces to am.h * Add AppletAE, step 2 --- src/core/CMakeLists.txt | 2 + src/core/hle/service/am/am.cpp | 333 +++++++++++++++++++++++ src/core/hle/service/am/am.h | 93 +++++++ src/core/hle/service/am/applet_ae.cpp | 112 ++++++++ src/core/hle/service/am/applet_ae.h | 30 +++ src/core/hle/service/am/applet_oe.cpp | 374 +------------------------- src/core/hle/service/am/applet_oe.h | 6 - 7 files changed, 571 insertions(+), 379 deletions(-) create mode 100644 src/core/hle/service/am/applet_ae.cpp create mode 100644 src/core/hle/service/am/applet_ae.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2e32ff35b..848b17b18 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -84,6 +84,8 @@ add_library(core STATIC hle/service/acc/acc_u0.h hle/service/am/am.cpp hle/service/am/am.h + hle/service/am/applet_ae.cpp + hle/service/am/applet_ae.h hle/service/am/applet_oe.cpp hle/service/am/applet_oe.h hle/service/aoc/aoc_u.cpp diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index b6896852e..2825abd1a 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -2,14 +2,347 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_ae.h" #include "core/hle/service/am/applet_oe.h" +#include "core/hle/service/apm/apm.h" +#include "core/hle/service/nvflinger/nvflinger.h" namespace Service { namespace AM { +IWindowController::IWindowController() : ServiceFramework("IWindowController") { + static const FunctionInfo functions[] = { + {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, + {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, + }; + RegisterHandlers(functions); +} + +void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(0); +} + +void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +IAudioController::IAudioController() : ServiceFramework("IAudioController") {} + +IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {} + +IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {} + +ISelfController::ISelfController(std::shared_ptr nvflinger) + : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) { + static const FunctionInfo functions[] = { + {1, &ISelfController::LockExit, "LockExit"}, + {2, &ISelfController::UnlockExit, "UnlockExit"}, + {11, &ISelfController::SetOperationModeChangedNotification, + "SetOperationModeChangedNotification"}, + {12, &ISelfController::SetPerformanceModeChangedNotification, + "SetPerformanceModeChangedNotification"}, + {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, + {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, + {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, + {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, + }; + RegisterHandlers(functions); +} + +void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { + // Takes 3 input u8s with each field located immediately after the previous u8, these are + // bool flags. No output. + + IPC::RequestParser rp{ctx}; + + struct FocusHandlingModeParams { + u8 unknown0; + u8 unknown1; + u8 unknown2; + }; + auto flags = rp.PopRaw(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + bool flag = rp.Pop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast(flag)); +} + +void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + bool flag = rp.Pop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast(flag)); +} + +void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { + // Takes 3 input u8s with each field located immediately after the previous u8, these are + // bool flags. No output. + IPC::RequestParser rp{ctx}; + + bool enabled = rp.Pop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast(enabled)); +} + +void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { + // TODO(Subv): Find out how AM determines the display to use, for now just create the layer + // in the Default display. + u64 display_id = nvflinger->OpenDisplay("Default"); + u64 layer_id = nvflinger->CreateLayer(display_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(layer_id); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { + static const FunctionInfo functions[] = { + {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, + {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, + {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, + {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, + {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, + }; + RegisterHandlers(functions); + + event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event"); +} + +void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) { + event->Signal(); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(event); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(15); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast(FocusState::InFocus)); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast(OperationMode::Handheld)); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast(APM::PerformanceMode::Handheld)); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {} + +class IStorageAccessor final : public ServiceFramework { +public: + explicit IStorageAccessor(std::vector buffer) + : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) { + static const FunctionInfo functions[] = { + {0, &IStorageAccessor::GetSize, "GetSize"}, + {11, &IStorageAccessor::Read, "Read"}, + }; + RegisterHandlers(functions); + } + +private: + std::vector buffer; + + void GetSize(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; + + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast(buffer.size())); + + LOG_DEBUG(Service, "called"); + } + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + u64 offset = rp.Pop(); + + const auto& output_buffer = ctx.BufferDescriptorC()[0]; + + ASSERT(offset + output_buffer.Size() <= buffer.size()); + + Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); + + IPC::ResponseBuilder rb{ctx, 2}; + + rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service, "called"); + } +}; + +class IStorage final : public ServiceFramework { +public: + explicit IStorage(std::vector buffer) + : ServiceFramework("IStorage"), buffer(std::move(buffer)) { + static const FunctionInfo functions[] = { + {0, &IStorage::Open, "Open"}, + }; + RegisterHandlers(functions); + } + +private: + std::vector buffer; + + void Open(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(buffer); + + LOG_DEBUG(Service, "called"); + } +}; + +IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { + static const FunctionInfo functions[] = { + {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, + {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, + {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, + {66, &IApplicationFunctions::InitializeGamePlayRecording, "InitializeGamePlayRecording"}, + {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, + {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, + }; + RegisterHandlers(functions); +} + +void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { + constexpr u8 data[0x88] = { + 0xca, 0x97, 0x94, 0xc7, // Magic + 1, 0, 0, 0, // IsAccountSelected (bool) + 1, 0, 0, 0, // User Id (word 0) + 0, 0, 0, 0, // User Id (word 1) + 0, 0, 0, 0, // User Id (word 2) + 0, 0, 0, 0 // User Id (word 3) + }; + + std::vector buffer(data, data + sizeof(data)); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(buffer); + + LOG_DEBUG(Service, "called"); +} + +void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) { + // Takes an input u32 Result, no output. + // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. + + IPC::RequestParser rp{ctx}; + u32 result = rp.Pop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); +} + +void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(SystemLanguage::English); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); +} + +void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(0); // Unknown, seems to be ignored by official processes + + LOG_WARNING(Service, "(STUBBED) called"); +} + void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr nvflinger) { + std::make_shared(nvflinger)->InstallAsService(service_manager); std::make_shared(nvflinger)->InstallAsService(service_manager); } diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 3b8a06c1d..b603c17dd 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -7,6 +7,10 @@ #include #include "core/hle/service/service.h" +namespace Kernel { +class Event; +} + namespace Service { namespace NVFlinger { class NVFlinger; @@ -14,6 +18,95 @@ class NVFlinger; namespace AM { +// TODO: Add more languages +enum SystemLanguage { + Japanese = 0, + English = 1, +}; + +class IWindowController final : public ServiceFramework { +public: + IWindowController(); + +private: + void GetAppletResourceUserId(Kernel::HLERequestContext& ctx); + void AcquireForegroundRights(Kernel::HLERequestContext& ctx); +}; + +class IAudioController final : public ServiceFramework { +public: + IAudioController(); +}; + +class IDisplayController final : public ServiceFramework { +public: + IDisplayController(); +}; + +class IDebugFunctions final : public ServiceFramework { +public: + IDebugFunctions(); +}; + +class ISelfController final : public ServiceFramework { +public: + ISelfController(std::shared_ptr nvflinger); + +private: + void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); + void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); + void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); + void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); + void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); + void LockExit(Kernel::HLERequestContext& ctx); + void UnlockExit(Kernel::HLERequestContext& ctx); + void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); + + std::shared_ptr nvflinger; +}; + +class ICommonStateGetter final : public ServiceFramework { +public: + ICommonStateGetter(); + +private: + enum class FocusState : u8 { + InFocus = 1, + NotInFocus = 2, + }; + + enum class OperationMode : u8 { + Handheld = 0, + Docked = 1, + }; + + void GetEventHandle(Kernel::HLERequestContext& ctx); + void ReceiveMessage(Kernel::HLERequestContext& ctx); + void GetCurrentFocusState(Kernel::HLERequestContext& ctx); + void GetOperationMode(Kernel::HLERequestContext& ctx); + void GetPerformanceMode(Kernel::HLERequestContext& ctx); + + Kernel::SharedPtr event; +}; + +class ILibraryAppletCreator final : public ServiceFramework { +public: + ILibraryAppletCreator(); +}; + +class IApplicationFunctions final : public ServiceFramework { +public: + IApplicationFunctions(); + +private: + void PopLaunchParameter(Kernel::HLERequestContext& ctx); + void SetTerminateResult(Kernel::HLERequestContext& ctx); + void GetDesiredLanguage(Kernel::HLERequestContext& ctx); + void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx); + void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx); + void NotifyRunning(Kernel::HLERequestContext& ctx); +}; + /// Registers all AM services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr nvflinger); diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp new file mode 100644 index 000000000..a63fb6210 --- /dev/null +++ b/src/core/hle/service/am/applet_ae.cpp @@ -0,0 +1,112 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applet_ae.h" +#include "core/hle/service/nvflinger/nvflinger.h" + +namespace Service { +namespace AM { + +class ILibraryAppletProxy final : public ServiceFramework { +public: + ILibraryAppletProxy(std::shared_ptr nvflinger) + : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)) { + static const FunctionInfo functions[] = { + {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, + {1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"}, + {2, &ILibraryAppletProxy::GetWindowController, "GetWindowController"}, + {3, &ILibraryAppletProxy::GetAudioController, "GetAudioController"}, + {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, + {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, + {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"}, + {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, + }; + RegisterHandlers(functions); + } + +private: + void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetSelfController(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(nvflinger); + LOG_DEBUG(Service, "called"); + } + + void GetWindowController(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetAudioController(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetDisplayController(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetDebugFunctions(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); + } + + std::shared_ptr nvflinger; +}; + +void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(nvflinger); + LOG_DEBUG(Service, "called"); +} + +AppletAE::AppletAE(std::shared_ptr nvflinger) + : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)) { + static const FunctionInfo functions[] = { + {100, nullptr, "OpenSystemAppletProxy"}, + {200, &AppletAE::OpenLibraryAppletProxyOld, "OpenLibraryAppletProxyOld"}, + {201, nullptr, "OpenLibraryAppletProxy"}, + {300, nullptr, "OpenOverlayAppletProxy"}, + {350, nullptr, "OpenSystemApplicationProxy"}, + {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, + }; + RegisterHandlers(functions); +} + +} // namespace AM +} // namespace Service diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h new file mode 100644 index 000000000..38fc428fb --- /dev/null +++ b/src/core/hle/service/am/applet_ae.h @@ -0,0 +1,30 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace NVFlinger { +class NVFlinger; +} + +namespace AM { + +class AppletAE final : public ServiceFramework { +public: + AppletAE(std::shared_ptr nvflinger); + ~AppletAE() = default; + +private: + void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); + + std::shared_ptr nvflinger; +}; + +} // namespace AM +} // namespace Service diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index 15b7701e0..5aa765770 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -4,385 +4,13 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" +#include "core/hle/service/am/am.h" #include "core/hle/service/am/applet_oe.h" -#include "core/hle/service/apm/apm.h" #include "core/hle/service/nvflinger/nvflinger.h" namespace Service { namespace AM { -class IWindowController final : public ServiceFramework { -public: - IWindowController() : ServiceFramework("IWindowController") { - static const FunctionInfo functions[] = { - {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, - {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, - }; - RegisterHandlers(functions); - } - -private: - void GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.Push(0); - } - - void AcquireForegroundRights(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - } -}; - -class IAudioController final : public ServiceFramework { -public: - IAudioController() : ServiceFramework("IAudioController") {} -}; - -class IDisplayController final : public ServiceFramework { -public: - IDisplayController() : ServiceFramework("IDisplayController") {} -}; - -class IDebugFunctions final : public ServiceFramework { -public: - IDebugFunctions() : ServiceFramework("IDebugFunctions") {} -}; - -class ISelfController final : public ServiceFramework { -public: - ISelfController(std::shared_ptr nvflinger) - : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) { - static const FunctionInfo functions[] = { - {1, &ISelfController::LockExit, "LockExit"}, - {2, &ISelfController::UnlockExit, "UnlockExit"}, - {11, &ISelfController::SetOperationModeChangedNotification, - "SetOperationModeChangedNotification"}, - {12, &ISelfController::SetPerformanceModeChangedNotification, - "SetPerformanceModeChangedNotification"}, - {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, - {14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"}, - {16, &ISelfController::SetOutOfFocusSuspendingEnabled, - "SetOutOfFocusSuspendingEnabled"}, - {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, - }; - RegisterHandlers(functions); - } - -private: - void SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous u8, these are - // bool flags. No output. - - IPC::RequestParser rp{ctx}; - - struct FocusHandlingModeParams { - u8 unknown0; - u8 unknown1; - u8 unknown2; - }; - auto flags = rp.PopRaw(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - bool flag = rp.Pop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast(flag)); - } - - void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - bool flag = rp.Pop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast(flag)); - } - - void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { - // Takes 3 input u8s with each field located immediately after the previous u8, these are - // bool flags. No output. - IPC::RequestParser rp{ctx}; - - bool enabled = rp.Pop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast(enabled)); - } - - void LockExit(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void UnlockExit(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { - // TODO(Subv): Find out how AM determines the display to use, for now just create the layer - // in the Default display. - u64 display_id = nvflinger->OpenDisplay("Default"); - u64 layer_id = nvflinger->CreateLayer(display_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.Push(layer_id); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - std::shared_ptr nvflinger; -}; - -class ICommonStateGetter final : public ServiceFramework { -public: - ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { - static const FunctionInfo functions[] = { - {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, - {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, - {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, - {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, - {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, - }; - RegisterHandlers(functions); - - event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event"); - } - -private: - enum class FocusState : u8 { - InFocus = 1, - NotInFocus = 2, - }; - - enum class OperationMode : u8 { - Handheld = 0, - Docked = 1, - }; - - void GetEventHandle(Kernel::HLERequestContext& ctx) { - event->Signal(); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void ReceiveMessage(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(15); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(FocusState::InFocus)); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void GetOperationMode(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(OperationMode::Handheld)); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void GetPerformanceMode(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(APM::PerformanceMode::Handheld)); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - Kernel::SharedPtr event; -}; - -class IStorageAccessor final : public ServiceFramework { -public: - explicit IStorageAccessor(std::vector buffer) - : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) { - static const FunctionInfo functions[] = { - {0, &IStorageAccessor::GetSize, "GetSize"}, - {11, &IStorageAccessor::Read, "Read"}, - }; - RegisterHandlers(functions); - } - -private: - std::vector buffer; - - void GetSize(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4}; - - rb.Push(RESULT_SUCCESS); - rb.Push(static_cast(buffer.size())); - - LOG_DEBUG(Service, "called"); - } - - void Read(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - u64 offset = rp.Pop(); - - const auto& output_buffer = ctx.BufferDescriptorC()[0]; - - ASSERT(offset + output_buffer.Size() <= buffer.size()); - - Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); - - IPC::ResponseBuilder rb{ctx, 2}; - - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service, "called"); - } -}; - -class IStorage final : public ServiceFramework { -public: - explicit IStorage(std::vector buffer) - : ServiceFramework("IStorage"), buffer(std::move(buffer)) { - static const FunctionInfo functions[] = { - {0, &IStorage::Open, "Open"}, - }; - RegisterHandlers(functions); - } - -private: - std::vector buffer; - - void Open(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(buffer); - - LOG_DEBUG(Service, "called"); - } -}; - -class IApplicationFunctions final : public ServiceFramework { -public: - IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { - static const FunctionInfo functions[] = { - {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, - {21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"}, - {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, - {66, &IApplicationFunctions::InitializeGamePlayRecording, - "InitializeGamePlayRecording"}, - {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, - {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, - }; - RegisterHandlers(functions); - } - -private: - void PopLaunchParameter(Kernel::HLERequestContext& ctx) { - constexpr u8 data[0x88] = { - 0xca, 0x97, 0x94, 0xc7, // Magic - 1, 0, 0, 0, // IsAccountSelected (bool) - 1, 0, 0, 0, // User Id (word 0) - 0, 0, 0, 0, // User Id (word 1) - 0, 0, 0, 0, // User Id (word 2) - 0, 0, 0, 0 // User Id (word 3) - }; - - std::vector buffer(data, data + sizeof(data)); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(buffer); - - LOG_DEBUG(Service, "called"); - } - - void SetTerminateResult(Kernel::HLERequestContext& ctx) { - // Takes an input u32 Result, no output. - // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. - - IPC::RequestParser rp{ctx}; - u32 result = rp.Pop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); - } - - void GetDesiredLanguage(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); - rb.Push(SystemLanguage::English); - LOG_WARNING(Service, "(STUBBED) called"); - } - - void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); - } - - void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service, "(STUBBED) called"); - } - - void NotifyRunning(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(0); // Unknown, seems to be ignored by official processes - - LOG_WARNING(Service, "(STUBBED) called"); - } -}; - -class ILibraryAppletCreator final : public ServiceFramework { -public: - ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {} -}; - class IApplicationProxy final : public ServiceFramework { public: IApplicationProxy(std::shared_ptr nvflinger) diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 8083135c3..d2ab44c67 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -15,12 +15,6 @@ class NVFlinger; namespace AM { -// TODO: Add more languages -enum SystemLanguage { - Japanese = 0, - English = 1, -}; - class AppletOE final : public ServiceFramework { public: AppletOE(std::shared_ptr nvflinger);