Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,8 @@ add_library(core STATIC
hle/service/am/service/application_functions.cpp
hle/service/am/service/application_functions.h
hle/service/am/service/application_proxy.cpp
hle/service/am/service/graphics_scale_controller.h
hle/service/am/service/graphics_scaling_parameters_functions.h
hle/service/am/service/performance_functions.h
hle/service/am/service/application_proxy.h
hle/service/am/service/application_proxy_service.cpp
hle/service/am/service/application_proxy_service.h
Expand Down
1 change: 1 addition & 0 deletions src/core/hle/service/am/applet.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct Applet {
// Application functions
bool game_play_recording_supported{};
bool media_playback_state{};
bool cpu_overclock_requested{}; ///< Switch 2 IPerformanceFunctions
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
bool jit_service_launched{};
bool application_crash_report_enabled{};
Expand Down
9 changes: 8 additions & 1 deletion src/core/hle/service/am/service/application_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_
{200, &IApplicationFunctions::StubReplyZeroed, "GetLastApplicationExitReason"},
{210, D<&IApplicationFunctions::GetOperationModeRefreshEvent>, "GetOperationModeRefreshEvent (guessed)"},
{220, &IApplicationFunctions::StubReplyZeroed, "Unknown220"}, // [20.0.0+]
{230, &IApplicationFunctions::StubReplyZeroed, "Unknown230"},
{230, D<&IApplicationFunctions::IsTensorRtSupported>, "IsTensorRtSupported"},
{300, &IApplicationFunctions::StubReplyInterface, "CreateMovieWriter"}, // [19.0.0+]
{310, &IApplicationFunctions::StubReplyZeroed, "Unknown310"}, // [20.0.0+]
{320, D<&IApplicationFunctions::Unknown320>, "Unknown320"}, // [20.0.0+]
Expand Down Expand Up @@ -576,6 +576,13 @@ Result IApplicationFunctions::GetOperationModeRefreshEvent(
R_SUCCEED();
}

Result IApplicationFunctions::IsTensorRtSupported(Out<bool> out_is_supported) {
// Switch 2 hardware runs TensorRT networks (DLSS); the zeroed stub told titles it can't.
LOG_DEBUG(Service_AM, "called");
*out_is_supported = true;
R_SUCCEED();
}

Result IApplicationFunctions::Unknown320(Out<u16> out) {
// Called by Switch 2 titles during nn::oe::Initialize. It returns two bytes of data (meaning
// unknown); a reply without them left the caller reading stale message words.
Expand Down
1 change: 1 addition & 0 deletions src/core/hle/service/am/service/application_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class IApplicationFunctions final : public ServiceFramework<IApplicationFunction
Result GetHealthWarningDisappearedSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result CreateApplicationAndRequestToStart(u64 application_id);
Result GetOperationModeRefreshEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsTensorRtSupported(Out<bool> out_is_supported);
Result Unknown320(Out<u16> out);
Result Unknown321(Out<u8> out);
Result Unknown330(Out<u8> out);
Expand Down
23 changes: 16 additions & 7 deletions src/core/hle/service/am/service/application_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
#include "core/hle/service/am/service/common_state_getter.h"
#include "core/hle/service/am/service/debug_functions.h"
#include "core/hle/service/am/service/display_controller.h"
#include "core/hle/service/am/service/graphics_scale_controller.h"
#include "core/hle/service/am/service/graphics_scaling_parameters_functions.h"
#include "core/hle/service/am/service/library_applet_creator.h"
#include "core/hle/service/am/service/performance_functions.h"
#include "core/hle/service/am/service/process_winding_controller.h"
#include "core/hle/service/am/service/self_controller.h"
#include "core/hle/service/am/service/window_controller.h"
Expand All @@ -35,10 +36,11 @@ IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Appl
{10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"},
{11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
{20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"},
// Switch 2-only getters; see nx2_stub_interface.h.
{40, &IApplicationProxy::GetNx2Interface, "Nx2Getter40"},
// Switch 2-only getters; see nx2_stub_interface.h. Switchbrew leaves 40 and 60 unnamed:
// their names follow the interfaces they return.
{40, D<&IApplicationProxy::GetPerformanceFunctions>, "GetPerformanceFunctions"},
{50, &IApplicationProxy::GetNx2Interface, "Nx2Getter50"},
{60, D<&IApplicationProxy::GetGraphicsScaleController>, "GetGraphicsScaleController (Switch 2)"},
{60, D<&IApplicationProxy::GetGraphicsScalingParametersFunctions>, "GetGraphicsScalingParametersFunctions"},
{70, &IApplicationProxy::GetNx2Interface, "Nx2Getter70"},
{80, &IApplicationProxy::GetNx2Interface, "Nx2Getter80"},
{90, &IApplicationProxy::GetNx2Interface, "Nx2Getter90"},
Expand All @@ -51,10 +53,17 @@ IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Appl

IApplicationProxy::~IApplicationProxy() = default;

Result IApplicationProxy::GetGraphicsScaleController(
Out<SharedPointer<IGraphicsScaleController>> out_controller) {
Result IApplicationProxy::GetPerformanceFunctions(
Out<SharedPointer<IPerformanceFunctions>> out_functions) {
LOG_DEBUG(Service_AM, "called");
*out_controller = std::make_shared<IGraphicsScaleController>(system);
*out_functions = std::make_shared<IPerformanceFunctions>(system, m_applet);
R_SUCCEED();
}

Result IApplicationProxy::GetGraphicsScalingParametersFunctions(
Out<SharedPointer<IGraphicsScalingParametersFunctions>> out_functions) {
LOG_DEBUG(Service_AM, "called");
*out_functions = std::make_shared<IGraphicsScalingParametersFunctions>(system);
R_SUCCEED();
}

Expand Down
7 changes: 5 additions & 2 deletions src/core/hle/service/am/service/application_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ class IApplicationFunctions;
class ICommonStateGetter;
class IDebugFunctions;
class IDisplayController;
class IGraphicsScaleController;
class IGraphicsScalingParametersFunctions;
class ILibraryAppletCreator;
class IPerformanceFunctions;
class IProcessWindingController;
class ISelfController;
class IWindowController;
Expand All @@ -32,7 +33,9 @@ class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {

private:
void GetNx2Interface(HLERequestContext& ctx);
Result GetGraphicsScaleController(Out<SharedPointer<IGraphicsScaleController>> out_controller);
Result GetPerformanceFunctions(Out<SharedPointer<IPerformanceFunctions>> out_functions);
Result GetGraphicsScalingParametersFunctions(
Out<SharedPointer<IGraphicsScalingParametersFunctions>> out_functions);
Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
Result GetProcessWindingController(
Expand Down
6 changes: 3 additions & 3 deletions src/core/hle/service/am/service/application_proxy_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ IApplicationProxyService::IApplicationProxyService(Core::System& system_,
: ServiceFramework{system_, "appletOE"}, m_window_system{window_system} {
static const FunctionInfo functions[] = {
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
// Switch 2 SDKs open the proxy with command 10, same arguments.
{10, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy (Switch 2)"},
{2000, &IApplicationProxyService::StubReplyInterface, "Unknown2000"},
// Switch 2 SDKs open the proxy with OpenApplicationProxy2, same arguments.
{10, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy2"},
{2000, &IApplicationProxyService::StubReplyInterface, "OpenCompatApplicationFunctions"},
};
RegisterHandlers(functions);
}
Expand Down
8 changes: 4 additions & 4 deletions src/core/hle/service/am/service/common_state_getter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
{600, &ICommonStateGetter::StubReplyZeroed, "SetHidInputMagnificationForApplication"}, //20.0.0+
{610, D<&ICommonStateGetter::Unknown610>, "Unknown610"}, //21.0.0+
{611, D<&ICommonStateGetter::Unknown611>, "Unknown611"}, //22.0.0+
{650, &ICommonStateGetter::StubReplyZeroed, "Unknown650"},
{651, &ICommonStateGetter::StubReplyZeroed, "Unknown651"},
{650, &ICommonStateGetter::StubReplyZeroed, "BeginUsingCameraResource"},
{651, &ICommonStateGetter::StubReplyZeroed, "EndUsingCameraResource"},
{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, //11.0.0+
{910, &ICommonStateGetter::StubReplyZeroed, "GetLaunchRequiredTick"}, //17.0.0+
{1000, D<&ICommonStateGetter::BeginVrMode3d>, "BeginVrMode3d"}, //19.0.0+
Expand All @@ -89,8 +89,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
{1003, D<&ICommonStateGetter::GetVrLaboGoggleViewport>, "GetVrLaboGoggleViewport"}, //21.0.0+
{1004, D<&ICommonStateGetter::GetPanelPhysicalSizeForSpecificTitle>, "GetPanelPhysicalSizeForSpecificTitle"}, //21.0.0+
{1005, D<&ICommonStateGetter::GetPanelResolutionForSpecificTitle>, "GetPanelResolutionForSpecificTitle"}, //21.0.0+
{2000, &ICommonStateGetter::StubReplyZeroed, "Unknown2000"},
{2010, &ICommonStateGetter::StubReplyZeroed, "Unknown2010"},
{2000, &ICommonStateGetter::StubReplyZeroed, "SetRtcModeChangedMessageEnabled"},
{2010, &ICommonStateGetter::StubReplyZeroed, "GetCurrentDisplayLayoutRatio"},
};
// clang-format on

Expand Down
39 changes: 0 additions & 39 deletions src/core/hle/service/am/service/graphics_scale_controller.h

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

namespace Service::AM {

// nn::am::service::IGraphicsScalingParametersFunctions (Switch 2), returned by IApplicationProxy
// command 60. nn::oe's GetCurrentGraphicsScale reads command 10 and accepts 10, 20 or 30 (scale
// enum 0, 1, 2). Commands without a handler are auto-stubbed because the name carries the nx2:
// prefix.
class IGraphicsScalingParametersFunctions final
: public ServiceFramework<IGraphicsScalingParametersFunctions> {
public:
explicit IGraphicsScalingParametersFunctions(Core::System& system_)
: ServiceFramework{system_, "nx2:IGraphicsScalingParametersFunctions"} {
// clang-format off
static const FunctionInfo functions[] = {
{10, D<&IGraphicsScalingParametersFunctions::GetGraphicsScalingParameters>, "GetGraphicsScalingParameters"},
{1050, D<&IGraphicsScalingParametersFunctions::SetGraphicsScaleChangedNotificationEnabled>, "SetGraphicsScaleChangedNotificationEnabled"},
};
// clang-format on
RegisterHandlers(functions);
}

private:
// The reply is 12 bytes; only the first word (the scale) is known. The other two used to be
// left to the message buffer's leftovers.
Result GetGraphicsScalingParameters(Out<u32> out_scale, Out<u32> out_unknown1,
Out<u32> out_unknown2) {
LOG_WARNING(Service_AM, "(STUBBED) called, returning 10");
*out_scale = 10;
*out_unknown1 = 0;
*out_unknown2 = 0;
R_SUCCEED();
}

// 1050(bool): every title calls it at boot. The scale never changes here, so there is never a
// change message to send either way.
Result SetGraphicsScaleChangedNotificationEnabled(bool enabled) {
LOG_DEBUG(Service_AM, "called, enabled={}", enabled);
R_SUCCEED();
}
};

} // namespace Service::AM
54 changes: 54 additions & 0 deletions src/core/hle/service/am/service/performance_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <memory>
#include <mutex>

#include "common/settings.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"

namespace Service::AM {

// nn::am::service::IPerformanceFunctions (Switch 2), returned by IApplicationProxy command 40. The
// application's own request is kept on its applet (so it survives the interface being opened
// again) and read back, and Eden's CPU clock setting (Boost or Overclock) also reads as enabled.
// The request doesn't change that setting: it scales the guest clock, which would jump under a
// running title. Commands without a handler are auto-stubbed because the name carries the nx2:
// prefix.
class IPerformanceFunctions final : public ServiceFramework<IPerformanceFunctions> {
public:
explicit IPerformanceFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
: ServiceFramework{system_, "nx2:IPerformanceFunctions"}, m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IPerformanceFunctions::IsCpuOverclockEnabled>, "IsCpuOverclockEnabled"},
{1, D<&IPerformanceFunctions::SetCpuOverclockEnabled>, "SetCpuOverclockEnabled"},
};
// clang-format on
RegisterHandlers(functions);
}

private:
Result IsCpuOverclockEnabled(Out<bool> out_is_enabled) {
std::scoped_lock lk{m_applet->lock};
*out_is_enabled = m_applet->cpu_overclock_requested ||
Settings::values.cpu_clock.GetValue() != Settings::CpuClock::Normal;
LOG_DEBUG(Service_AM, "called, enabled={}", *out_is_enabled);
R_SUCCEED();
}

Result SetCpuOverclockEnabled(bool enabled) {
LOG_DEBUG(Service_AM, "called, enabled={}", enabled);
std::scoped_lock lk{m_applet->lock};
m_applet->cpu_overclock_requested = enabled;
R_SUCCEED();
}

const std::shared_ptr<Applet> m_applet;
};

} // namespace Service::AM
22 changes: 11 additions & 11 deletions src/core/hle/service/am/service/self_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
{19, D<&ISelfController::SetAlbumImageOrientation>, "SetAlbumImageOrientation"},
{20, &ISelfController::StubReplyZeroed, "SetDesirableKeyboardLayout"},
{21, &ISelfController::StubReplyZeroed, "GetScreenShotProgramId"},
{22, &ISelfController::StubReplyZeroed, "Unknown22"},
{23, &ISelfController::StubReplyZeroed, "Unknown23"},
{24, &ISelfController::StubReplyZeroed, "Unknown24"},
{22, &ISelfController::StubReplyZeroed, "GetScreenShotAcdIndex"},
{23, &ISelfController::StubReplyZeroed, "GetScreenShotApparentPlatform"},
{24, &ISelfController::StubReplyZeroed, "GetScreenShotApplicationProperty"},
{40, D<&ISelfController::CreateManagedDisplayLayer>, "CreateManagedDisplayLayer"},
{41, D<&ISelfController::IsSystemBufferSharingEnabled>, "IsSystemBufferSharingEnabled"},
{42, D<&ISelfController::GetSystemSharedLayerHandle>, "GetSystemSharedLayerHandle"},
Expand Down Expand Up @@ -83,12 +83,12 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
{230, D<&ISelfController::Unknown230>, "Unknown230"},
{240, D<&ISelfController::Unknown240>, "Unknown240"},
{1000, &ISelfController::StubReplyInterface, "GetDebugStorageChannel"},
{2000, &ISelfController::GetNx2GraphicsSystemSession, "GetGraphicsSystemSession (Switch 2, guessed)"},
{2100, &ISelfController::StubReplyZeroed, "Unknown2100"},
{2200, &ISelfController::StubReplyZeroed, "Unknown2200"},
{2300, &ISelfController::StubReplyZeroed, "Unknown2300"},
{2400, &ISelfController::StubReplyZeroed, "Unknown2400"},
{2401, &ISelfController::StubReplyZeroed, "Unknown2401"},
{2000, &ISelfController::GetGraphicsSupervisor, "GetGraphicsSupervisor"},
{2100, &ISelfController::StubReplyZeroed, "SetRecordingLayerEnabled"},
{2200, &ISelfController::StubReplyZeroed, "SetSharingLayerEnabled"},
{2300, &ISelfController::StubReplyZeroed, "SetCopyrightLayerEnabled"},
{2400, &ISelfController::StubReplyZeroed, "SetRtcScreenSharingAudioEnabled"},
{2401, &ISelfController::StubReplyZeroed, "SetStreamPlayMirroringAudioEnabled"},
{2402, &ISelfController::StubReplyZeroed, "Unknown2402"},
};
// clang-format on
Expand All @@ -100,9 +100,9 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
m_applet->library_applet_mode);
}

void ISelfController::GetNx2GraphicsSystemSession(HLERequestContext& ctx) {
void ISelfController::GetGraphicsSupervisor(HLERequestContext& ctx) {
// nn::gsv::BootWithRemoteMemory sends TIPC on the handle this returns.
LOG_WARNING(Service_AM, "(STUBBED) Switch 2 ISelfController::2000, returning a nx2:gsv session");
LOG_WARNING(Service_AM, "(STUBBED) GetGraphicsSupervisor, returning a nx2:gsv session");
ReturnRawSession(system, ctx, std::make_shared<INx2GraphicsSystemSession>(system));
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/hle/service/am/service/self_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ISelfController final : public ServiceFramework<ISelfController> {
~ISelfController() override;

private:
void GetNx2GraphicsSystemSession(HLERequestContext& ctx);
void GetGraphicsSupervisor(HLERequestContext& ctx);
Result Exit();
Result LockExit();
Result UnlockExit();
Expand Down
6 changes: 3 additions & 3 deletions src/core/hle/service/audio/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService("audrec:u", std::make_shared<IFinalOutputRecorderManager>(system), 30);
server_manager->RegisterNamedService("audren:u", std::make_shared<IAudioRendererManager>(system), 30);
// Switch 2 audio entry point (nn::audio::CreateUserClientSessionByHipc).
server_manager->RegisterNamedService("aud:u", std::make_shared<INx2AudioUserClient>(system), 30);
server_manager->RegisterNamedService("auddmg:u", std::make_shared<INx2AudioDeviceManagerService>(system), 30);
server_manager->RegisterNamedService("audsmx:u", std::make_shared<INx2AudioSoundMixerService>(system), 30);
server_manager->RegisterNamedService("aud:u", std::make_shared<IUserClientSession>(system), 30);
server_manager->RegisterNamedService("auddmg:u", std::make_shared<Devmgr::IUserSessionManager>(system), 30);
server_manager->RegisterNamedService("audsmx:u", std::make_shared<Sysmix::IUserSessionManager>(system), 30);
server_manager->RegisterNamedService("audren:a", std::make_shared<IAudioRendererManagerForApplet>(system), 30);
server_manager->RegisterNamedService("hwopus", std::make_shared<IHardwareOpusDecoderManager>(system), 25);
ServerManager::RunServer(std::move(server_manager));
Expand Down
Loading
Loading