Service/am: Add AppletAE service (#153)
* Add AppletAE, step 1: move common interfaces to am.h * Add AppletAE, step 2
This commit is contained in:
parent
5ad9b3e19d
commit
1a8f5bfb8e
|
@ -84,6 +84,8 @@ add_library(core STATIC
|
||||||
hle/service/acc/acc_u0.h
|
hle/service/acc/acc_u0.h
|
||||||
hle/service/am/am.cpp
|
hle/service/am/am.cpp
|
||||||
hle/service/am/am.h
|
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.cpp
|
||||||
hle/service/am/applet_oe.h
|
hle/service/am/applet_oe.h
|
||||||
hle/service/aoc/aoc_u.cpp
|
hle/service/aoc/aoc_u.cpp
|
||||||
|
|
|
@ -2,14 +2,347 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// 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/am.h"
|
||||||
|
#include "core/hle/service/am/applet_ae.h"
|
||||||
#include "core/hle/service/am/applet_oe.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 Service {
|
||||||
namespace AM {
|
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<u64>(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::NVFlinger> 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<FocusHandlingModeParams>();
|
||||||
|
|
||||||
|
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<bool>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
bool flag = rp.Pop<bool>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(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<bool>();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(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<u32>(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<u8>(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<u8>(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<u32>(APM::PerformanceMode::Handheld));
|
||||||
|
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called");
|
||||||
|
}
|
||||||
|
|
||||||
|
ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {}
|
||||||
|
|
||||||
|
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
|
||||||
|
public:
|
||||||
|
explicit IStorageAccessor(std::vector<u8> buffer)
|
||||||
|
: ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IStorageAccessor::GetSize, "GetSize"},
|
||||||
|
{11, &IStorageAccessor::Read, "Read"},
|
||||||
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<u8> buffer;
|
||||||
|
|
||||||
|
void GetSize(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.Push(static_cast<u64>(buffer.size()));
|
||||||
|
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Read(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
|
||||||
|
u64 offset = rp.Pop<u64>();
|
||||||
|
|
||||||
|
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<IStorage> {
|
||||||
|
public:
|
||||||
|
explicit IStorage(std::vector<u8> buffer)
|
||||||
|
: ServiceFramework("IStorage"), buffer(std::move(buffer)) {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IStorage::Open, "Open"},
|
||||||
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<u8> buffer;
|
||||||
|
|
||||||
|
void Open(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<AM::IStorageAccessor>(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<u8> buffer(data, data + sizeof(data));
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<AM::IStorage>(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<u32>();
|
||||||
|
|
||||||
|
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<u64>(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<u8>(0); // Unknown, seems to be ignored by official processes
|
||||||
|
|
||||||
|
LOG_WARNING(Service, "(STUBBED) called");
|
||||||
|
}
|
||||||
|
|
||||||
void InstallInterfaces(SM::ServiceManager& service_manager,
|
void InstallInterfaces(SM::ServiceManager& service_manager,
|
||||||
std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
|
std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
|
||||||
|
std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager);
|
||||||
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
|
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class Event;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace NVFlinger {
|
namespace NVFlinger {
|
||||||
class NVFlinger;
|
class NVFlinger;
|
||||||
|
@ -14,6 +18,95 @@ class NVFlinger;
|
||||||
|
|
||||||
namespace AM {
|
namespace AM {
|
||||||
|
|
||||||
|
// TODO: Add more languages
|
||||||
|
enum SystemLanguage {
|
||||||
|
Japanese = 0,
|
||||||
|
English = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
class IWindowController final : public ServiceFramework<IWindowController> {
|
||||||
|
public:
|
||||||
|
IWindowController();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetAppletResourceUserId(Kernel::HLERequestContext& ctx);
|
||||||
|
void AcquireForegroundRights(Kernel::HLERequestContext& ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
class IAudioController final : public ServiceFramework<IAudioController> {
|
||||||
|
public:
|
||||||
|
IAudioController();
|
||||||
|
};
|
||||||
|
|
||||||
|
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
||||||
|
public:
|
||||||
|
IDisplayController();
|
||||||
|
};
|
||||||
|
|
||||||
|
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
|
||||||
|
public:
|
||||||
|
IDebugFunctions();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ISelfController final : public ServiceFramework<ISelfController> {
|
||||||
|
public:
|
||||||
|
ISelfController(std::shared_ptr<NVFlinger::NVFlinger> 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::NVFlinger> nvflinger;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
||||||
|
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<Kernel::Event> event;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||||
|
public:
|
||||||
|
ILibraryAppletCreator();
|
||||||
|
};
|
||||||
|
|
||||||
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
|
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.
|
/// Registers all AM services with the specified service manager.
|
||||||
void InstallInterfaces(SM::ServiceManager& service_manager,
|
void InstallInterfaces(SM::ServiceManager& service_manager,
|
||||||
std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
|
std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
|
||||||
|
|
|
@ -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<ILibraryAppletProxy> {
|
||||||
|
public:
|
||||||
|
ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> 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<ICommonStateGetter>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetSelfController(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<ISelfController>(nvflinger);
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetWindowController(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<IWindowController>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetAudioController(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<IAudioController>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetDisplayController(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<IDisplayController>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<IDebugFunctions>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletCreator>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<IApplicationFunctions>();
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
|
||||||
|
LOG_DEBUG(Service, "called");
|
||||||
|
}
|
||||||
|
|
||||||
|
AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> 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
|
|
@ -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 <memory>
|
||||||
|
#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<AppletAE> {
|
||||||
|
public:
|
||||||
|
AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
|
||||||
|
~AppletAE() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace AM
|
||||||
|
} // namespace Service
|
|
@ -4,385 +4,13 @@
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/ipc_helpers.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/am/applet_oe.h"
|
||||||
#include "core/hle/service/apm/apm.h"
|
|
||||||
#include "core/hle/service/nvflinger/nvflinger.h"
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace AM {
|
namespace AM {
|
||||||
|
|
||||||
class IWindowController final : public ServiceFramework<IWindowController> {
|
|
||||||
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<u64>(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<IAudioController> {
|
|
||||||
public:
|
|
||||||
IAudioController() : ServiceFramework("IAudioController") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDisplayController final : public ServiceFramework<IDisplayController> {
|
|
||||||
public:
|
|
||||||
IDisplayController() : ServiceFramework("IDisplayController") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
|
|
||||||
public:
|
|
||||||
IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ISelfController final : public ServiceFramework<ISelfController> {
|
|
||||||
public:
|
|
||||||
ISelfController(std::shared_ptr<NVFlinger::NVFlinger> 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<FocusHandlingModeParams>();
|
|
||||||
|
|
||||||
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<bool>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
bool flag = rp.Pop<bool>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(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<bool>();
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(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::NVFlinger> nvflinger;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
|
|
||||||
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<u32>(15);
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called");
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.Push(static_cast<u8>(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<u8>(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<u32>(APM::PerformanceMode::Handheld));
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called");
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::Event> event;
|
|
||||||
};
|
|
||||||
|
|
||||||
class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
|
|
||||||
public:
|
|
||||||
explicit IStorageAccessor(std::vector<u8> buffer)
|
|
||||||
: ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &IStorageAccessor::GetSize, "GetSize"},
|
|
||||||
{11, &IStorageAccessor::Read, "Read"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<u8> buffer;
|
|
||||||
|
|
||||||
void GetSize(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.Push(static_cast<u64>(buffer.size()));
|
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Read(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp{ctx};
|
|
||||||
|
|
||||||
u64 offset = rp.Pop<u64>();
|
|
||||||
|
|
||||||
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<IStorage> {
|
|
||||||
public:
|
|
||||||
explicit IStorage(std::vector<u8> buffer)
|
|
||||||
: ServiceFramework("IStorage"), buffer(std::move(buffer)) {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &IStorage::Open, "Open"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<u8> buffer;
|
|
||||||
|
|
||||||
void Open(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
|
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
|
||||||
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<u8> buffer(data, data + sizeof(data));
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
|
||||||
rb.PushIpcInterface<AM::IStorage>(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<u32>();
|
|
||||||
|
|
||||||
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<u64>(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<u8>(0); // Unknown, seems to be ignored by official processes
|
|
||||||
|
|
||||||
LOG_WARNING(Service, "(STUBBED) called");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
|
||||||
public:
|
|
||||||
ILibraryAppletCreator() : ServiceFramework("ILibraryAppletCreator") {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||||
public:
|
public:
|
||||||
IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
|
IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
|
||||||
|
|
|
@ -15,12 +15,6 @@ class NVFlinger;
|
||||||
|
|
||||||
namespace AM {
|
namespace AM {
|
||||||
|
|
||||||
// TODO: Add more languages
|
|
||||||
enum SystemLanguage {
|
|
||||||
Japanese = 0,
|
|
||||||
English = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
class AppletOE final : public ServiceFramework<AppletOE> {
|
class AppletOE final : public ServiceFramework<AppletOE> {
|
||||||
public:
|
public:
|
||||||
AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
|
AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
|
||||||
|
|
Loading…
Reference in New Issue