Compare commits

..

18 Commits

Author SHA1 Message Date
lizzie ca9dc2da35 Fix license headers 2026-09-28 06:16:38 +00:00
lizzie 33e2e0cf57 2026-09-23 07:42:01
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 737535dc2b 2026-09-23 02:07:39
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie ccb257c729 2026-09-23 01:28:59
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie f9292fa4ac 2026-09-23 01:18:14
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie b5b59f2659 2026-09-22 04:33:30
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie e18e8b5995 2026-09-22 04:25:09
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 214d7772b4 2026-09-21 02:08:29
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 08585f03de 2026-09-21 02:07:30
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 4bb5ab4d83 Fix license headers 2026-09-28 06:16:25 +00:00
lizzie 6acf3c496a Fix license headers 2026-09-28 06:16:25 +00:00
lizzie c9c5e5c677 2026-09-21 00:39:13
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 86761a1892 Fix license headers 2026-09-28 06:16:25 +00:00
lizzie 261cf66e58 2026-09-20 13:20:40
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 2a991fafe9 2026-09-20 13:02:52
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie 338cf2a532 2026-09-20 12:52:02
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
lizzie e85ce56b11 Fix license headers 2026-09-28 06:16:25 +00:00
lizzie e853a577e3 2026-09-20 07:03:36
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-28 06:16:25 +00:00
473 changed files with 27160 additions and 25325 deletions
+1 -1
View File
@@ -79,7 +79,7 @@
"name": "ffmpeg",
"package": "FFmpeg",
"repo": "crueter-ci/FFmpeg",
"version": "9.0.2-1790726865-946fcce07b"
"version": "9.0.1-1788120736-bf1b838f2a"
},
"fmt": {
"hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2",
+473 -455
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+463 -440
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+457 -440
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+463 -440
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+463 -440
View File
File diff suppressed because it is too large Load Diff
+463 -440
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+463 -440
View File
File diff suppressed because it is too large Load Diff
+456 -439
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
# Design Overview
Modern game consoles require heavy power to emulate. This is why the emulator uses an approach known as HLE (High-Level-Emulation), in a nutshell: Instead of accurately emulating every subsystem that forms part of a component, emulate the resulting visible output of said interface instead.
Modern game consoles require heavy power to be emulated appropriately. This is why the emulator uses an approach known as HLE (High-Level-Emulation), in a nutshell: Instead of accurately emulating every subsystem that forms part of a component, emulate the resulting visible I/O interface instead.
For example, take a disk write, instead of emulating a proper SD card we instead use the C++ standard library for I/O. Additionally we use the abstractions provided by the `fs` service to "lie" to programs about certain SD card properties. Notably this includes making up sizes for the fake SD card, giving "realistic" values or expected outputs for a given card, and so on. And instead of writing to an actual SD card, the emulator simply writes to a file.
+1 -52
View File
@@ -1,6 +1,4 @@
# Subsystem: HLE
## HOS Kernel
# HOS Kernel
In brief, the HOS kernel is a microkernel, all services and programs run in userspace, the primary way to do communication between these is via `HIPC` (not covered here); otherwise most of the primitives reside in the forms of syscalls invoked via `svc #imm`. The kernel supports both 32-bit and 64-bit programs, and has the capacity to use 32, 36 and 39 bits of address space for spawned processes. Most of the networking stack is based off FreeBSD's network stack.
@@ -31,52 +29,3 @@ Every process keeps it's own tracking of the following structures:
The emulator willingly restricts itself to only use 4 threads (to emulate 4 cores), this is because most existing applications do not benefit greatly from the added core count, and in fact can be detrimental due to extra contention. This translates equitatively to about 4 `ArmInterface` slots for each process, these are then redirected to whatever is the last `pc` of the last thread running on the core is meant to be; proceed to run it, then when returning (due to halt or interruption), proceed to reschedule the thread.
The scheduler as-is isn't 100% faithful to the original (for example the original is cooperative and not preemptive), and has great timing variance (especially due to the fact the emulator can run in systems with wildly different timings).
## Services
Consult [SwitchBrew](https://switchbrew.org/) for per-service methods, and implementation details.
All services are instatiated implicitly using `ServiceFramework`. To register a new interface or service, you can inherit from said class, providing additionally a template parameter that references `Self`, for example:
```c++
// Follows as:
// class MyInterface [final] : public ServiceFramework<MyInterface> { ... };
// [final] is optional, but should be used whenever there is no intention of this class itself being inherited.
class IFloatingRegistrationRequest final : public ServiceFramework<IFloatingRegistrationRequest> {
public:
// ctor, you can pass extra parameters here (if so required)
explicit IFloatingRegistrationRequest(Core::System& system_)
: ServiceFramework{system_, "IFloatingRegistrationRequest"}
{}
// Must be placed after all methods are defined (or declared).
// Define here your functions and methods, please order them.
// Use FindRequestTipc for TIPC handlers.
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, nullptr, "GetSessionId"},
FunctionInfo{12, nullptr, "GetAccountId"},
FunctionInfo{13, nullptr, "GetLinkedNintendoAccountId"},
FunctionInfo{14, nullptr, "GetNickname"},
FunctionInfo{15, nullptr, "GetProfileImage"},
FunctionInfo{16, nullptr, "GetProfileLargeImage", MakeVersionGate({18,0,0})},
FunctionInfo{21, nullptr, "LoadIdTokenCache"},
FunctionInfo{100, nullptr, "RegisterUser"},
FunctionInfo{101, nullptr, "RegisterUserWithUid"},
FunctionInfo{102, nullptr, "RegisterNetworkServiceAccountAsync", MakeVersionGate({4,0,0})},
FunctionInfo{103, nullptr, "RegisterNetworkServiceAccountWithUidAsync", MakeVersionGate({4,0,0})},
FunctionInfo{110, nullptr, "SetSystemProgramIdentification"},
FunctionInfo{111, nullptr, "EnsureIdTokenCacheAsync"}
);
std::optional<FunctionInfoBase> FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key, functions);
}
};
```
Try to keep service structures local, that is, don't place them on header files if they're only going to be used by a specific service.
In each `.cpp` file that uses `D<...>/C<...>` CMIF wrapper helpers, remember to include the corresponding instancer, so you don't face linker errors:
```c++
#include "core/hle/service/cmif_serialization.h"
```
This will properly instatiate the corresponding wrappers and decompose the provided arguments in the wiring order.
+1 -1
View File
@@ -21,7 +21,7 @@ This contains documentation created by developers, build instructions, guideline
- Subsystems:
- **[Design Overview](./DesignOverview.md)**
- **[Dynarmic](./dynarmic/README.md)**
- **[Subsystem: HLE](./SubsystemHLE.md)**
- **[HOS Kernel](./HosKernel.md)**
- **[Settings](./Settings.md)**
## Policies
@@ -23,7 +23,6 @@ import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.utils.GpuDriverMetadata
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.NativeConfig
import java.io.File
@@ -147,11 +146,11 @@ class DriverViewModel : ViewModel() {
private fun wipeGameShaders(game: Game) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val userDirectory = DirectoryInitialization.userDirectory
val externalFilesDir = YuzuApplication.appContext.getExternalFilesDir(null)
?: return@withContext
val shaderDir = File(
userDirectory +
"/cache/shader/" + game.settingsName.lowercase()
externalFilesDir.absolutePath +
"/shader/" + game.settingsName.lowercase()
)
if (shaderDir.exists()) {
shaderDir.deleteRecursively()
+6 -1
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
@@ -19,6 +19,11 @@ ADSP::ADSP(Core::System& system, Sink::Sink& sink) {
}
}
void ADSP::Shutdown() {
audio_renderer->Stop();
opus_decoder->Shutdown();
}
AudioRenderer::AudioRenderer& ADSP::AudioRenderer() {
return *audio_renderer;
}
+2 -1
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
@@ -45,6 +45,7 @@ public:
explicit ADSP(Core::System& system, Sink::Sink& sink);
~ADSP() = default;
void Shutdown();
AudioRenderer::AudioRenderer& AudioRenderer();
OpusDecoder::OpusDecoder& OpusDecoder();
@@ -34,26 +34,19 @@ void AudioRenderer::Start() {
mailbox.Send(Direction::DSP, Message::InitializeOK);
if (mailbox.Receive(Direction::Host) != Message::InitializeOK) {
LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown "
"message response from ADSP!");
return;
LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown message response from ADSP!");
}
running = true;
}
void AudioRenderer::Stop() {
if (!running) {
return;
if (main_thread.joinable()) {
main_thread.request_stop();
mailbox.Send(Direction::DSP, Message::Shutdown);
if (mailbox.Receive(Direction::Host, main_thread.get_stop_token()) != Message::Shutdown) {
LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown message response from ADSP!");
}
main_thread.join();
}
mailbox.Send(Direction::DSP, Message::Shutdown);
if (mailbox.Receive(Direction::Host) != Message::Shutdown) {
LOG_ERROR(Service_Audio, "Host Audio Renderer -- Failed to receive shutdown "
"message response from ADSP!");
}
main_thread.request_stop();
main_thread.join();
for (auto& stream : streams) {
if (stream) {
stream->Stop();
@@ -61,7 +54,6 @@ void AudioRenderer::Stop() {
stream = nullptr;
}
}
running = false;
}
void AudioRenderer::Signal() {
@@ -69,13 +61,12 @@ void AudioRenderer::Signal() {
Send(Direction::DSP, Message::Render);
}
void AudioRenderer::Wait() {
auto msg = Receive(Direction::Host);
void AudioRenderer::Wait(std::stop_token stop_token) {
auto msg = mailbox.Receive(Direction::Host, stop_token);
if (msg != Message::RenderResponse) {
LOG_ERROR(Service_Audio,
"Did not receive the expected render response from the AudioRenderer! Expected "
"{}, got {}",
Message::RenderResponse, msg);
"Did not receive the expected render response from the AudioRenderer! Expected "
"{}, got {}", Message::RenderResponse, msg);
}
PostDSPClearCommandBuffer();
}
@@ -147,7 +138,9 @@ void AudioRenderer::Main(std::stop_token stop_token) {
constexpr u64 max_process_time{2'304'000ULL};
while (!stop_token.stop_requested()) {
auto msg{mailbox.Receive(Direction::DSP)};
auto msg = mailbox.Receive(Direction::DSP, stop_token);
if (stop_token.stop_requested())
break;
switch (msg) {
case Message::Shutdown:
mailbox.Send(Direction::Host, Message::Shutdown);
@@ -63,13 +63,15 @@ public:
*/
void Start();
void NotifyShutdown();
/**
* Stop the AudioRenderer.
*/
void Stop();
void Signal();
void Wait();
void Wait(std::stop_token stop_token);
void Send(Direction dir, u32 message);
u32 Receive(Direction dir);
@@ -102,8 +104,6 @@ private:
Mailbox mailbox;
/// Main thread
std::jthread main_thread{};
/// The current state
std::atomic<bool> running{};
/// Shared memory of input command buffers, set by host, read by DSP
std::array<CommandBuffer, MaxRendererSessions> command_buffers{};
/// The command lists to process
+33 -23
View File
@@ -41,19 +41,16 @@ OpusDecoder::OpusDecoder(Core::System& system_) : system{system_} {
}
OpusDecoder::~OpusDecoder() {
if (!running) {
if (main_thread.joinable()) {
// Shutdown the thread
Send(Direction::DSP, Message::Shutdown);
main_thread.request_stop();
auto msg = Receive(Direction::Host, main_thread.get_stop_token());
ASSERT_MSG(msg == Message::ShutdownOK, "Expected Opus shutdown code {}, got {}", Message::ShutdownOK, msg);
main_thread.join();
} else {
init_thread.request_stop();
return;
}
// Shutdown the thread
Send(Direction::DSP, Message::Shutdown);
auto msg = Receive(Direction::Host);
ASSERT_MSG(msg == Message::ShutdownOK, "Expected Opus shutdown code {}, got {}",
Message::ShutdownOK, msg);
main_thread.request_stop();
main_thread.join();
running = false;
}
void OpusDecoder::Send(Direction dir, u32 message) {
@@ -73,7 +70,6 @@ void OpusDecoder::Init(std::stop_token stop_token) {
return;
}
main_thread = std::jthread([this](std::stop_token st) { Main(st); });
running = true;
Send(Direction::Host, Message::StartOK);
}
@@ -82,12 +78,15 @@ void OpusDecoder::Main(std::stop_token stop_token) {
while (!stop_token.stop_requested()) {
auto msg = Receive(Direction::DSP, stop_token);
if (stop_token.stop_requested())
break;
switch (msg) {
case Shutdown:
case Message::Shutdown:
Send(Direction::Host, Message::ShutdownOK);
return;
case GetWorkBufferSize: {
case Message::GetWorkBufferSize: {
auto channel_count = static_cast<s32>(shared_memory->host_send_data[0]);
ASSERT(IsValidChannelCount(channel_count));
@@ -96,7 +95,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::GetWorkBufferSizeOK);
} break;
case InitializeDecodeObject: {
case Message::InitializeDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
@@ -113,7 +112,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::InitializeDecodeObjectOK);
} break;
case ShutdownDecodeObject: {
case Message::ShutdownDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
@@ -123,7 +122,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::ShutdownDecodeObjectOK);
} break;
case DecodeInterleaved: {
case Message::DecodeInterleaved: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
@@ -161,19 +160,19 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::DecodeInterleavedOK);
} break;
case MapMemory: {
case Message::MapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::MapMemoryOK);
} break;
case UnmapMemory: {
case Message::UnmapMemory: {
[[maybe_unused]] auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
Send(Direction::Host, Message::UnmapMemoryOK);
} break;
case GetWorkBufferSizeForMultiStream: {
case Message::GetWorkBufferSizeForMultiStream: {
auto total_stream_count = static_cast<s32>(shared_memory->host_send_data[0]);
auto stereo_stream_count = static_cast<s32>(shared_memory->host_send_data[1]);
@@ -184,7 +183,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::GetWorkBufferSizeForMultiStreamOK);
} break;
case InitializeMultiStreamDecodeObject: {
case Message::InitializeMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
auto buffer_size = shared_memory->host_send_data[1];
auto sample_rate = static_cast<s32>(shared_memory->host_send_data[2]);
@@ -211,7 +210,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::InitializeMultiStreamDecodeObjectOK);
} break;
case ShutdownMultiStreamDecodeObject: {
case Message::ShutdownMultiStreamDecodeObject: {
auto buffer = shared_memory->host_send_data[0];
[[maybe_unused]] auto buffer_size = shared_memory->host_send_data[1];
@@ -221,7 +220,7 @@ void OpusDecoder::Main(std::stop_token stop_token) {
Send(Direction::Host, Message::ShutdownMultiStreamDecodeObjectOK);
} break;
case DecodeInterleavedForMultiStream: {
case Message::DecodeInterleavedForMultiStream: {
auto start_time = system.CoreTiming().GetGlobalTimeUs();
auto buffer = shared_memory->host_send_data[0];
@@ -266,4 +265,15 @@ void OpusDecoder::Main(std::stop_token stop_token) {
}
}
void OpusDecoder::Shutdown() {
if (init_thread.joinable()) {
init_thread.request_stop();
init_thread.join(); //must explicitly wait for init to join
}
if (main_thread.joinable()) {
main_thread.request_stop();
Send(Direction::DSP, Message::Shutdown);
}
}
} // namespace AudioCore::ADSP::OpusDecoder
+3 -3
View File
@@ -57,7 +57,7 @@ public:
~OpusDecoder();
bool IsRunning() const noexcept {
return running;
return main_thread.joinable();
}
void Send(Direction dir, u32 message);
@@ -67,6 +67,8 @@ public:
shared_memory = &shared_memory_;
}
void Shutdown();
private:
/**
* Initializing thread, launched at audio_core boot to avoid blocking the main emu boot thread.
@@ -85,8 +87,6 @@ private:
std::jthread init_thread{};
/// Main thread
std::jthread main_thread{};
/// The current state
bool running{};
/// Structure shared with the host, input data set by the host before sending a mailbox message,
/// and the responses are written back by the OpusDecoder.
SharedMemory* shared_memory{};
+1
View File
@@ -33,6 +33,7 @@ void AudioCore::CreateSinks() {
void AudioCore::Shutdown() {
audio_manager->Shutdown();
adsp->Shutdown();
}
AudioManager& AudioCore::GetAudioManager() {
+2 -2
View File
@@ -17,7 +17,7 @@ AudioManager::AudioManager() {
std::unique_lock l{events.GetAudioEventLock()};
events.ClearEvents();
while (!stop_token.stop_requested()) {
const auto timed_out{events.Wait(l, std::chrono::seconds(2))};
const auto timed_out = events.Wait(l, std::chrono::seconds{2});
if (events.CheckAudioEventSet(Event::Type::Max)) {
break;
}
@@ -35,9 +35,9 @@ AudioManager::AudioManager() {
}
void AudioManager::Shutdown() {
events.SetAudioEvent(Event::Type::Max, true);
if (thread.joinable()) {
thread.request_stop();
events.SetAudioEvent(Event::Type::Max, true);
thread.join();
}
}
+1 -3
View File
@@ -39,9 +39,7 @@ class AudioManager {
public:
explicit AudioManager();
/**
* Shutdown the audio manager.
*/
/// @brief Shutdown the audio manager.
void Shutdown();
/**
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -35,7 +38,7 @@ void CircularBufferSinkInfo::Update(BehaviorInfo::ErrorInfo& error_info, OutStat
auto current_params{reinterpret_cast<CircularBufferInParameter*>(parameter.data())};
auto current_state{reinterpret_cast<CircularBufferState*>(state.data())};
if (in_use == buffer_params->in_use && !buffer_unmapped) {
if (in_use == bool(buffer_params->in_use) && !buffer_unmapped) {
error_info.error_code = ResultSuccess;
error_info.address = CpuAddr(0);
out_status.writeOffset = current_state->last_pos2;
+19 -20
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -31,10 +31,10 @@ public:
};
struct DeviceInParameter {
/* 0x000 */ char name[0x100];
/* 0x000 */ u8 name[0x100];
/* 0x100 */ u32 input_count;
/* 0x104 */ std::array<s8, MaxChannels> inputs;
/* 0x10A */ char unk10A[0x1];
/* 0x10A */ u8 unk10A[0x1];
/* 0x10B */ bool downmix_enabled;
/* 0x10C */ std::array<f32, 4> downmix_coeff;
};
@@ -43,7 +43,7 @@ public:
struct DeviceState {
/* 0x00 */ UpsamplerInfo* upsampler_info;
/* 0x08 */ std::array<Common::FixedPoint<16, 16>, 4> downmix_coeff;
/* 0x18 */ char unk18[0x18];
/* 0x18 */ u8 unk18[0x18];
};
static_assert(sizeof(DeviceState) == 0x30, "DeviceState has the wrong size!");
@@ -55,8 +55,8 @@ public:
/* 0x14 */ u32 previous_pos;
/* 0x18 */ SampleFormat format;
/* 0x1C */ std::array<s8, MaxChannels> inputs;
/* 0x22 */ bool in_use;
/* 0x23 */ char unk23[0x5];
/* 0x22 */ u8 in_use;
/* 0x23 */ u8 unk23[0x5];
};
static_assert(sizeof(CircularBufferInParameter) == 0x28,
"CircularBufferInParameter has the wrong size!");
@@ -65,16 +65,16 @@ public:
/* 0x00 */ u32 last_pos2;
/* 0x04 */ s32 current_pos;
/* 0x08 */ u32 last_pos;
/* 0x0C */ char unk0C[0x4];
/* 0x0C */ u8 unk0C[0x4];
/* 0x10 */ AddressInfo address_info;
};
static_assert(sizeof(CircularBufferState) == 0x30, "CircularBufferState has the wrong size!");
struct InParameter {
/* 0x000 */ Type type;
/* 0x001 */ bool in_use;
/* 0x001 */ u8 in_use;
/* 0x004 */ u32 node_id;
/* 0x008 */ char unk08[0x18];
/* 0x008 */ u8 unk08[0x18];
union {
/* 0x020 */ DeviceInParameter device;
/* 0x020 */ CircularBufferInParameter circular_buffer;
@@ -84,7 +84,7 @@ public:
struct OutStatus {
/* 0x00 */ u32 writeOffset;
/* 0x04 */ char unk04[0x1C];
/* 0x04 */ u8 unk04[0x1C];
}; // size == 0x20
static_assert(sizeof(OutStatus) == 0x20, "SinkInfoBase::OutStatus has the wrong size!");
@@ -162,19 +162,18 @@ public:
u8* GetParameter();
protected:
/// Type of this sink
Type type{Type::Invalid};
/// Is this sink in use?
bool in_use{};
/// Is this sink's buffer unmapped? Circular only
bool buffer_unmapped{};
/// Node id for this sink
u32 node_id{};
/// State buffer for this sink
std::array<u8, (std::max)(sizeof(DeviceState), sizeof(CircularBufferState))> state{};
/// Parameter buffer for this sink
std::array<u8, (std::max)(sizeof(DeviceInParameter), sizeof(CircularBufferInParameter))>
parameter{};
std::array<u8, (std::max)(sizeof(DeviceInParameter), sizeof(CircularBufferInParameter))> parameter{};
/// Type of this sink
Type type{Type::Invalid};
/// Node id for this sink
u32 node_id{};
/// Is this sink in use?
bool in_use : 1 = false;
/// Is this sink's buffer unmapped? Circular only
bool buffer_unmapped : 1 = false;
};
} // namespace AudioCore::Renderer
+14 -14
View File
@@ -100,8 +100,9 @@ u64 System::GetWorkBufferSize(const AudioRendererParameterInternal& params) {
}
System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
: core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()},
adsp_rendered_event{adsp_rendered_event_} {}
: core{core_}
, adsp_rendered_event{adsp_rendered_event_}
{}
Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
@@ -406,7 +407,7 @@ void System::Finalize() {
return;
}
if (active) {
if (IsActive()) {
Stop();
}
@@ -433,14 +434,12 @@ void System::Start() {
std::scoped_lock l{lock};
frames_elapsed = 0;
state = State::Started;
active = true;
}
void System::Stop() {
{
std::scoped_lock l{lock};
state = State::Stopped;
active = false;
}
if (execution_mode == ExecutionMode::Auto) {
@@ -480,7 +479,7 @@ Result System::Update(std::span<const u8> input, std::span<u8> performance, std:
return result;
}
result = info_updater.UpdateEffects(effect_context, active, memory_pool_workbuffer,
result = info_updater.UpdateEffects(effect_context, IsActive(), memory_pool_workbuffer,
memory_pool_count);
if (result.IsError()) {
LOG_ERROR(Service_Audio, "Failed to update Effects!");
@@ -582,16 +581,16 @@ u32 System::GetRenderingDevice() const {
}
bool System::IsActive() const {
return active;
return state == State::Started;
}
void System::SendCommandToDsp() {
std::scoped_lock l{lock};
if (initialized) {
if (active) {
if (IsActive()) {
terminate_event.Reset();
const auto remaining_command_count{audio_renderer.GetRemainCommandCount(session_id)};
const auto remaining_command_count = core.AudioCore().ADSP().AudioRenderer().GetRemainCommandCount(session_id);
u64 command_size{0};
if (remaining_command_count) {
@@ -618,16 +617,17 @@ void System::SendCommandToDsp() {
auto time_limit{
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, process_handle,
reset_command_buffers);
core.AudioCore().ADSP().AudioRenderer().SetCommandBuffer(session_id,
translated_addr, command_size,
time_limit, applet_resource_user_id,
process_handle, reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {
adsp_rendered_event->Signal(core.Kernel());
}
} else {
audio_renderer.ClearRemainCommandCount(session_id);
core.AudioCore().ADSP().AudioRenderer().ClearRemainCommandCount(session_id);
terminate_event.Set();
}
}
@@ -738,7 +738,7 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
const auto end_time{core.CoreTiming().GetGlobalTimeNs().count()};
total_ticks_elapsed += end_time - start_time;
num_command_lists_generated++;
render_start_tick = audio_renderer.GetRenderingStartTick(session_id);
render_start_tick = core.AudioCore().ADSP().AudioRenderer().GetRenderingStartTick(session_id);
frames_elapsed++;
return command_buffer.size;
+3 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -219,8 +222,6 @@ public:
private:
/// Core system
Core::System& core;
/// Reference to the ADSP's AudioRenderer for communication
::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
/// Is this system initialized?
bool initialized{};
/// Is this system currently active?
+27 -30
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -11,73 +11,70 @@
#include "audio_core/renderer/system_manager.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/core_timing.h"
namespace AudioCore::Renderer {
SystemManager::SystemManager(Core::System& core_)
: core{core_}, audio_renderer{core.AudioCore().ADSP().AudioRenderer()} {}
: core{core_}
{
}
SystemManager::~SystemManager() {
Stop();
}
void SystemManager::InitializeUnsafe() {
if (!active) {
active = true;
audio_renderer.Start();
thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("AudioRenderSystemManager");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
while (active && !stop_token.stop_requested()) {
if (!thread.joinable()) {
core.AudioCore().ADSP().AudioRenderer().Start();
thread = core.Kernel().RunOnHostCoreThread("AudioRenderSystemManager", [this]() {
auto& audio_renderer = core.AudioCore().ADSP().AudioRenderer();
auto const stop_token = thread.get_stop_token();
while (!stop_token.stop_requested()) {
{
std::scoped_lock l{mutex1};
std::scoped_lock lk{mutex};
for (auto system : systems)
system->SendCommandToDsp();
}
audio_renderer.Signal();
audio_renderer.Wait();
audio_renderer.Wait(stop_token);
}
});
}
}
void SystemManager::Stop() {
if (active) {
active = false;
core.AudioCore().ADSP().AudioRenderer().Stop();
if (thread.joinable()) {
thread.request_stop();
thread.join();
audio_renderer.Stop();
}
}
bool SystemManager::Add(System& system_) {
std::scoped_lock l2{mutex2};
if (systems.size() + 1 > MaxRendererSessions) {
std::scoped_lock lk{mutex};
if (systems.size() >= MaxRendererSessions) {
LOG_ERROR(Service_Audio, "Maximum AudioRenderer Systems active, cannot add more!");
return false;
}
{
std::scoped_lock l{mutex1};
if (systems.empty())
InitializeUnsafe();
}
systems.push_back(&system_);
if (!systems.empty()) {
InitializeUnsafe();
}
return true;
}
bool SystemManager::Remove(System& system_) {
std::scoped_lock l2{mutex2};
{
std::scoped_lock l{mutex1};
if (systems.remove(&system_) == 0) {
LOG_ERROR(Service_Audio, "Failed to remove a render system, it was not found in the list!");
return false;
}
std::scoped_lock lk{mutex};
if (systems.remove(&system_) == 0) {
LOG_ERROR(Service_Audio, "Failed to remove a render system, it was not found in the list!");
return false;
}
if (systems.empty())
if (systems.empty()) {
Stop();
}
return true;
}
+3 -9
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -75,14 +75,8 @@ private:
std::list<System*> systems{};
/// Main worker thread for generating command lists
std::jthread thread;
/// Mutex for the systems
std::mutex mutex1{};
/// Mutex for adding/removing systems
std::mutex mutex2{};
/// Is the system manager thread active?
std::atomic<bool> active{};
/// Reference to the ADSP's AudioRenderer for communication
::AudioCore::ADSP::AudioRenderer::AudioRenderer& audio_renderer;
/// Mutex for the reading and adding/removing systems
std::mutex mutex{};
};
} // namespace AudioCore::Renderer
+7 -7
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -109,12 +109,6 @@ private:
if (read_index == producer.index.load(std::memory_order::acquire)) {
return false;
}
} else if constexpr (Mode == PopMode::Wait) {
// Wait until the queue is not empty.
std::unique_lock lock{consumer.cv_mutex};
consumer.cv.wait(lock, [this, read_index] {
return read_index != producer.index.load(std::memory_order::acquire);
});
} else if constexpr (Mode == PopMode::WaitWithStopToken) {
// Wait until the queue is not empty.
std::unique_lock lock{consumer.cv_mutex};
@@ -124,6 +118,12 @@ private:
if (stop_token.stop_requested()) {
return false;
}
} else if constexpr (Mode == PopMode::Wait) {
// Wait until the queue is not empty.
std::unique_lock lock{consumer.cv_mutex};
consumer.cv.wait(lock, [this, read_index] {
return read_index != producer.index.load(std::memory_order::acquire);
});
} else {
static_assert(Mode < PopMode::Count, "Invalid PopMode.");
}
+1 -1
View File
@@ -150,7 +150,7 @@ ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, Scale
ENUM(AntiAliasing, None, Fxaa, Smaa);
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
ENUM(ConsoleMode, Handheld, Docked);
ENUM(AppletMode, HLE, LLE, Disabled);
ENUM(AppletMode, HLE, LLE);
ENUM(SpirvOptimizeMode, Never, OnLoad, Always);
ENUM(GpuClock, Normal, Boost, Overclock)
ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
+69 -1
View File
@@ -444,18 +444,28 @@ add_library(core STATIC
hle/service/am/process_creation.h
hle/service/am/process_holder.cpp
hle/service/am/process_holder.h
hle/service/am/service/all_system_applet_proxies_service.cpp
hle/service/am/service/all_system_applet_proxies_service.h
hle/service/am/service/applet_common_functions.cpp
hle/service/am/service/applet_common_functions.h
hle/service/am/service/application_accessor.cpp
hle/service/am/service/application_accessor.h
hle/service/am/service/application_creator.cpp
hle/service/am/service/application_creator.h
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/application_proxy.h
hle/service/am/service/application_proxy_service.cpp
hle/service/am/service/application_proxy_service.h
hle/service/am/service/audio_controller.cpp
hle/service/am/service/audio_controller.h
hle/service/am/service/common_state_getter.cpp
hle/service/am/service/common_state_getter.h
hle/service/am/service/cradle_firmware_updater.cpp
hle/service/am/service/cradle_firmware_updater.h
hle/service/am/service/debug_functions.cpp
hle/service/am/service/debug_functions.h
hle/service/am/service/display_controller.cpp
hle/service/am/service/display_controller.h
hle/service/am/service/global_state_controller.cpp
@@ -464,14 +474,28 @@ add_library(core STATIC
hle/service/am/service/home_menu_functions.h
hle/service/am/service/library_applet_accessor.cpp
hle/service/am/service/library_applet_accessor.h
hle/service/am/service/library_applet_creator.cpp
hle/service/am/service/library_applet_creator.h
hle/service/am/service/library_applet_proxy.cpp
hle/service/am/service/library_applet_proxy.h
hle/service/am/service/library_applet_self_accessor.cpp
hle/service/am/service/library_applet_self_accessor.h
hle/service/am/service/lock_accessor.cpp
hle/service/am/service/lock_accessor.h
hle/service/am/service/overlay_functions.cpp
hle/service/am/service/overlay_functions.h
hle/service/am/service/overlay_applet_proxy.cpp
hle/service/am/service/overlay_applet_proxy.h
hle/service/am/service/process_winding_controller.cpp
hle/service/am/service/process_winding_controller.h
hle/service/am/service/self_controller.cpp
hle/service/am/service/self_controller.h
hle/service/am/service/storage.cpp
hle/service/am/service/storage.h
hle/service/am/service/storage_accessor.cpp
hle/service/am/service/storage_accessor.h
hle/service/am/service/system_applet_proxy.cpp
hle/service/am/service/system_applet_proxy.h
hle/service/am/service/window_controller.cpp
hle/service/am/service/window_controller.h
hle/service/am/window_system.cpp
@@ -556,8 +580,20 @@ add_library(core STATIC
hle/service/btdrv/btdrv.h
hle/service/btm/btm.cpp
hle/service/btm/btm.h
hle/service/btm/btm_debug.cpp
hle/service/btm/btm_debug.h
hle/service/btm/btm_system.cpp
hle/service/btm/btm_system.h
hle/service/btm/btm_system_core.cpp
hle/service/btm/btm_system_core.h
hle/service/btm/btm_user.cpp
hle/service/btm/btm_user.h
hle/service/btm/btm_user_core.cpp
hle/service/btm/btm_user_core.h
hle/service/caps/caps.cpp
hle/service/caps/caps.h
hle/service/caps/caps_a.cpp
hle/service/caps/caps_a.h
hle/service/caps/caps_c.cpp
hle/service/caps/caps_c.h
hle/service/caps/caps_manager.cpp
@@ -582,6 +618,10 @@ add_library(core STATIC
hle/service/eupld/eupld.h
hle/service/fatal/fatal.cpp
hle/service/fatal/fatal.h
hle/service/fatal/fatal_p.cpp
hle/service/fatal/fatal_p.h
hle/service/fatal/fatal_u.cpp
hle/service/fatal/fatal_u.h
hle/service/fgm/fgm.cpp
hle/service/fgm/fgm.h
hle/service/filesystem/filesystem.cpp
@@ -613,6 +653,8 @@ add_library(core STATIC
hle/service/filesystem/save_data_controller.h
hle/service/friend/friend.cpp
hle/service/friend/friend.h
hle/service/friend/friend_interface.cpp
hle/service/friend/friend_interface.h
hle/service/glue/arp.cpp
hle/service/glue/arp.h
hle/service/glue/bgtc.cpp
@@ -681,6 +723,8 @@ add_library(core STATIC
hle/service/ldn/monitor_service.h
hle/service/ldn/sf_monitor_service.cpp
hle/service/ldn/sf_monitor_service.h
hle/service/ldn/sf_service.cpp
hle/service/ldn/sf_service.h
hle/service/ldn/sf_service_monitor.cpp
hle/service/ldn/sf_service_monitor.h
hle/service/ldn/system_local_communication_service.cpp
@@ -869,6 +913,8 @@ add_library(core STATIC
hle/service/olsc/native_handle_holder.h
hle/service/olsc/olsc_service_for_application.cpp
hle/service/olsc/olsc_service_for_application.h
hle/service/olsc/olsc_service_for_system_service.cpp
hle/service/olsc/olsc_service_for_system_service.h
hle/service/olsc/olsc.cpp
hle/service/olsc/olsc.h
hle/service/olsc/remote_storage_controller.cpp
@@ -898,8 +944,14 @@ add_library(core STATIC
hle/service/os/process.h
hle/service/pcie/pcie.cpp
hle/service/pcie/pcie.h
hle/service/pctl/parental_control_service_factory.cpp
hle/service/pctl/parental_control_service_factory.h
hle/service/pctl/parental_control_service.cpp
hle/service/pctl/parental_control_service.h
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl.h
hle/service/pctl/pctl_results.h
hle/service/pctl/pctl_types.h
hle/service/pcv/pcv.cpp
hle/service/pcv/pcv.h
hle/service/pm/pm.cpp
@@ -909,8 +961,18 @@ add_library(core STATIC
hle/service/psc/ovln/ovln_types.h
hle/service/psc/ovln/receiver_service.cpp
hle/service/psc/ovln/receiver_service.h
hle/service/psc/ovln/receiver.cpp
hle/service/psc/ovln/receiver.h
hle/service/psc/ovln/sender_service.cpp
hle/service/psc/ovln/sender_service.h
hle/service/psc/ovln/sender.cpp
hle/service/psc/ovln/sender.h
hle/service/psc/pm_control.cpp
hle/service/psc/pm_control.h
hle/service/psc/pm_module.cpp
hle/service/psc/pm_module.h
hle/service/psc/pm_service.cpp
hle/service/psc/pm_service.h
hle/service/psc/psc.cpp
hle/service/psc/psc.h
hle/service/psc/time/alarms.cpp
@@ -961,6 +1023,10 @@ add_library(core STATIC
hle/service/ptm/ts.h
hle/service/ro/ro.cpp
hle/service/ro/ro.h
hle/service/ro/ro_nro_utils.cpp
hle/service/ro/ro_nro_utils.h
hle/service/ro/ro_results.h
hle/service/ro/ro_types.h
hle/service/server_manager.cpp
hle/service/server_manager.h
hle/service/service.cpp
@@ -989,6 +1055,8 @@ add_library(core STATIC
hle/service/set/system_settings_server.h
hle/service/sm/sm.cpp
hle/service/sm/sm.h
hle/service/sm/sm_controller.cpp
hle/service/sm/sm_controller.h
hle/service/sockets/bsd.cpp
hle/service/sockets/bsd.h
hle/service/sockets/nsd.cpp
@@ -1154,7 +1222,7 @@ target_link_libraries(core PRIVATE
RenderDoc::API
ZLIB::ZLIB)
target_link_libraries(core PUBLIC httplib::httplib zstd::zstd frozen::frozen-headers)
target_link_libraries(core PUBLIC httplib::httplib zstd::zstd)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE)
+45 -23
View File
@@ -110,8 +110,13 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{kernel}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
: kernel{system}
, fs_controller{system}
, hid_core{kernel}
, cpu_manager{system}
, reporter{system}
, profile_manager{}
{}
u64 program_id;
@@ -124,6 +129,12 @@ struct System::Impl {
core_timing.SetMulticore(is_multicore);
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
applet_manager.emplace(system);
frontend_applets.emplace(system);
apm_controller.emplace(core_timing);
arp_manager.emplace();
profile_manager.emplace();
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
@@ -133,7 +144,7 @@ struct System::Impl {
}
// Create default implementations of applets if one is not provided.
frontend_applets.SetDefaultAppletsIfMissing();
frontend_applets->SetDefaultAppletsIfMissing();
auto const is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
@@ -376,7 +387,7 @@ struct System::Impl {
// Register with applet manager
// All threads are started, begin main process execution, now that we're in the clear
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params);
applet_manager->CreateAndInsertByFrontendAppletParameters(std::move(process), params);
if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) {
@@ -428,13 +439,27 @@ struct System::Impl {
core_timing.SyncPause(false);
Network::CancelPendingSocketOperations();
kernel.SuspendEmulation(true);
kernel.CloseServices();
kernel.ShutdownCores();
// Notify services helpers of shutdown
audio_core->Shutdown();
// Wait for threads/services to join
kernel.CloseServices();
// service shutdown
services.reset();
service_manager.reset();
frontend_applets.reset();
applet_manager.reset();
apm_controller.reset();
arp_manager.reset();
profile_manager.reset();
fs_controller.Reset();
cheat_engine.reset();
core_timing.ClearPendingEvents();
core_timing.Reset();
app_loader.reset();
audio_core.reset();
gpu_core.reset();
@@ -451,9 +476,6 @@ struct System::Impl {
room_member->SendGameInfo(game_info);
}
// Reset all glue registrations
arp_manager.ResetAll();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -482,13 +504,13 @@ struct System::Impl {
CpuManager cpu_manager;
Reporter reporter;
/// Applets
Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
std::optional<Service::AM::AppletManager> applet_manager;
std::optional<Service::AM::Frontend::FrontendAppletHolder> frontend_applets;
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
std::optional<Service::APM::Controller> apm_controller;
/// Service State
Service::Glue::ARPManager arp_manager;
Service::Account::ProfileManager profile_manager;
std::optional<Service::Glue::ARPManager> arp_manager;
std::optional<Service::Account::ProfileManager> profile_manager;
/// Network instance
Network::NetworkInstance network_instance;
Core::SpeedLimiter speed_limiter;
@@ -815,19 +837,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
}
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
impl->frontend_applets->SetFrontendAppletSet(std::move(set));
}
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
return impl->frontend_applets;
return *impl->frontend_applets;
}
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets;
return *impl->frontend_applets;
}
Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
return *impl->applet_manager;
}
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -868,27 +890,27 @@ const Reporter& System::GetReporter() const {
}
Service::Glue::ARPManager& System::GetARPManager() {
return impl->arp_manager;
return *impl->arp_manager;
}
const Service::Glue::ARPManager& System::GetARPManager() const {
return impl->arp_manager;
return *impl->arp_manager;
}
Service::APM::Controller& System::GetAPMController() {
return impl->apm_controller;
return *impl->apm_controller;
}
const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller;
return *impl->apm_controller;
}
Service::Account::ProfileManager& System::GetProfileManager() {
return impl->profile_manager;
return *impl->profile_manager;
}
const Service::Account::ProfileManager& System::GetProfileManager() const {
return impl->profile_manager;
return *impl->profile_manager;
}
void System::SetExitLocked(bool locked) {
+2 -2
View File
@@ -304,10 +304,10 @@ std::optional<s64> CoreTiming::Advance() {
void CoreTiming::Reset() {
paused = true;
pause_event.Set();
event.Set();
if (timer_thread.joinable()) {
timer_thread.request_stop();
pause_event.Set();
event.Set();
timer_thread.join();
}
has_started = false;
@@ -72,11 +72,9 @@ void GlobalSchedulerContext::UnregisterDummyThreadForWakeup(KThread* thread) noe
void GlobalSchedulerContext::WakeupWaitingDummyThreads(KernelCore& kernel) noexcept {
ASSERT(this->IsLocked());
if (m_woken_dummy_threads.size() > 0) {
for (auto* thread : m_woken_dummy_threads)
thread->DummyThreadEndWait(kernel);
m_woken_dummy_threads.clear();
}
for (auto* thread : m_woken_dummy_threads)
thread->DummyThreadEndWait(kernel);
m_woken_dummy_threads.clear();
}
} // namespace Kernel
-1
View File
@@ -59,7 +59,6 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* t
KThread* cur_child = nullptr;
{
KScopedLightLock proc_lk(process->GetListLock());
auto& thread_list = process->GetThreadList();
for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
+4 -10
View File
@@ -1236,18 +1236,13 @@ namespace Kernel {
KScopedSchedulerLock sl{kernel};
// Determine if this is the first termination request.
const bool first_request = [&]() -> bool {
// Perform an atomic compare-and-swap from false to true.
bool expected = false;
return m_termination_requested.compare_exchange_strong(expected, true);
}();
// Perform an atomic compare-and-swap from false to true.
bool expected = false;
// If this is the first request, start termination procedure.
if (first_request) {
if (m_termination_requested.compare_exchange_strong(expected, true)) {
// If the thread is in initialized state, just change state to terminated.
if (this->GetState() == ThreadState::Initialized) {
m_thread_state = ThreadState::Terminated;
return ThreadState::Terminated;
return m_thread_state = ThreadState::Terminated;
}
// Register the terminating dpc.
@@ -1281,7 +1276,6 @@ namespace Kernel {
m_wait_queue->CancelWait(kernel, this, ResultTerminationRequested, true);
}
}
return this->GetState();
}
+34 -5
View File
@@ -4,7 +4,9 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include "common/assert.h"
#include "common/thread.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_worker_task.h"
@@ -26,7 +28,33 @@ void KWorkerTask::DoWorkerTask(KernelCore& kernel) {
}
}
KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "KWorkerTaskManager") {}
KWorkerTaskManager::KWorkerTaskManager(KernelCore& kernel) {
m_waiting_thread = std::jthread([&kernel, this](std::stop_token stop_token) {
Common::SetCurrentThreadName("KWorkerManager");
while (!stop_token.stop_requested()) {
KWorkerTask* t;
{
std::unique_lock lk{m_task_mutex};
m_task_cv.wait(lk, m_waiting_thread.get_stop_token(), [&]() {
return !m_task_queue.empty();
});
if (stop_token.stop_requested())
break;
t = m_task_queue.back();
m_task_queue.pop_back();
}
t->DoWorkerTask(kernel);
}
});
}
KWorkerTaskManager::~KWorkerTaskManager() {
if (m_waiting_thread.joinable()) {
m_waiting_thread.request_stop();
m_task_cv.notify_one();
m_waiting_thread.join();
}
}
void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) {
ASSERT(type <= WorkerType::Count);
@@ -35,10 +63,11 @@ void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTas
void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) {
KScopedSchedulerLock sl(kernel);
m_waiting_thread.QueueWork([&kernel, task]() {
// Do the task.
task->DoWorkerTask(kernel);
});
{
std::scoped_lock lk{m_task_mutex};
m_task_queue.emplace_back(task);
}
m_task_cv.notify_one();
}
} // namespace Kernel
+11 -4
View File
@@ -1,8 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <condition_variable>
#include <thread>
#include "common/common_types.h"
#include "common/thread_worker.h"
@@ -18,15 +23,17 @@ public:
Count,
};
KWorkerTaskManager();
KWorkerTaskManager(KernelCore& kernel);
~KWorkerTaskManager();
static void AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task);
private:
void AddTask(KernelCore& kernel, KWorkerTask* task);
std::jthread m_waiting_thread;
private:
Common::ThreadWorker m_waiting_thread;
std::mutex m_task_mutex;
std::condition_variable_any m_task_cv;
std::vector<KWorkerTask*> m_task_queue;
};
} // namespace Kernel
+17 -12
View File
@@ -80,7 +80,10 @@ struct KernelCore::Impl {
// so it will be statically given a TLS slot anyways.
static inline thread_local ThreadLocalData tls_data = {};
explicit Impl(Core::System& system_, KernelCore& kernel_) : system{system_} {
explicit Impl(Core::System& system_, KernelCore& kernel_)
: worker_task_manager{kernel_}
, system{system_}
{
tls_data.lock = true;
}
@@ -967,12 +970,16 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
return *impl->hardware_timer;
}
KAutoObjectWithListContainer& KernelCore::ObjectListContainer() {
return *impl->global_object_list_container;
KAutoObjectWithListContainer* KernelCore::ObjectListContainer() {
if (!impl->global_object_list_container)
return nullptr;
return std::addressof(*impl->global_object_list_container);
}
const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
return *impl->global_object_list_container;
const KAutoObjectWithListContainer* KernelCore::ObjectListContainer() const {
if (!impl->global_object_list_container)
return nullptr;
return std::addressof(*impl->global_object_list_container);
}
void KernelCore::PrepareReschedule(std::size_t id) {
@@ -1001,16 +1008,10 @@ void KernelCore::UnregisterInUseObject(KAutoObject* object) {
void KernelCore::RunServer(std::unique_ptr<Service::ServerManager>&& server_manager) {
auto* manager = server_manager.get();
{
if (!impl->is_shutting_down) {
std::scoped_lock lk{impl->server_lock};
if (impl->is_shutting_down) {
return;
}
impl->server_managers.emplace_back(std::move(server_manager));
}
manager->LoopProcess();
}
@@ -1255,6 +1256,10 @@ void KernelCore::SuspendEmulation(bool suspended) {
}
void KernelCore::ShutdownCores() {
// Notify shutdown (pre-emptively)
for (auto& sm : impl->server_managers) {
sm->NotifyShutdown();
}
impl->TerminateAllProcesses();
KScopedSchedulerLock lk{*this};
for (auto* thread : impl->shutdown_threads)
+2 -3
View File
@@ -175,9 +175,8 @@ public:
/// Stops execution of 'id' core, in order to reschedule a new thread.
void PrepareReschedule(std::size_t id);
KAutoObjectWithListContainer& ObjectListContainer();
const KAutoObjectWithListContainer& ObjectListContainer() const;
KAutoObjectWithListContainer* ObjectListContainer();
const KAutoObjectWithListContainer* ObjectListContainer() const;
/// Registers all kernel objects with the global emulation state, this is purely for tracking
/// leaks after emulation has been shutdown.
+4 -3
View File
@@ -151,7 +151,8 @@ public:
const bool is_initialized = this->IsInitialized();
uintptr_t arg = 0;
if (is_initialized) {
kernel.ObjectListContainer().Unregister(this);
if (auto const olc = kernel.ObjectListContainer(); olc)
olc->Unregister(this);
arg = this->GetPostDestroyArgument();
this->Finalize(kernel);
}
@@ -175,7 +176,7 @@ public:
public:
static void InitializeSlabHeap(KernelCore& kernel, void* memory, size_t memory_size) {
kernel.SlabHeap<Derived>().Initialize(memory, memory_size);
kernel.ObjectListContainer().Initialize();
kernel.ObjectListContainer()->Initialize();
}
static Derived* Create(KernelCore& kernel) {
@@ -186,7 +187,7 @@ public:
}
static void Register(KernelCore& kernel, Derived* obj) {
return kernel.ObjectListContainer().Register(obj);
return kernel.ObjectListContainer()->Register(obj);
}
static size_t GetObjectSize(KernelCore& kernel) {
File diff suppressed because it is too large Load Diff
+64
View File
@@ -14,6 +14,70 @@ namespace Service::Account {
class ProfileManager;
class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
explicit Interface(std::shared_ptr<Module> module_,
std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_,
const char* name);
~Interface() override;
void GetUserCount(HLERequestContext& ctx);
void GetUserExistence(HLERequestContext& ctx);
void ListAllUsers(HLERequestContext& ctx);
void ListOpenUsers(HLERequestContext& ctx);
void GetLastOpenedUser(HLERequestContext& ctx);
void GetProfile(HLERequestContext& ctx);
void InitializeApplicationInfo(HLERequestContext& ctx);
void InitializeApplicationInfoRestricted(HLERequestContext& ctx);
void GetBaasAccountManagerForApplication(HLERequestContext& ctx);
void IsUserRegistrationRequestPermitted(HLERequestContext& ctx);
void TrySelectUserWithoutInteractionDeprecated(HLERequestContext& ctx);
void TrySelectUserWithoutInteraction(HLERequestContext& ctx);
void IsUserAccountSwitchLocked(HLERequestContext& ctx);
void InitializeApplicationInfoV2(HLERequestContext& ctx);
void BeginUserRegistration(HLERequestContext& ctx);
void CompleteUserRegistration(HLERequestContext& ctx);
void DeleteUser(HLERequestContext& ctx);
void SetUserPosition(HLERequestContext& ctx);
void GetProfileEditor(HLERequestContext& ctx);
void GetBaasAccountAdministrator(HLERequestContext &ctx);
void ListQualifiedUsers(HLERequestContext& ctx);
void ListOpenContextStoredUsers(HLERequestContext& ctx);
void StoreSaveDataThumbnailApplication(HLERequestContext& ctx);
void GetBaasAccountManagerForSystemService(HLERequestContext& ctx);
void StoreSaveDataThumbnailSystem(HLERequestContext& ctx);
void GetPinCodeLength(HLERequestContext& ctx);
private:
Result InitializeApplicationInfoBase();
void StoreSaveDataThumbnail(HLERequestContext& ctx, const Common::UUID& uuid,
const u64 tid);
enum class ApplicationType : u32_le {
GameCard = 0,
Digital = 1,
Unknown = 3,
};
struct ApplicationInfo {
Service::Glue::ApplicationLaunchProperty launch_property;
ApplicationType application_type;
constexpr explicit operator bool() const {
return launch_property.title_id != 0x0;
}
};
ApplicationInfo application_info{};
protected:
std::shared_ptr<Module> module;
std::shared_ptr<ProfileManager> profile_manager;
};
};
void LoopProcess(Core::System& system);
} // namespace Service::Account
@@ -12,6 +12,17 @@
namespace Service::Account {
IAsyncContext::IAsyncContext(Core::System& system_)
: ServiceFramework{system_, "IAsyncContext"}, service_context{system_, "IAsyncContext"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"},
{1, &IAsyncContext::Cancel, "Cancel"},
{2, &IAsyncContext::HasDone, "HasDone"},
{3, &IAsyncContext::GetResult, "GetResult"},
};
// clang-format on
RegisterHandlers(functions);
completion_event = service_context.CreateEvent("IAsyncContext:CompletionEvent");
}
-13
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,16 +30,6 @@ protected:
void MarkComplete();
std::optional<FunctionInfoBase> FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key, functions);
}
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"},
FunctionInfo{1, &IAsyncContext::Cancel, "Cancel"},
FunctionInfo{2, &IAsyncContext::HasDone, "HasDone"},
FunctionInfo{3, &IAsyncContext::GetResult, "GetResult"}
);
KernelHelpers::ServiceContext service_context;
std::atomic<bool> is_complete{false};
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -26,24 +26,25 @@ EventObserver::EventObserver(Core::System& system, WindowSystem& window_system)
m_window_system.SetEventObserver(this);
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait));
m_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("am:EventObserver");
system.Kernel().RunOnGuestCoreProcess("am:EventObserver", [this]() {
auto const stop_token = m_stop_source.get_token();
while (!stop_token.stop_requested()) {
auto* signaled_holder = this->WaitSignaled(stop_token);
if (!signaled_holder)
if (stop_token.stop_requested() || !signaled_holder)
break;
this->Process(signaled_holder);
}
m_process_cv.notify_one();
});
}
EventObserver::~EventObserver() {
// Signal thread and wait for processing to finish.
if (m_thread.joinable()) {
// Signal thread and wait for processing to finish.
m_thread.request_stop();
m_wakeup_event.Signal(m_system.Kernel());
m_thread.join();
m_stop_source.request_stop();
m_wakeup_event.Signal(m_system.Kernel());
{
std::unique_lock lk{m_process_mutex};
m_process_cv.wait(lk);
}
// Free remaining owned sessions.
+5 -1
View File
@@ -6,6 +6,8 @@
#pragma once
#include <condition_variable>
#include <stop_token>
#include "common/polyfill_thread.h"
#include "common/thread.h"
#include "core/hle/service/kernel_helpers.h"
@@ -62,7 +64,9 @@ private:
MultiWait m_deferred_wait_list;
// Processing thread.
std::jthread m_thread{};
std::stop_source m_stop_source{};
std::mutex m_process_mutex;
std::condition_variable m_process_cv{};
};
} // namespace Service::AM
@@ -0,0 +1,135 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
#include "core/hle/service/am/service/application_proxy.h"
#include "core/hle/service/am/service/library_applet_proxy.h"
#include "core/hle/service/am/service/system_applet_proxy.h"
#include "core/hle/service/am/service/overlay_applet_proxy.h"
#include "core/hle/service/am/window_system.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::AM {
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
WindowSystem& window_system)
: ServiceFramework{system_, "appletAE"}, m_window_system{window_system} {
// clang-format off
static const FunctionInfo functions[] = {
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
{110, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxyEx"},
{200, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld>, "OpenLibraryAppletProxyOld"},
{201, D<&IAllSystemAppletProxiesService::OpenLibraryAppletProxy>, "OpenLibraryAppletProxy"},
{300, D<&IAllSystemAppletProxiesService::OpenOverlayAppletProxy>, "OpenOverlayAppletProxy"},
{350, D<&IAllSystemAppletProxiesService::OpenSystemApplicationProxy>, "OpenSystemApplicationProxy"},
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
{410, nullptr, "GetSystemAppletControllerForDebug"},
{450, D<&IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions>, "GetSystemProcessCommonFunctions"}, // 19.0.0+
{460, D<&IAllSystemAppletProxiesService::GetAppletAlternativeFunctions>, "GetAppletAlternativeFunctions"}, // 20.0.0+
{1000, nullptr, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}
IAllSystemAppletProxiesService::~IAllSystemAppletProxiesService() = default;
Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle) {
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
*out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
system, applet, process_handle.Get(), m_window_system);
R_SUCCEED();
} else {
UNIMPLEMENTED();
R_THROW(ResultUnknown);
}
}
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle,
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute) {
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
*out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
system, applet, process_handle.Get(), m_window_system);
R_SUCCEED();
} else {
UNIMPLEMENTED();
R_THROW(ResultUnknown);
}
}
Result IAllSystemAppletProxiesService::OpenOverlayAppletProxy(
Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle) {
LOG_WARNING(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
*out_overlay_applet_proxy = std::make_shared<IOverlayAppletProxy>(
system, applet, process_handle.Get(), m_window_system);
R_SUCCEED();
} else {
UNIMPLEMENTED();
R_THROW(ResultUnknown);
}
}
Result IAllSystemAppletProxiesService::OpenSystemApplicationProxy(
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle) {
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
*out_system_application_proxy = std::make_shared<IApplicationProxy>(
system, applet, process_handle.Get(), m_window_system);
R_SUCCEED();
} else {
UNIMPLEMENTED();
R_THROW(ResultUnknown);
}
}
Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle) {
LOG_DEBUG(Service_AM, "called");
AppletAttribute attribute{};
R_RETURN(
this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));
}
Result IAllSystemAppletProxiesService::GetSystemProcessCommonFunctions() {
LOG_DEBUG(Service_AM, "(STUBBED) called.");
// TODO (jarrodnorwell)
R_SUCCEED();
}
Result IAllSystemAppletProxiesService::GetAppletAlternativeFunctions() {
LOG_DEBUG(Service_AM, "(STUBBED) called.");
// TODO (maufeat)
R_SUCCEED();
}
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
ProcessId process_id) {
return m_window_system.GetByAppletResourceUserId(process_id.pid);
}
} // namespace Service::AM
@@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
#include "core/hle/service/am/service/overlay_applet_proxy.h"
namespace Service {
namespace AM {
struct Applet;
struct AppletAttribute;
class IApplicationProxy;
class ILibraryAppletProxy;
class ISystemAppletProxy;
class WindowSystem;
class IAllSystemAppletProxiesService final
: public ServiceFramework<IAllSystemAppletProxiesService> {
public:
explicit IAllSystemAppletProxiesService(Core::System& system_, WindowSystem& window_system);
~IAllSystemAppletProxiesService() override;
private:
Result OpenSystemAppletProxy(Out<SharedPointer<ISystemAppletProxy>> out_system_applet_proxy,
ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle);
Result OpenLibraryAppletProxy(Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy,
ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle,
InLargeData<AppletAttribute, BufferAttr_HipcMapAlias> attribute);
Result OpenOverlayAppletProxy(Out<SharedPointer<IOverlayAppletProxy>> out_overlay_applet_proxy,
ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
Result OpenLibraryAppletProxyOld(
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle);
Result OpenSystemApplicationProxy(
Out<SharedPointer<IApplicationProxy>> out_system_application_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle);
Result GetSystemProcessCommonFunctions();
Result GetAppletAlternativeFunctions();
private:
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
WindowSystem& m_window_system;
};
} // namespace AM
} // namespace Service
@@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/file_sys/common_funcs.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/service/applet_common_functions.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::AM {
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
std::shared_ptr<Applet> applet_)
: ServiceFramework{system_, "IAppletCommonFunctions"}, applet{std::move(applet_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "SetTerminateResult"},
{10, nullptr, "ReadThemeStorage"},
{11, nullptr, "WriteThemeStorage"},
{20, nullptr, "PushToAppletBoundChannel"},
{21, nullptr, "TryPopFromAppletBoundChannel"},
{40, nullptr, "GetDisplayLogicalResolution"},
{42, D<&IAppletCommonFunctions::SetDisplayMagnification>, "SetDisplayMagnification"},
{50, D<&IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled>, "SetHomeButtonDoubleClickEnabled"},
{51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
{60, nullptr, "IsVrModeCurtainRequired"},
{61, nullptr, "IsSleepRequiredByHighTemperature"},
{62, nullptr, "IsSleepRequiredByLowBattery"},
{70, D<&IAppletCommonFunctions::SetCpuBoostRequestPriority>, "SetCpuBoostRequestPriority"},
{80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
{81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
{90, nullptr, "OpenNamedChannelAsParent"},
{91, nullptr, "OpenNamedChannelAsChild"},
{100, nullptr, "SetApplicationCoreUsageMode"},
{300, D<&IAppletCommonFunctions::GetCurrentApplicationId>, "GetCurrentApplicationId"},
{310, nullptr, "IsSystemAppletHomeMenu"}, //19.0.0+
{320, D<&IAppletCommonFunctions::SetGpuTimeSliceBoost>, "SetGpuTimeSliceBoost"}, //19.0.0+
{321, nullptr, "SetGpuTimeSliceBoostDueToApplication"}, //19.0.0+
{350, D<&IAppletCommonFunctions::Unknown350>, "Unknown350"} //20.0.0+
};
// clang-format on
RegisterHandlers(functions);
}
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
Result IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled(
bool home_button_double_click_enabled) {
LOG_WARNING(Service_AM, "(STUBBED) called, home_button_double_click_enabled={}",
home_button_double_click_enabled);
R_SUCCEED();
}
Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled(
Out<bool> out_home_button_double_click_enabled) {
LOG_WARNING(Service_AM, "(STUBBED) called");
*out_home_button_double_click_enabled = false;
R_SUCCEED();
}
Result IAppletCommonFunctions::SetDisplayMagnification(f32 x, f32 y, f32 width, f32 height) {
LOG_DEBUG(Service_AM, "(STUBBED) called, x={}, y={}, width={}, height={}", x, y, width,
height);
std::scoped_lock lk{applet->lock};
applet->display_magnification = Common::Rectangle<f32>{x, y, x + width, y + height};
R_SUCCEED();
}
Result IAppletCommonFunctions::SetCpuBoostRequestPriority(s32 priority) {
LOG_WARNING(Service_AM, "(STUBBED) called");
std::scoped_lock lk{applet->lock};
applet->cpu_boost_request_priority = priority;
R_SUCCEED();
}
Result IAppletCommonFunctions::GetCurrentApplicationId(Out<u64> out_application_id) {
LOG_WARNING(Service_AM, "(STUBBED) called");
*out_application_id = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
R_SUCCEED();
}
Result IAppletCommonFunctions::SetGpuTimeSliceBoost(s64 time_span) {
LOG_WARNING(Service_AM, "(STUBBED) called, time_span={}", time_span);
R_SUCCEED();
}
Result IAppletCommonFunctions::Unknown350(Out<u16> out_unknown) {
LOG_WARNING(Service_AM, "(STUBBED) called");
*out_unknown = 0;
R_SUCCEED();
}
} // namespace Service::AM
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::AM {
struct Applet;
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
public:
explicit IAppletCommonFunctions(Core::System& system_, std::shared_ptr<Applet> applet_);
~IAppletCommonFunctions() override;
private:
Result SetHomeButtonDoubleClickEnabled(bool home_button_double_click_enabled);
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
Result SetDisplayMagnification(f32 x, f32 y, f32 width, f32 height);
Result SetCpuBoostRequestPriority(s32 priority);
Result GetCurrentApplicationId(Out<u64> out_application_id);
Result SetGpuTimeSliceBoost(s64 time_span);
Result Unknown350(Out<u16> out_unknown);
const std::shared_ptr<Applet> applet;
};
} // namespace Service::AM
@@ -18,42 +18,42 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IApplicationAccessor::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
FunctionInfo{1, nullptr, "IsCompleted"},
FunctionInfo{10, D<&IApplicationAccessor::Start>, "Start"},
FunctionInfo{20, D<&IApplicationAccessor::RequestExit>, "RequestExit"},
FunctionInfo{25, D<&IApplicationAccessor::Terminate>, "Terminate"},
FunctionInfo{30, D<&IApplicationAccessor::GetResult>, "GetResult"},
FunctionInfo{101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"},
FunctionInfo{110, nullptr, "TerminateAllLibraryApplets"},
FunctionInfo{111, nullptr, "AreAnyLibraryAppletsLeft"},
FunctionInfo{112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"},
FunctionInfo{120, nullptr, "GetApplicationId"},
FunctionInfo{121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"},
FunctionInfo{122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"},
FunctionInfo{123, nullptr, "GetApplicationLaunchProperty"},
FunctionInfo{124, nullptr, "GetApplicationLaunchRequestInfo"},
FunctionInfo{130, D<&IApplicationAccessor::SetUsers>, "SetUsers"},
FunctionInfo{131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"},
FunctionInfo{132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"},
FunctionInfo{140, nullptr, "GetDesirableUids"},
FunctionInfo{150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"},
FunctionInfo{160, nullptr, "SetApplicationAttribute"},
FunctionInfo{170, nullptr, "HasSaveDataAccessPermission"},
FunctionInfo{180, nullptr, "PushToFriendInvitationStorageChannel"},
FunctionInfo{190, nullptr, "PushToNotificationStorageChannel"},
FunctionInfo{200, nullptr, "RequestApplicationSoftReset"},
FunctionInfo{201, nullptr, "RestartApplicationTimer"}
);
return HandlerTableGenerateWithFind(key, functions);
}
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet,
WindowSystem& window_system)
: ServiceFramework{system_, "IApplicationAccessor"}, m_window_system(window_system),
m_applet(std::move(applet)) {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
{1, nullptr, "IsCompleted"},
{10, D<&IApplicationAccessor::Start>, "Start"},
{20, D<&IApplicationAccessor::RequestExit>, "RequestExit"},
{25, D<&IApplicationAccessor::Terminate>, "Terminate"},
{30, D<&IApplicationAccessor::GetResult>, "GetResult"},
{101, D<&IApplicationAccessor::RequestForApplicationToGetForeground>, "RequestForApplicationToGetForeground"},
{110, nullptr, "TerminateAllLibraryApplets"},
{111, nullptr, "AreAnyLibraryAppletsLeft"},
{112, D<&IApplicationAccessor::GetCurrentLibraryApplet>, "GetCurrentLibraryApplet"},
{120, nullptr, "GetApplicationId"},
{121, D<&IApplicationAccessor::PushLaunchParameter>, "PushLaunchParameter"},
{122, D<&IApplicationAccessor::GetApplicationControlProperty>, "GetApplicationControlProperty"},
{123, nullptr, "GetApplicationLaunchProperty"},
{124, nullptr, "GetApplicationLaunchRequestInfo"},
{130, D<&IApplicationAccessor::SetUsers>, "SetUsers"},
{131, D<&IApplicationAccessor::CheckRightsEnvironmentAvailable>, "CheckRightsEnvironmentAvailable"},
{132, D<&IApplicationAccessor::GetNsRightsEnvironmentHandle>, "GetNsRightsEnvironmentHandle"},
{140, nullptr, "GetDesirableUids"},
{150, D<&IApplicationAccessor::ReportApplicationExitTimeout>, "ReportApplicationExitTimeout"},
{160, nullptr, "SetApplicationAttribute"},
{170, nullptr, "HasSaveDataAccessPermission"},
{180, nullptr, "PushToFriendInvitationStorageChannel"},
{190, nullptr, "PushToNotificationStorageChannel"},
{200, nullptr, "RequestApplicationSoftReset"},
{201, nullptr, "RestartApplicationTimer"},
};
// clang-format on
RegisterHandlers(functions);
}
IApplicationAccessor::~IApplicationAccessor() = default;
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -39,7 +36,6 @@ private:
Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
Result ReportApplicationExitTimeout();
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
WindowSystem& m_window_system;
const std::shared_ptr<Applet> m_applet;
};
@@ -20,16 +20,6 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IApplicationCreator::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
FunctionInfo{1, nullptr, "PopLaunchRequestedApplication"},
FunctionInfo{10, D<&IApplicationCreator::CreateSystemApplication>, "CreateSystemApplication"},
FunctionInfo{100, nullptr, "PopFloatingApplicationForDevelopment"}
);
return HandlerTableGenerateWithFind(key, functions);
}
namespace {
Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_application_accessor, Core::System& system, WindowSystem& window_system, u64 program_id) {
@@ -64,6 +54,16 @@ Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_applicati
IApplicationCreator::IApplicationCreator(Core::System& system_, WindowSystem& window_system)
: ServiceFramework{system_, "IApplicationCreator"}, m_window_system{window_system} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
{1, nullptr, "PopLaunchRequestedApplication"},
{10, D<&IApplicationCreator::CreateSystemApplication>, "CreateSystemApplication"},
{100, nullptr, "PopFloatingApplicationForDevelopment"},
};
// clang-format on
RegisterHandlers(functions);
}
IApplicationCreator::~IApplicationCreator() = default;
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -24,7 +24,6 @@ private:
Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
Result CreateSystemApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
WindowSystem& m_window_system;
};
@@ -51,84 +51,83 @@ FileSys::PatchManager::Metadata GetApplicationMetadata(Core::System& system, u64
} // Anonymous namespace
std::optional<ServiceFrameworkBase::FunctionInfoBase> IApplicationFunctions::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
FunctionInfo{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
FunctionInfo{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
FunctionInfo{12, D<&IApplicationFunctions::CreateApplicationAndRequestToStart>, "CreateApplicationAndRequestToStart"},
FunctionInfo{13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
FunctionInfo{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
FunctionInfo{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
FunctionInfo{20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
FunctionInfo{21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
FunctionInfo{22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
FunctionInfo{23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
FunctionInfo{24, nullptr, "GetLaunchStorageInfoForDebug"},
FunctionInfo{25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
FunctionInfo{26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
FunctionInfo{27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
FunctionInfo{28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
FunctionInfo{29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"},
FunctionInfo{30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
FunctionInfo{31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
FunctionInfo{32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
FunctionInfo{33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
FunctionInfo{34, nullptr, "SelectApplicationLicense"},
FunctionInfo{35, nullptr, "GetDeviceSaveDataSizeMax"},
FunctionInfo{36, nullptr, "GetLimitedApplicationLicense"},
FunctionInfo{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
FunctionInfo{40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
FunctionInfo{50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
FunctionInfo{60, D<&IApplicationFunctions::SetMediaPlaybackStateForApplication>, "SetMediaPlaybackStateForApplication"},
FunctionInfo{65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
FunctionInfo{66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
FunctionInfo{67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
FunctionInfo{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
FunctionInfo{70, nullptr, "RequestToShutdown"},
FunctionInfo{71, nullptr, "RequestToReboot"},
FunctionInfo{72, nullptr, "RequestToSleep"},
FunctionInfo{80, nullptr, "ExitAndRequestToShowThanksMessage"},
FunctionInfo{90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
FunctionInfo{100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
FunctionInfo{101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
FunctionInfo{102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
FunctionInfo{110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
FunctionInfo{111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
FunctionInfo{120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
FunctionInfo{121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
FunctionInfo{122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
FunctionInfo{123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
FunctionInfo{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
FunctionInfo{130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
FunctionInfo{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
FunctionInfo{140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
FunctionInfo{141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
FunctionInfo{150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
FunctionInfo{151, nullptr, "TryPopFromNotificationStorageChannel"},
FunctionInfo{160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"},
FunctionInfo{170, nullptr, "SetHdcpAuthenticationActivated"},
FunctionInfo{180, nullptr, "GetLaunchRequiredVersion"},
FunctionInfo{181, nullptr, "UpgradeLaunchRequiredVersion"},
FunctionInfo{190, nullptr, "SendServerMaintenanceOverlayNotification"},
FunctionInfo{200, nullptr, "GetLastApplicationExitReason"},
FunctionInfo{210, D<&IApplicationFunctions::GetUnknownEvent210>, "Unknown210"},
FunctionInfo{220, nullptr, "Unknown220"}, // [20.0.0+]
FunctionInfo{300, nullptr, "CreateMovieWriter"}, // [19.0.0+]
FunctionInfo{310, nullptr, "Unknown310"}, // [20.0.0+]
FunctionInfo{320, nullptr, "Unknown320"}, // [20.0.0+]
FunctionInfo{330, D<&IApplicationFunctions::Unknown330>, "Unknown330"}, // [20.0.0+]
FunctionInfo{500, nullptr, "StartContinuousRecordingFlushForDebug"},
FunctionInfo{1000, nullptr, "CreateMovieMaker"},
FunctionInfo{1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"}
);
return HandlerTableGenerateWithFind(key, functions);
}
IApplicationFunctions::IApplicationFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
: ServiceFramework{system_, "IApplicationFunctions"}
, m_applet{std::move(applet)}
{}
: ServiceFramework{system_, "IApplicationFunctions"}, m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{1, D<&IApplicationFunctions::PopLaunchParameter>, "PopLaunchParameter"},
{10, nullptr, "CreateApplicationAndPushAndRequestToStart"},
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
{12, D<&IApplicationFunctions::CreateApplicationAndRequestToStart>, "CreateApplicationAndRequestToStart"},
{13, nullptr, "CreateApplicationAndRequestToStartForQuest"},
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
{20, D<&IApplicationFunctions::EnsureSaveData>, "EnsureSaveData"},
{21, D<&IApplicationFunctions::GetDesiredLanguage>, "GetDesiredLanguage"},
{22, D<&IApplicationFunctions::SetTerminateResult>, "SetTerminateResult"},
{23, D<&IApplicationFunctions::GetDisplayVersion>, "GetDisplayVersion"},
{24, nullptr, "GetLaunchStorageInfoForDebug"},
{25, D<&IApplicationFunctions::ExtendSaveData>, "ExtendSaveData"},
{26, D<&IApplicationFunctions::GetSaveDataSize>, "GetSaveDataSize"},
{27, D<&IApplicationFunctions::CreateCacheStorage>, "CreateCacheStorage"},
{28, D<&IApplicationFunctions::GetSaveDataSizeMax>, "GetSaveDataSizeMax"},
{29, D<&IApplicationFunctions::GetCacheStorageMax>, "GetCacheStorageMax"},
{30, D<&IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed>, "BeginBlockingHomeButtonShortAndLongPressed"},
{31, D<&IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed>, "EndBlockingHomeButtonShortAndLongPressed"},
{32, D<&IApplicationFunctions::BeginBlockingHomeButton>, "BeginBlockingHomeButton"},
{33, D<&IApplicationFunctions::EndBlockingHomeButton>, "EndBlockingHomeButton"},
{34, nullptr, "SelectApplicationLicense"},
{35, nullptr, "GetDeviceSaveDataSizeMax"},
{36, nullptr, "GetLimitedApplicationLicense"},
{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
{40, D<&IApplicationFunctions::NotifyRunning>, "NotifyRunning"},
{50, D<&IApplicationFunctions::GetPseudoDeviceId>, "GetPseudoDeviceId"},
{60, D<&IApplicationFunctions::SetMediaPlaybackStateForApplication>, "SetMediaPlaybackStateForApplication"},
{65, D<&IApplicationFunctions::IsGamePlayRecordingSupported>, "IsGamePlayRecordingSupported"},
{66, D<&IApplicationFunctions::InitializeGamePlayRecording>, "InitializeGamePlayRecording"},
{67, D<&IApplicationFunctions::SetGamePlayRecordingState>, "SetGamePlayRecordingState"},
{68, nullptr, "RequestFlushGamePlayingMovieForDebug"},
{70, nullptr, "RequestToShutdown"},
{71, nullptr, "RequestToReboot"},
{72, nullptr, "RequestToSleep"},
{80, nullptr, "ExitAndRequestToShowThanksMessage"},
{90, D<&IApplicationFunctions::EnableApplicationCrashReport>, "EnableApplicationCrashReport"},
{100, D<&IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer>, "InitializeApplicationCopyrightFrameBuffer"},
{101, D<&IApplicationFunctions::SetApplicationCopyrightImage>, "SetApplicationCopyrightImage"},
{102, D<&IApplicationFunctions::SetApplicationCopyrightVisibility>, "SetApplicationCopyrightVisibility"},
{110, D<&IApplicationFunctions::QueryApplicationPlayStatistics>, "QueryApplicationPlayStatistics"},
{111, D<&IApplicationFunctions::QueryApplicationPlayStatisticsByUid>, "QueryApplicationPlayStatisticsByUid"},
{120, D<&IApplicationFunctions::ExecuteProgram>, "ExecuteProgram"},
{121, D<&IApplicationFunctions::ClearUserChannel>, "ClearUserChannel"},
{122, D<&IApplicationFunctions::UnpopToUserChannel>, "UnpopToUserChannel"},
{123, D<&IApplicationFunctions::GetPreviousProgramIndex>, "GetPreviousProgramIndex"},
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
{130, D<&IApplicationFunctions::GetGpuErrorDetectedSystemEvent>, "GetGpuErrorDetectedSystemEvent"},
{131, nullptr, "SetDelayTimeToAbortOnGpuError"},
{140, D<&IApplicationFunctions::GetFriendInvitationStorageChannelEvent>, "GetFriendInvitationStorageChannelEvent"},
{141, D<&IApplicationFunctions::TryPopFromFriendInvitationStorageChannel>, "TryPopFromFriendInvitationStorageChannel"},
{150, D<&IApplicationFunctions::GetNotificationStorageChannelEvent>, "GetNotificationStorageChannelEvent"},
{151, nullptr, "TryPopFromNotificationStorageChannel"},
{160, D<&IApplicationFunctions::GetHealthWarningDisappearedSystemEvent>, "GetHealthWarningDisappearedSystemEvent"},
{170, nullptr, "SetHdcpAuthenticationActivated"},
{180, nullptr, "GetLaunchRequiredVersion"},
{181, nullptr, "UpgradeLaunchRequiredVersion"},
{190, nullptr, "SendServerMaintenanceOverlayNotification"},
{200, nullptr, "GetLastApplicationExitReason"},
{210, D<&IApplicationFunctions::GetUnknownEvent210>, "Unknown210"},
{220, nullptr, "Unknown220"}, // [20.0.0+]
{300, nullptr, "CreateMovieWriter"}, // [19.0.0+]
{310, nullptr, "Unknown310"}, // [20.0.0+]
{320, nullptr, "Unknown320"}, // [20.0.0+]
{330, D<&IApplicationFunctions::Unknown330>, "Unknown330"}, // [20.0.0+]
{500, nullptr, "StartContinuousRecordingFlushForDebug"},
{1000, nullptr, "CreateMovieMaker"},
{1001, D<&IApplicationFunctions::PrepareForJit>, "PrepareForJit"},
};
// clang-format on
RegisterHandlers(functions);
}
IApplicationFunctions::~IApplicationFunctions() = default;
@@ -84,7 +84,6 @@ private:
Result GetUnknownEvent210(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result Unknown330(Out<u8> out);
Result PrepareForJit();
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
const std::shared_ptr<Applet> m_applet;
};
@@ -0,0 +1,106 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/am/service/applet_common_functions.h"
#include "core/hle/service/am/service/application_functions.h"
#include "core/hle/service/am/service/application_proxy.h"
#include "core/hle/service/am/service/audio_controller.h"
#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/library_applet_creator.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"
#include "core/hle/service/cmif_serialization.h"
namespace Service::AM {
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
Kernel::KProcess* process, WindowSystem& window_system)
: ServiceFramework{system_, "IApplicationProxy"},
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
{1, D<&IApplicationProxy::GetSelfController>, "GetSelfController"},
{2, D<&IApplicationProxy::GetWindowController>, "GetWindowController"},
{3, D<&IApplicationProxy::GetAudioController>, "GetAudioController"},
{4, D<&IApplicationProxy::GetDisplayController>, "GetDisplayController"},
{10, D<&IApplicationProxy::GetProcessWindingController>, "GetProcessWindingController"},
{11, D<&IApplicationProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
{20, D<&IApplicationProxy::GetApplicationFunctions>, "GetApplicationFunctions"},
{1000, D<&IApplicationProxy::GetDebugFunctions>, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}
IApplicationProxy::~IApplicationProxy() = default;
Result IApplicationProxy::GetAudioController(
Out<SharedPointer<IAudioController>> out_audio_controller) {
LOG_DEBUG(Service_AM, "called");
*out_audio_controller = std::make_shared<IAudioController>(system);
R_SUCCEED();
}
Result IApplicationProxy::GetDisplayController(
Out<SharedPointer<IDisplayController>> out_display_controller) {
LOG_DEBUG(Service_AM, "called");
*out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
R_SUCCEED();
}
Result IApplicationProxy::GetProcessWindingController(
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
LOG_DEBUG(Service_AM, "called");
*out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
R_SUCCEED();
}
Result IApplicationProxy::GetDebugFunctions(
Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
LOG_DEBUG(Service_AM, "called");
*out_debug_functions = std::make_shared<IDebugFunctions>(system);
R_SUCCEED();
}
Result IApplicationProxy::GetWindowController(
Out<SharedPointer<IWindowController>> out_window_controller) {
LOG_DEBUG(Service_AM, "called");
*out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system);
R_SUCCEED();
}
Result IApplicationProxy::GetSelfController(
Out<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
*out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
R_SUCCEED();
}
Result IApplicationProxy::GetCommonStateGetter(
Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
LOG_DEBUG(Service_AM, "called");
*out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
R_SUCCEED();
}
Result IApplicationProxy::GetLibraryAppletCreator(
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
LOG_DEBUG(Service_AM, "called");
*out_library_applet_creator =
std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system);
R_SUCCEED();
}
Result IApplicationProxy::GetApplicationFunctions(
Out<SharedPointer<IApplicationFunctions>> out_application_functions) {
LOG_DEBUG(Service_AM, "called");
*out_application_functions = std::make_shared<IApplicationFunctions>(system, m_applet);
R_SUCCEED();
}
} // namespace Service::AM
@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::AM {
struct Applet;
class IAudioController;
class IApplicationFunctions;
class ICommonStateGetter;
class IDebugFunctions;
class IDisplayController;
class ILibraryAppletCreator;
class IProcessWindingController;
class ISelfController;
class IWindowController;
class WindowSystem;
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
public:
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
Kernel::KProcess* process, WindowSystem& window_system);
~IApplicationProxy();
private:
Result GetAudioController(Out<SharedPointer<IAudioController>> out_audio_controller);
Result GetDisplayController(Out<SharedPointer<IDisplayController>> out_display_controller);
Result GetProcessWindingController(
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller);
Result GetDebugFunctions(Out<SharedPointer<IDebugFunctions>> out_debug_functions);
Result GetWindowController(Out<SharedPointer<IWindowController>> out_window_controller);
Result GetSelfController(Out<SharedPointer<ISelfController>> out_self_controller);
Result GetCommonStateGetter(Out<SharedPointer<ICommonStateGetter>> out_common_state_getter);
Result GetLibraryAppletCreator(
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator);
Result GetApplicationFunctions(
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
private:
WindowSystem& m_window_system;
Kernel::KProcess* const m_process;
const std::shared_ptr<Applet> m_applet;
};
} // namespace Service::AM
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/service/application_proxy.h"
#include "core/hle/service/am/service/application_proxy_service.h"
#include "core/hle/service/am/window_system.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::AM {
IApplicationProxyService::IApplicationProxyService(Core::System& system_,
WindowSystem& window_system)
: ServiceFramework{system_, "appletOE"}, m_window_system{window_system} {
static const FunctionInfo functions[] = {
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
};
RegisterHandlers(functions);
}
IApplicationProxyService::~IApplicationProxyService() = default;
Result IApplicationProxyService::OpenApplicationProxy(
Out<SharedPointer<IApplicationProxy>> out_application_proxy, ClientProcessId pid,
InCopyHandle<Kernel::KProcess> process_handle) {
LOG_DEBUG(Service_AM, "called");
if (const auto applet = this->GetAppletFromProcessId(pid)) {
*out_application_proxy = std::make_shared<IApplicationProxy>(
system, applet, process_handle.Get(), m_window_system);
R_SUCCEED();
} else {
UNIMPLEMENTED();
R_THROW(ResultUnknown);
}
}
std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) {
return m_window_system.GetByAppletResourceUserId(process_id.pid);
}
} // namespace Service::AM
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service {
namespace AM {
struct Applet;
class IApplicationProxy;
class WindowSystem;
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
public:
explicit IApplicationProxyService(Core::System& system_, WindowSystem& window_system);
~IApplicationProxyService() override;
private:
Result OpenApplicationProxy(Out<SharedPointer<IApplicationProxy>> out_application_proxy,
ClientProcessId pid, InCopyHandle<Kernel::KProcess> process_handle);
private:
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
WindowSystem& m_window_system;
};
} // namespace AM
} // namespace Service
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -9,20 +9,20 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IAudioController::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"},
FunctionInfo{1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"},
FunctionInfo{2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
FunctionInfo{3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
FunctionInfo{4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
FunctionInfo{5, nullptr, "Unknown5", MakeVersionGate({20,0,0})}
);
return HandlerTableGenerateWithFind(key, functions);
}
IAudioController::IAudioController(Core::System& system_)
: ServiceFramework{system_, "IAudioController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioController::SetExpectedMasterVolume>, "SetExpectedMasterVolume"},
{1, D<&IAudioController::GetMainAppletExpectedMasterVolume>, "GetMainAppletExpectedMasterVolume"},
{2, D<&IAudioController::GetLibraryAppletExpectedMasterVolume>, "GetLibraryAppletExpectedMasterVolume"},
{3, D<&IAudioController::ChangeMainAppletMasterVolume>, "ChangeMainAppletMasterVolume"},
{4, D<&IAudioController::SetTransparentVolumeRate>, "SetTransparentVolumeRate"},
{5, nullptr, "Unknown5"}, //20.0.0+
};
// clang-format on
RegisterHandlers(functions);
}
IAudioController::~IAudioController() = default;
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -23,7 +20,6 @@ private:
Result ChangeMainAppletMasterVolume(f32 volume, s64 fade_time_ns);
Result SetTransparentVolumeRate(f32 transparent_volume_rate);
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
static constexpr float MinAllowedVolume = 0.0f;
static constexpr float MaxAllowedVolume = 1.0f;
@@ -8,6 +8,7 @@
#include "core/hle/service/am/am_results.h"
#include "core/hle/service/am/applet.h"
#include "core/hle/service/am/service/common_state_getter.h"
#include "core/hle/service/am/service/lock_accessor.h"
#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/cmif_serialization.h"
@@ -17,147 +18,77 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> ICommonStateGetter::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"},
FunctionInfo{1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"},
FunctionInfo{2, nullptr, "GetThisAppletKind"},
FunctionInfo{3, nullptr, "AllowToEnterSleep"},
FunctionInfo{4, nullptr, "DisallowToEnterSleep"},
FunctionInfo{5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"},
FunctionInfo{6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"},
FunctionInfo{7, nullptr, "GetCradleStatus"},
FunctionInfo{8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"},
FunctionInfo{9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"},
FunctionInfo{10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"},
FunctionInfo{11, D<&ICommonStateGetter::ReleaseSleepLock>, "ReleaseSleepLock"},
FunctionInfo{12, D<&ICommonStateGetter::ReleaseSleepLockTransiently>, "ReleaseSleepLockTransiently"},
FunctionInfo{13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"},
FunctionInfo{14, nullptr, "GetWakeupCount", MakeVersionGate({11,0,0})},
FunctionInfo{15, nullptr, "Unknown15", MakeVersionGate({19,0,0})},
FunctionInfo{20, D<&ICommonStateGetter::PushToGeneralChannel>, "PushToGeneralChannel"},
FunctionInfo{30, D<&ICommonStateGetter::GetHomeButtonReaderLockAccessor>, "GetHomeButtonReaderLockAccessor"},
FunctionInfo{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx", MakeVersionGate({2,0,0})},
FunctionInfo{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx", MakeVersionGate({7,0,0})},
FunctionInfo{40, nullptr, "GetCradleFwVersion", MakeVersionGate({2,0,0})},
FunctionInfo{50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled", MakeVersionGate({3,0,0})},
FunctionInfo{51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled", MakeVersionGate({3,0,0})},
FunctionInfo{52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled", MakeVersionGate({4,0,0})},
FunctionInfo{53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx", MakeVersionGate({7,0,0})},
FunctionInfo{54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx", MakeVersionGate({7,0,0})},
FunctionInfo{55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection", MakeVersionGate({3,0,0})},
FunctionInfo{59, nullptr, "SetVrPositionForDebug", MakeVersionGate({1,0,0})},
FunctionInfo{60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"},
FunctionInfo{61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"},
FunctionInfo{62, D<&ICommonStateGetter::GetHdcpAuthenticationState>, "GetHdcpAuthenticationState"},
FunctionInfo{63, D<&ICommonStateGetter::GetHdcpAuthenticationStateChangeEvent>, "GetHdcpAuthenticationStateChangeEvent"},
FunctionInfo{64, nullptr, "SetTvPowerStateMatchingMode"},
FunctionInfo{65, nullptr, "GetApplicationIdByContentActionName"},
FunctionInfo{66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
FunctionInfo{67, nullptr, "CancelCpuBoostMode"},
FunctionInfo{68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"},
FunctionInfo{80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"},
FunctionInfo{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
FunctionInfo{91, nullptr, "GetCurrentPerformanceConfiguration"},
FunctionInfo{100, D<&ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
FunctionInfo{110, nullptr, "OpenMyGpuErrorHandler"},
FunctionInfo{120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory", MakeVersionGate({13,0,0})},
FunctionInfo{130, D<&ICommonStateGetter::EnableStartupLogoDisappearedMessage>, "EnableStartupLogoDisappearedMessage", MakeVersionGate({21,0,0})},
FunctionInfo{200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
FunctionInfo{300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
FunctionInfo{400, nullptr, "ActivateMigrationService"},
FunctionInfo{401, nullptr, "DeactivateMigrationService"},
FunctionInfo{500, nullptr, "DisableSleepTillShutdown"},
FunctionInfo{501, nullptr, "SuppressDisablingSleepTemporarily"},
FunctionInfo{502, nullptr, "IsSleepEnabled"},
FunctionInfo{503, nullptr, "IsDisablingSleepSuppressed"},
FunctionInfo{600, nullptr, "SetHidInputMagnificationForApplication", MakeVersionGate({20,0,0})},
FunctionInfo{610, D<&ICommonStateGetter::Unknown610>, "Unknown610", MakeVersionGate({21,0,0})},
FunctionInfo{611, D<&ICommonStateGetter::Unknown611>, "Unknown611", MakeVersionGate({22,0,0})},
FunctionInfo{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled", MakeVersionGate({11,0,0})},
FunctionInfo{910, nullptr, "GetLaunchRequiredTick", MakeVersionGate({17,0,0})},
FunctionInfo{1000, D<&ICommonStateGetter::BeginVrMode3d>, "BeginVrMode3d", MakeVersionGate({19,0,0})},
FunctionInfo{1001, D<&ICommonStateGetter::EndVrMode3d>, "EndVrMode3d", MakeVersionGate({19,0,0})},
FunctionInfo{1002, D<&ICommonStateGetter::IsVrModeEnabled3d>, "IsVrModeEnabled3d", MakeVersionGate({19,0,0})},
FunctionInfo{1003, D<&ICommonStateGetter::GetVrLaboGoggleViewport>, "GetVrLaboGoggleViewport", MakeVersionGate({21,0,0})},
FunctionInfo{1004, D<&ICommonStateGetter::GetPanelPhysicalSizeForSpecificTitle>, "GetPanelPhysicalSizeForSpecificTitle", MakeVersionGate({21,0,0})},
FunctionInfo{1005, D<&ICommonStateGetter::GetPanelResolutionForSpecificTitle>, "GetPanelResolutionForSpecificTitle", MakeVersionGate({21,0,0})}
);
return HandlerTableGenerateWithFind(key, functions);
}
class ILockAccessor final : public ServiceFramework<ILockAccessor> {
public:
explicit ILockAccessor(Core::System& system_)
: ServiceFramework{system_, "ILockAccessor"}, m_context{system_, "ILockAccessor"},
m_event{m_context} {
m_event.Signal(system.Kernel());
}
~ILockAccessor() override = default;
Result TryLock(Out<bool> out_is_locked, OutCopyHandle<Kernel::KReadableEvent> out_handle, bool return_handle) {
LOG_INFO(Service_AM, "called, return_handle={}", return_handle);
{
std::scoped_lock lk{m_mutex};
if (m_is_locked) {
*out_is_locked = false;
} else {
m_is_locked = true;
*out_is_locked = true;
}
}
if (return_handle) {
*out_handle = m_event.GetHandle();
}
R_SUCCEED();
}
Result Unlock() {
LOG_INFO(Service_AM, "called");
{
std::scoped_lock lk{m_mutex};
m_is_locked = false;
}
m_event.Signal(system.Kernel());
R_SUCCEED();
}
Result GetEvent(OutCopyHandle<Kernel::KReadableEvent> out_handle) {
LOG_INFO(Service_AM, "called");
*out_handle = m_event.GetHandle();
R_SUCCEED();
}
Result IsLocked(Out<bool> out_is_locked) {
LOG_INFO(Service_AM, "called");
std::scoped_lock lk{m_mutex};
*out_is_locked = m_is_locked;
R_SUCCEED();
}
private:
std::optional<FunctionInfoBase> FindRequest(u32 key) override {
return HandlerTableGenerateWithFind(key, functions);
}
static constexpr auto functions = CreateStaticMap(
FunctionInfo{1, D<&ILockAccessor::TryLock>, "TryLock"},
FunctionInfo{2, D<&ILockAccessor::Unlock>, "Unlock"},
FunctionInfo{3, D<&ILockAccessor::GetEvent>, "GetEvent"},
FunctionInfo{4, D<&ILockAccessor::IsLocked>, "IsLocked"}
);
KernelHelpers::ServiceContext m_context;
Event m_event;
std::mutex m_mutex{};
bool m_is_locked{};
};
ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Applet> applet)
: ServiceFramework{system_, "ICommonStateGetter"}, m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ICommonStateGetter::GetEventHandle>, "GetEventHandle"},
{1, D<&ICommonStateGetter::ReceiveMessage>, "ReceiveMessage"},
{2, nullptr, "GetThisAppletKind"},
{3, nullptr, "AllowToEnterSleep"},
{4, nullptr, "DisallowToEnterSleep"},
{5, D<&ICommonStateGetter::GetOperationMode>, "GetOperationMode"},
{6, D<&ICommonStateGetter::GetPerformanceMode>, "GetPerformanceMode"},
{7, nullptr, "GetCradleStatus"},
{8, D<&ICommonStateGetter::GetBootMode>, "GetBootMode"},
{9, D<&ICommonStateGetter::GetCurrentFocusState>, "GetCurrentFocusState"},
{10, D<&ICommonStateGetter::RequestToAcquireSleepLock>, "RequestToAcquireSleepLock"},
{11, D<&ICommonStateGetter::ReleaseSleepLock>, "ReleaseSleepLock"},
{12, D<&ICommonStateGetter::ReleaseSleepLockTransiently>, "ReleaseSleepLockTransiently"},
{13, D<&ICommonStateGetter::GetAcquiredSleepLockEvent>, "GetAcquiredSleepLockEvent"},
{14, nullptr, "GetWakeupCount"}, //11.0.0+
{15, nullptr, "Unknown15"}, //19.0.0+
{20, D<&ICommonStateGetter::PushToGeneralChannel>, "PushToGeneralChannel"},
{30, D<&ICommonStateGetter::GetHomeButtonReaderLockAccessor>, "GetHomeButtonReaderLockAccessor"},
{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"}, //2.0.0+
{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"}, //7.0.0+
{40, nullptr, "GetCradleFwVersion"}, //2.0.0+
{50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"}, //3.0.0+
{51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"}, //3.0.0+
{52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"}, //4.0.0+
{53, D<&ICommonStateGetter::BeginVrModeEx>, "BeginVrModeEx"}, //7.0.0+
{54, D<&ICommonStateGetter::EndVrModeEx>, "EndVrModeEx"}, //7.0.0+
{55, D<&ICommonStateGetter::IsInControllerFirmwareUpdateSection>, "IsInControllerFirmwareUpdateSection"}, //3.0.0+
{59, nullptr, "SetVrPositionForDebug"}, //1.0.0+
{60, D<&ICommonStateGetter::GetDefaultDisplayResolution>, "GetDefaultDisplayResolution"},
{61, D<&ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent>, "GetDefaultDisplayResolutionChangeEvent"},
{62, D<&ICommonStateGetter::GetHdcpAuthenticationState>, "GetHdcpAuthenticationState"},
{63, D<&ICommonStateGetter::GetHdcpAuthenticationStateChangeEvent>, "GetHdcpAuthenticationStateChangeEvent"},
{64, nullptr, "SetTvPowerStateMatchingMode"},
{65, nullptr, "GetApplicationIdByContentActionName"},
{66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
{67, nullptr, "CancelCpuBoostMode"},
{68, D<&ICommonStateGetter::GetBuiltInDisplayType>, "GetBuiltInDisplayType"},
{80, D<&ICommonStateGetter::PerformSystemButtonPressingIfInFocus>, "PerformSystemButtonPressingIfInFocus"},
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
{91, nullptr, "GetCurrentPerformanceConfiguration"},
{100, D<&ICommonStateGetter::SetHandlingHomeButtonShortPressedEnabled>, "SetHandlingHomeButtonShortPressedEnabled"},
{110, nullptr, "OpenMyGpuErrorHandler"},
{120, D<&ICommonStateGetter::GetAppletLaunchedHistory>, "GetAppletLaunchedHistory"}, //13.0.0+
{130, D<&ICommonStateGetter::EnableStartupLogoDisappearedMessage>, "EnableStartupLogoDisappearedMessage"}, //21.0.0+
{200, D<&ICommonStateGetter::GetOperationModeSystemInfo>, "GetOperationModeSystemInfo"},
{300, D<&ICommonStateGetter::GetSettingsPlatformRegion>, "GetSettingsPlatformRegion"},
{400, nullptr, "ActivateMigrationService"},
{401, nullptr, "DeactivateMigrationService"},
{500, nullptr, "DisableSleepTillShutdown"},
{501, nullptr, "SuppressDisablingSleepTemporarily"},
{502, nullptr, "IsSleepEnabled"},
{503, nullptr, "IsDisablingSleepSuppressed"},
{600, nullptr, "SetHidInputMagnificationForApplication"}, //20.0.0+
{610, D<&ICommonStateGetter::Unknown610>, "Unknown610"}, //21.0.0+
{611, D<&ICommonStateGetter::Unknown611>, "Unknown611"}, //22.0.0+
{900, D<&ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled>, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"}, //11.0.0+
{910, nullptr, "GetLaunchRequiredTick"}, //17.0.0+
{1000, D<&ICommonStateGetter::BeginVrMode3d>, "BeginVrMode3d"}, //19.0.0+
{1001, D<&ICommonStateGetter::EndVrMode3d>, "EndVrMode3d"}, //19.0.0+
{1002, D<&ICommonStateGetter::IsVrModeEnabled3d>, "IsVrModeEnabled3d"}, //19.0.0+
{1003, D<&ICommonStateGetter::GetVrLaboGoggleViewport>, "GetVrLaboGoggleViewport"}, //21.0.0+
{1004, D<&ICommonStateGetter::GetPanelPhysicalSizeForSpecificTitle>, "GetPanelPhysicalSizeForSpecificTitle"}, //21.0.0+
{1005, D<&ICommonStateGetter::GetPanelResolutionForSpecificTitle>, "GetPanelResolutionForSpecificTitle"}, //21.0.0+
};
// clang-format on
RegisterHandlers(functions);
}
ICommonStateGetter::~ICommonStateGetter() = default;
@@ -76,7 +76,6 @@ private:
void SetCpuBoostMode(HLERequestContext& ctx);
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
const std::shared_ptr<Applet> m_applet;
};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,21 +6,22 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> ICradleFirmwareUpdater::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"},
FunctionInfo{1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"},
FunctionInfo{2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"},
FunctionInfo{3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"},
FunctionInfo{4, nullptr, "GetUpdateProgressInfo"},
FunctionInfo{5, nullptr, "GetLastInternalResult"}
);
return HandlerTableGenerateWithFind(key, functions);
}
ICradleFirmwareUpdater::ICradleFirmwareUpdater(Core::System& system_)
: ServiceFramework{system_, "ICradleFirmwareUpdater"},
m_context{system, "ICradleFirmwareUpdater"}, m_cradle_device_info_event{m_context} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ICradleFirmwareUpdater::StartUpdate>, "StartUpdate"},
{1, D<&ICradleFirmwareUpdater::FinishUpdate>, "FinishUpdate"},
{2, D<&ICradleFirmwareUpdater::GetCradleDeviceInfo>, "GetCradleDeviceInfo"},
{3, D<&ICradleFirmwareUpdater::GetCradleDeviceInfoChangeEvent>, "GetCradleDeviceInfoChangeEvent"},
{4, nullptr, "GetUpdateProgressInfo"},
{5, nullptr, "GetLastInternalResult"},
};
// clang-format on
RegisterHandlers(functions);
}
ICradleFirmwareUpdater::~ICradleFirmwareUpdater() = default;
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,7 +30,6 @@ private:
Result GetCradleDeviceInfoChangeEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
private:
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
KernelHelpers::ServiceContext m_context;
Event m_cradle_device_info_event;
};
@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/am/service/debug_functions.h"
namespace Service::AM {
IDebugFunctions::IDebugFunctions(Core::System& system_)
: ServiceFramework{system_, "IDebugFunctions"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "NotifyMessageToHomeMenuForDebug"},
{1, nullptr, "OpenMainApplication"},
{10, nullptr, "PerformSystemButtonPressing"},
{20, nullptr, "InvalidateTransitionLayer"},
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
{31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
{40, nullptr, "GetAppletResourceUsageInfo"},
{50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
{51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
{100, nullptr, "SetCpuBoostModeForApplet"},
{101, nullptr, "CancelCpuBoostModeForApplet"},
{110, nullptr, "PushToAppletBoundChannelForDebug"},
{111, nullptr, "TryPopFromAppletBoundChannelForDebug"},
{120, nullptr, "AlarmSettingNotificationEnableAppEventReserve"},
{121, nullptr, "AlarmSettingNotificationDisableAppEventReserve"},
{122, nullptr, "AlarmSettingNotificationPushAppEventNotify"},
{130, nullptr, "FriendInvitationSetApplicationParameter"},
{131, nullptr, "FriendInvitationClearApplicationParameter"},
{132, nullptr, "FriendInvitationPushApplicationParameter"},
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
{200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
{300, nullptr, "TerminateAllRunningApplicationsForDebug"},
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
};
// clang-format on
RegisterHandlers(functions);
}
IDebugFunctions::~IDebugFunctions() = default;
} // namespace Service::AM
@@ -0,0 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Service::AM {
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
public:
explicit IDebugFunctions(Core::System& system_);
~IDebugFunctions() override;
};
} // namespace Service::AM
@@ -12,42 +12,42 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IDisplayController::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, nullptr, "GetLastForegroundCaptureImage"},
FunctionInfo{1, nullptr, "UpdateLastForegroundCaptureImage"},
FunctionInfo{2, nullptr, "GetLastApplicationCaptureImage"},
FunctionInfo{3, nullptr, "GetCallerAppletCaptureImage"},
FunctionInfo{4, nullptr, "UpdateCallerAppletCaptureImage"},
FunctionInfo{5, D<&IDisplayController::GetLastForegroundCaptureImageEx>, "GetLastForegroundCaptureImageEx"},
FunctionInfo{6, nullptr, "GetLastApplicationCaptureImageEx"},
FunctionInfo{7, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"},
FunctionInfo{8, D<&IDisplayController::TakeScreenShotOfOwnLayer>, "TakeScreenShotOfOwnLayer"},
FunctionInfo{9, nullptr, "CopyBetweenCaptureBuffers"},
FunctionInfo{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
FunctionInfo{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
FunctionInfo{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
FunctionInfo{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
FunctionInfo{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
FunctionInfo{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
FunctionInfo{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
FunctionInfo{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
FunctionInfo{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
FunctionInfo{20, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"},
FunctionInfo{21, nullptr, "ClearAppletTransitionBuffer"},
FunctionInfo{22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"},
FunctionInfo{23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"},
FunctionInfo{24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"},
FunctionInfo{25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"},
FunctionInfo{26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"},
FunctionInfo{27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"},
FunctionInfo{28, nullptr, "TakeScreenShotOfOwnLayerEx"}
);
return HandlerTableGenerateWithFind(key, functions);
}
IDisplayController::IDisplayController(Core::System& system_, std::shared_ptr<Applet> applet_)
: ServiceFramework{system_, "IDisplayController"}, applet(std::move(applet_)) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetLastForegroundCaptureImage"},
{1, nullptr, "UpdateLastForegroundCaptureImage"},
{2, nullptr, "GetLastApplicationCaptureImage"},
{3, nullptr, "GetCallerAppletCaptureImage"},
{4, nullptr, "UpdateCallerAppletCaptureImage"},
{5, D<&IDisplayController::GetLastForegroundCaptureImageEx>, "GetLastForegroundCaptureImageEx"},
{6, nullptr, "GetLastApplicationCaptureImageEx"},
{7, D<&IDisplayController::GetCallerAppletCaptureImageEx>, "GetCallerAppletCaptureImageEx"},
{8, D<&IDisplayController::TakeScreenShotOfOwnLayer>, "TakeScreenShotOfOwnLayer"},
{9, nullptr, "CopyBetweenCaptureBuffers"},
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
{20, D<&IDisplayController::ClearCaptureBuffer>, "ClearCaptureBuffer"},
{21, nullptr, "ClearAppletTransitionBuffer"},
{22, D<&IDisplayController::AcquireLastApplicationCaptureSharedBuffer>, "AcquireLastApplicationCaptureSharedBuffer"},
{23, D<&IDisplayController::ReleaseLastApplicationCaptureSharedBuffer>, "ReleaseLastApplicationCaptureSharedBuffer"},
{24, D<&IDisplayController::AcquireLastForegroundCaptureSharedBuffer>, "AcquireLastForegroundCaptureSharedBuffer"},
{25, D<&IDisplayController::ReleaseLastForegroundCaptureSharedBuffer>, "ReleaseLastForegroundCaptureSharedBuffer"},
{26, D<&IDisplayController::AcquireCallerAppletCaptureSharedBuffer>, "AcquireCallerAppletCaptureSharedBuffer"},
{27, D<&IDisplayController::ReleaseCallerAppletCaptureSharedBuffer>, "ReleaseCallerAppletCaptureSharedBuffer"},
{28, nullptr, "TakeScreenShotOfOwnLayerEx"},
};
// clang-format on
RegisterHandlers(functions);
}
IDisplayController::~IDisplayController() = default;
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -35,7 +35,6 @@ private:
Out<s32> out_fbshare_layer_index);
Result ReleaseLastApplicationCaptureSharedBuffer();
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
const std::shared_ptr<Applet> applet;
};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,28 +7,28 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IGlobalStateController::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, nullptr, "RequestToEnterSleep"},
FunctionInfo{1, nullptr, "EnterSleep"},
FunctionInfo{2, nullptr, "StartSleepSequence"},
FunctionInfo{3, D<&IGlobalStateController::StartShutdownSequence>, "StartShutdownSequence"},
FunctionInfo{4, D<&IGlobalStateController::StartRebootSequence>, "StartRebootSequence"},
FunctionInfo{9, nullptr, "IsAutoPowerDownRequested"},
FunctionInfo{10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
FunctionInfo{11, nullptr, "NotifyCecSettingsChanged"},
FunctionInfo{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
FunctionInfo{13, nullptr, "UpdateDefaultDisplayResolution"},
FunctionInfo{14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"},
FunctionInfo{15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"},
FunctionInfo{30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"}
);
return HandlerTableGenerateWithFind(key, functions);
}
IGlobalStateController::IGlobalStateController(Core::System& system_)
: ServiceFramework{system_, "IGlobalStateController"},
m_context{system_, "IGlobalStateController"}, m_hdcp_authentication_failed_event{m_context} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestToEnterSleep"},
{1, nullptr, "EnterSleep"},
{2, nullptr, "StartSleepSequence"},
{3, D<&IGlobalStateController::StartShutdownSequence>, "StartShutdownSequence"},
{4, D<&IGlobalStateController::StartRebootSequence>, "StartRebootSequence"},
{9, nullptr, "IsAutoPowerDownRequested"},
{10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
{11, nullptr, "NotifyCecSettingsChanged"},
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},
{13, nullptr, "UpdateDefaultDisplayResolution"},
{14, D<&IGlobalStateController::ShouldSleepOnBoot>, "ShouldSleepOnBoot"},
{15, D<&IGlobalStateController::GetHdcpAuthenticationFailedEvent>, "GetHdcpAuthenticationFailedEvent"},
{30, D<&IGlobalStateController::OpenCradleFirmwareUpdater>, "OpenCradleFirmwareUpdater"},
};
// clang-format on
RegisterHandlers(functions);
}
Result IGlobalStateController::StartShutdownSequence() {
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -26,9 +23,9 @@ private:
Result LoadAndApplyIdlePolicySettings();
Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);
Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result OpenCradleFirmwareUpdater(Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater);
Result OpenCradleFirmwareUpdater(
Out<SharedPointer<ICradleFirmwareUpdater>> out_cradle_firmware_updater);
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
KernelHelpers::ServiceContext m_context;
Event m_hdcp_authentication_failed_event;
};
@@ -14,31 +14,31 @@
namespace Service::AM {
std::optional<ServiceFrameworkBase::FunctionInfoBase> IHomeMenuFunctions::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
FunctionInfo{11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"},
FunctionInfo{12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"},
FunctionInfo{20, D<&IHomeMenuFunctions::PopFromGeneralChannel>, "PopFromGeneralChannel"},
FunctionInfo{21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"},
FunctionInfo{30, nullptr, "GetHomeButtonWriterLockAccessor"},
FunctionInfo{31, nullptr, "GetWriterLockAccessorEx"},
FunctionInfo{40, D<&IHomeMenuFunctions::IsSleepEnabled>, "IsSleepEnabled"},
FunctionInfo{41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"},
FunctionInfo{50, nullptr, "LaunchSystemApplet"},
FunctionInfo{51, nullptr, "LaunchStarter"},
FunctionInfo{100, nullptr, "PopRequestLaunchApplicationForDebug"},
FunctionInfo{110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"},
FunctionInfo{200, nullptr, "LaunchDevMenu"},
FunctionInfo{1000, nullptr, "SetLastApplicationExitReason"}
);
return HandlerTableGenerateWithFind(key, functions);
}
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet,
WindowSystem& window_system)
: ServiceFramework{system_, "IHomeMenuFunctions"}, m_window_system{window_system},
m_applet{std::move(applet)}, m_context{system, "IHomeMenuFunctions"} {
// clang-format off
static const FunctionInfo functions[] = {
{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
{11, D<&IHomeMenuFunctions::LockForeground>, "LockForeground"},
{12, D<&IHomeMenuFunctions::UnlockForeground>, "UnlockForeground"},
{20, D<&IHomeMenuFunctions::PopFromGeneralChannel>, "PopFromGeneralChannel"},
{21, D<&IHomeMenuFunctions::GetPopFromGeneralChannelEvent>, "GetPopFromGeneralChannelEvent"},
{30, nullptr, "GetHomeButtonWriterLockAccessor"},
{31, nullptr, "GetWriterLockAccessorEx"},
{40, D<&IHomeMenuFunctions::IsSleepEnabled>, "IsSleepEnabled"},
{41, D<&IHomeMenuFunctions::IsRebootEnabled>, "IsRebootEnabled"},
{50, nullptr, "LaunchSystemApplet"},
{51, nullptr, "LaunchStarter"},
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
{110, D<&IHomeMenuFunctions::IsForceTerminateApplicationDisabledForDebug>, "IsForceTerminateApplicationDisabledForDebug"},
{200, nullptr, "LaunchDevMenu"},
{1000, nullptr, "SetLastApplicationExitReason"},
};
// clang-format on
RegisterHandlers(functions);
}
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
@@ -34,7 +34,6 @@ private:
Result IsForceTerminateApplicationDisabledForDebug(
Out<bool> out_is_force_terminate_application_disabled_for_debug);
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
WindowSystem& m_window_system;
const std::shared_ptr<Applet> m_applet;
KernelHelpers::ServiceContext m_context;
@@ -17,7 +17,9 @@
namespace Service::AM {
static void EnableSingleUserPlay(const std::shared_ptr<LibraryAppletStorage>& impl) {
namespace {
void EnableSingleUserPlay(const std::shared_ptr<LibraryAppletStorage>& impl) {
constexpr s64 DisplayOptionsOffset = 0x90;
constexpr s64 IsSkipEnabledOffset = 1;
constexpr s64 ShowSkipButtonOffset = 4;
@@ -27,7 +29,7 @@ static void EnableSingleUserPlay(const std::shared_ptr<LibraryAppletStorage>& im
impl->Write(DisplayOptionsOffset + ShowSkipButtonOffset, &enabled, sizeof(enabled));
}
static void ReplaceEmptyUuidWithCurrentUser(const std::shared_ptr<LibraryAppletStorage>& impl) {
void ReplaceEmptyUuidWithCurrentUser(const std::shared_ptr<LibraryAppletStorage>& impl) {
Frontend::UiReturnArg return_arg{};
impl->Read(0, &return_arg, sizeof(return_arg));
@@ -45,40 +47,42 @@ static void ReplaceEmptyUuidWithCurrentUser(const std::shared_ptr<LibraryAppletS
}
}
std::optional<ServiceFrameworkBase::FunctionInfoBase> ILibraryAppletAccessor::FindRequest(u32 key) {
static constexpr auto functions = CreateStaticMap(
FunctionInfo{0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
FunctionInfo{1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"},
FunctionInfo{10, D<&ILibraryAppletAccessor::Start>, "Start"},
FunctionInfo{20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"},
FunctionInfo{25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"},
FunctionInfo{30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"},
FunctionInfo{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
FunctionInfo{60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero", MakeVersionGate({10,0,0})},
FunctionInfo{80, nullptr, "RequestForLibraryAppletToGetForeground", MakeVersionGate({19,0,0})},
FunctionInfo{81, nullptr, "GetCurrentChildLibraryApplet", MakeVersionGate({19,0,0})},
FunctionInfo{90, D<&ILibraryAppletAccessor::Unknown90>, "Unknown90", MakeVersionGate({20,0,0})},
FunctionInfo{100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"},
FunctionInfo{101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"},
FunctionInfo{102, nullptr, "PushExtraStorage"},
FunctionInfo{103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"},
FunctionInfo{104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"},
FunctionInfo{105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
FunctionInfo{106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
FunctionInfo{110, nullptr, "NeedsToExitProcess"},
FunctionInfo{120, D<&ILibraryAppletAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
FunctionInfo{150, nullptr, "RequestForAppletToGetForeground"},
FunctionInfo{160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle", MakeVersionGate({2,0,0})},
FunctionInfo{170, D<&ILibraryAppletAccessor::Unknown170>, "Unknown170", MakeVersionGate({22,0,0})}
);
return HandlerTableGenerateWithFind(key, functions);
}
} // namespace
ILibraryAppletAccessor::ILibraryAppletAccessor(Core::System& system_,
std::shared_ptr<AppletDataBroker> broker,
std::shared_ptr<Applet> applet)
: ServiceFramework{system_, "ILibraryAppletAccessor"}, m_broker{std::move(broker)},
m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ILibraryAppletAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
{1, D<&ILibraryAppletAccessor::IsCompleted>, "IsCompleted"},
{10, D<&ILibraryAppletAccessor::Start>, "Start"},
{20, D<&ILibraryAppletAccessor::RequestExit>, "RequestExit"},
{25, D<&ILibraryAppletAccessor::Terminate>, "Terminate"},
{30, D<&ILibraryAppletAccessor::GetResult>, "GetResult"},
{50, nullptr, "SetOutOfFocusApplicationSuspendingEnabled"},
{60, D<&ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero>, "PresetLibraryAppletGpuTimeSliceZero"}, //10.0.0+
{80, nullptr, "RequestForLibraryAppletToGetForeground"}, //19.0.0+
{81, nullptr, "GetCurrentChildLibraryApplet"}, //19.0.0+
{90, D<&ILibraryAppletAccessor::Unknown90>, "Unknown90"}, //20.0.0+
{100, D<&ILibraryAppletAccessor::PushInData>, "PushInData"},
{101, D<&ILibraryAppletAccessor::PopOutData>, "PopOutData"},
{102, nullptr, "PushExtraStorage"},
{103, D<&ILibraryAppletAccessor::PushInteractiveInData>, "PushInteractiveInData"},
{104, D<&ILibraryAppletAccessor::PopInteractiveOutData>, "PopInteractiveOutData"},
{105, D<&ILibraryAppletAccessor::GetPopOutDataEvent>, "GetPopOutDataEvent"},
{106, D<&ILibraryAppletAccessor::GetPopInteractiveOutDataEvent>, "GetPopInteractiveOutDataEvent"},
{110, nullptr, "NeedsToExitProcess"},
{120, D<&ILibraryAppletAccessor::GetLibraryAppletInfo>, "GetLibraryAppletInfo"},
{150, nullptr, "RequestForAppletToGetForeground"},
{160, D<&ILibraryAppletAccessor::GetIndirectLayerConsumerHandle>, "GetIndirectLayerConsumerHandle"}, //2.0.0+
{170, D<&ILibraryAppletAccessor::Unknown170>, "Unknown170"}, //22.0.0+
};
// clang-format on
RegisterHandlers(functions);
}
ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
@@ -6,6 +6,7 @@
#pragma once
#include "core/hle/service/am/service/library_applet_self_accessor.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
@@ -15,26 +16,6 @@ class AppletDataBroker;
struct Applet;
class IStorage;
struct LibraryAppletInfo {
AppletId applet_id;
LibraryAppletMode library_applet_mode;
};
static_assert(sizeof(LibraryAppletInfo) == 0x8, "LibraryAppletInfo has incorrect size.");
struct ErrorCode {
u32 category;
u32 number;
};
static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
struct ErrorContext {
u8 type;
INSERT_PADDING_BYTES_NOINIT(0x7);
std::array<u8, 0x1f4> data;
Result result;
};
static_assert(sizeof(ErrorContext) == 0x200, "ErrorContext has incorrect size.");
class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
public:
explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<AppletDataBroker> broker,
@@ -68,7 +49,6 @@ private:
void FrontendExecuteInteractive();
void FrontendRequestExit();
std::optional<FunctionInfoBase> FindRequest(u32 key) override;
const std::shared_ptr<AppletDataBroker> m_broker;
const std::shared_ptr<Applet> m_applet;
};
@@ -0,0 +1,287 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/am/applet_data_broker.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/frontend/applets.h"
#include "core/hle/service/am/library_applet_storage.h"
#include "core/hle/service/am/process_creation.h"
#include "core/hle/service/am/service/library_applet_accessor.h"
#include "core/hle/service/am/service/library_applet_creator.h"
#include "core/hle/api_version.h"
#include "core/hle/service/am/service/storage.h"
#include "core/hle/service/am/window_system.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/sm/sm.h"
namespace Service::AM {
namespace {
bool ShouldCreateGuestApplet(AppletId applet_id) {
#define X(Name, name) \
if (applet_id == AppletId::Name && \
Settings::values.name##_applet_mode.GetValue() != Settings::AppletMode::LLE) { \
return false; \
}
X(Cabinet, cabinet)
X(Controller, controller)
X(DataErase, data_erase)
X(Error, error)
X(NetConnect, net_connect)
X(ProfileSelect, player_select)
X(SoftwareKeyboard, swkbd)
X(MiiEdit, mii_edit)
X(Web, web)
X(Shop, shop)
X(PhotoViewer, photo_viewer)
X(OfflineWeb, offline_web)
X(LoginShare, login_share)
X(WebAuth, wifi_web_auth)
X(MyPage, my_page)
#undef X
return true;
}
AppletProgramId AppletIdToProgramId(AppletId applet_id) {
switch (applet_id) {
case AppletId::OverlayDisplay:
return AppletProgramId::OverlayDisplay;
case AppletId::QLaunch:
return AppletProgramId::QLaunch;
case AppletId::Starter:
return AppletProgramId::Starter;
case AppletId::Auth:
return AppletProgramId::Auth;
case AppletId::Cabinet:
return AppletProgramId::Cabinet;
case AppletId::Controller:
return AppletProgramId::Controller;
case AppletId::DataErase:
return AppletProgramId::DataErase;
case AppletId::Error:
return AppletProgramId::Error;
case AppletId::NetConnect:
return AppletProgramId::NetConnect;
case AppletId::ProfileSelect:
return AppletProgramId::ProfileSelect;
case AppletId::SoftwareKeyboard:
return AppletProgramId::SoftwareKeyboard;
case AppletId::MiiEdit:
return AppletProgramId::MiiEdit;
case AppletId::Web:
return AppletProgramId::Web;
case AppletId::Shop:
return AppletProgramId::Shop;
case AppletId::PhotoViewer:
return AppletProgramId::PhotoViewer;
case AppletId::Settings:
return AppletProgramId::Settings;
case AppletId::OfflineWeb:
return AppletProgramId::OfflineWeb;
case AppletId::LoginShare:
return AppletProgramId::LoginShare;
case AppletId::WebAuth:
return AppletProgramId::WebAuth;
case AppletId::MyPage:
return AppletProgramId::MyPage;
default:
return static_cast<AppletProgramId>(0);
}
}
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
if (program_id == 0) {
// Unknown applet
return {};
}
auto process = CreateProcess(system, program_id, 1, HLE::ApiVersion::HOS_VERSION_MAJOR);
if (process) {
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden;
auto broker = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = broker;
{
std::scoped_lock lk{caller_applet->lock};
caller_applet->child_applets.push_back(applet);
}
window_system.TrackApplet(applet, false);
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
}
// Couldn't initialize the guest process
return {};
}
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
auto process = std::make_unique<Process>(system);
auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
auto storage = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = storage;
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
{
std::scoped_lock lk{caller_applet->lock};
caller_applet->child_applets.push_back(applet);
}
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
}
} // namespace
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
WindowSystem& window_system)
: ServiceFramework{system_, "ILibraryAppletCreator"},
m_window_system{window_system}, m_applet{std::move(applet)} {
static const FunctionInfo functions[] = {
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
{1, nullptr, "TerminateAllLibraryApplets"},
{2, nullptr, "AreAnyLibraryAppletsLeft"},
{3, D<&ILibraryAppletCreator::CreateLibraryAppletEx>, "CreateLibraryAppletEx"},
{10, D<&ILibraryAppletCreator::CreateStorage>, "CreateStorage"},
{11, D<&ILibraryAppletCreator::CreateTransferMemoryStorage>, "CreateTransferMemoryStorage"},
{12, D<&ILibraryAppletCreator::CreateHandleStorage>, "CreateHandleStorage"},
};
RegisterHandlers(functions);
}
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
Result ILibraryAppletCreator::CreateLibraryApplet(
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
LibraryAppletMode library_applet_mode) {
LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={}", applet_id,
library_applet_mode);
std::shared_ptr<ILibraryAppletAccessor> library_applet;
if (ShouldCreateGuestApplet(applet_id)) {
library_applet =
CreateGuestApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
}
if (!library_applet) {
library_applet =
CreateFrontendApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
}
if (!library_applet) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
R_THROW(ResultUnknown);
}
// Applet is created, can now be launched.
m_applet->library_applet_launchable_event.Signal(system.Kernel());
*out_library_applet_accessor = library_applet;
R_SUCCEED();
}
Result ILibraryAppletCreator::CreateLibraryAppletEx(
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
LibraryAppletMode library_applet_mode, u64 thread_id) {
LOG_DEBUG(Service_AM, "called with applet_id={} applet_mode={} thread_id={}", applet_id,
library_applet_mode, thread_id);
std::shared_ptr<ILibraryAppletAccessor> library_applet;
if (ShouldCreateGuestApplet(applet_id)) {
library_applet =
CreateGuestApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
}
if (!library_applet) {
library_applet =
CreateFrontendApplet(system, m_window_system, m_applet, applet_id, library_applet_mode);
}
if (!library_applet) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
R_THROW(ResultUnknown);
}
// Applet is created, can now be launched.
m_applet->library_applet_launchable_event.Signal(system.Kernel());
*out_library_applet_accessor = library_applet;
R_SUCCEED();
}
Result ILibraryAppletCreator::CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size) {
LOG_DEBUG(Service_AM, "called, size={}", size);
if (size <= 0) {
LOG_ERROR(Service_AM, "size is less than or equal to 0");
R_THROW(ResultUnknown);
}
*out_storage = std::make_shared<IStorage>(system, AM::CreateStorage(std::vector<u8>(size)));
R_SUCCEED();
}
Result ILibraryAppletCreator::CreateTransferMemoryStorage(
Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
LOG_DEBUG(Service_AM, "called, is_writable={} size={}", is_writable, size);
if (size <= 0) {
LOG_ERROR(Service_AM, "size is less than or equal to 0");
R_THROW(ResultUnknown);
}
if (!transfer_memory_handle) {
LOG_ERROR(Service_AM, "transfer_memory_handle is null");
R_THROW(ResultUnknown);
}
*out_storage = std::make_shared<IStorage>(
system, AM::CreateTransferMemoryStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(),
transfer_memory_handle.Get(), is_writable, size));
R_SUCCEED();
}
Result ILibraryAppletCreator::CreateHandleStorage(
Out<SharedPointer<IStorage>> out_storage, s64 size,
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle) {
LOG_DEBUG(Service_AM, "called, size={}", size);
if (size <= 0) {
LOG_ERROR(Service_AM, "size is less than or equal to 0");
R_THROW(ResultUnknown);
}
if (!transfer_memory_handle) {
LOG_ERROR(Service_AM, "transfer_memory_handle is null");
R_THROW(ResultUnknown);
}
*out_storage = std::make_shared<IStorage>(
system, AM::CreateHandleStorage(system.Kernel(), transfer_memory_handle->GetOwner()->GetMemory(),
transfer_memory_handle.Get(), size));
R_SUCCEED();
}
} // namespace Service::AM
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/am/am_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::AM {
struct Applet;
class ILibraryAppletAccessor;
class IStorage;
class WindowSystem;
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
public:
explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
WindowSystem& window_system);
~ILibraryAppletCreator() override;
private:
Result CreateLibraryApplet(
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
LibraryAppletMode library_applet_mode);
Result CreateLibraryAppletEx(
Out<SharedPointer<ILibraryAppletAccessor>> out_library_applet_accessor, AppletId applet_id,
LibraryAppletMode library_applet_mode, u64 thread_id);
Result CreateStorage(Out<SharedPointer<IStorage>> out_storage, s64 size);
Result CreateTransferMemoryStorage(
Out<SharedPointer<IStorage>> out_storage, bool is_writable, s64 size,
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
WindowSystem& m_window_system;
const std::shared_ptr<Applet> m_applet;
};
} // namespace Service::AM
@@ -0,0 +1,134 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/am/service/applet_common_functions.h"
#include "core/hle/service/am/service/audio_controller.h"
#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/global_state_controller.h"
#include "core/hle/service/am/service/home_menu_functions.h"
#include "core/hle/service/am/service/library_applet_creator.h"
#include "core/hle/service/am/service/library_applet_proxy.h"
#include "core/hle/service/am/service/library_applet_self_accessor.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"
#include "core/hle/service/cmif_serialization.h"
namespace Service::AM {
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
Kernel::KProcess* process, WindowSystem& window_system)
: ServiceFramework{system_, "ILibraryAppletProxy"},
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
{1, D<&ILibraryAppletProxy::GetSelfController>, "GetSelfController"},
{2, D<&ILibraryAppletProxy::GetWindowController>, "GetWindowController"},
{3, D<&ILibraryAppletProxy::GetAudioController>, "GetAudioController"},
{4, D<&ILibraryAppletProxy::GetDisplayController>, "GetDisplayController"},
{10, D<&ILibraryAppletProxy::GetProcessWindingController>, "GetProcessWindingController"},
{11, D<&ILibraryAppletProxy::GetLibraryAppletCreator>, "GetLibraryAppletCreator"},
{20, D<&ILibraryAppletProxy::OpenLibraryAppletSelfAccessor>, "OpenLibraryAppletSelfAccessor"},
{21, D<&ILibraryAppletProxy::GetAppletCommonFunctions>, "GetAppletCommonFunctions"},
{22, D<&ILibraryAppletProxy::GetHomeMenuFunctions>, "GetHomeMenuFunctions"},
{23, D<&ILibraryAppletProxy::GetGlobalStateController>, "GetGlobalStateController"},
{1000, D<&ILibraryAppletProxy::GetDebugFunctions>, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}
ILibraryAppletProxy::~ILibraryAppletProxy() = default;
Result ILibraryAppletProxy::GetAudioController(
Out<SharedPointer<IAudioController>> out_audio_controller) {
LOG_DEBUG(Service_AM, "called");
*out_audio_controller = std::make_shared<IAudioController>(system);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetDisplayController(
Out<SharedPointer<IDisplayController>> out_display_controller) {
LOG_DEBUG(Service_AM, "called");
*out_display_controller = std::make_shared<IDisplayController>(system, m_applet);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetProcessWindingController(
Out<SharedPointer<IProcessWindingController>> out_process_winding_controller) {
LOG_DEBUG(Service_AM, "called");
*out_process_winding_controller = std::make_shared<IProcessWindingController>(system, m_applet);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetDebugFunctions(
Out<SharedPointer<IDebugFunctions>> out_debug_functions) {
LOG_DEBUG(Service_AM, "called");
*out_debug_functions = std::make_shared<IDebugFunctions>(system);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetWindowController(
Out<SharedPointer<IWindowController>> out_window_controller) {
LOG_DEBUG(Service_AM, "called");
*out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetSelfController(
Out<SharedPointer<ISelfController>> out_self_controller) {
LOG_DEBUG(Service_AM, "called");
*out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetCommonStateGetter(
Out<SharedPointer<ICommonStateGetter>> out_common_state_getter) {
LOG_DEBUG(Service_AM, "called");
*out_common_state_getter = std::make_shared<ICommonStateGetter>(system, m_applet);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetLibraryAppletCreator(
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
LOG_DEBUG(Service_AM, "called");
*out_library_applet_creator =
std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system);
R_SUCCEED();
}
Result ILibraryAppletProxy::OpenLibraryAppletSelfAccessor(
Out<SharedPointer<ILibraryAppletSelfAccessor>> out_library_applet_self_accessor) {
LOG_DEBUG(Service_AM, "called");
*out_library_applet_self_accessor =
std::make_shared<ILibraryAppletSelfAccessor>(system, m_applet);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetAppletCommonFunctions(
Out<SharedPointer<IAppletCommonFunctions>> out_applet_common_functions) {
LOG_DEBUG(Service_AM, "called");
*out_applet_common_functions = std::make_shared<IAppletCommonFunctions>(system, m_applet);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetHomeMenuFunctions(
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
LOG_DEBUG(Service_AM, "called");
*out_home_menu_functions =
std::make_shared<IHomeMenuFunctions>(system, m_applet, m_window_system);
R_SUCCEED();
}
Result ILibraryAppletProxy::GetGlobalStateController(
Out<SharedPointer<IGlobalStateController>> out_global_state_controller) {
LOG_DEBUG(Service_AM, "called");
*out_global_state_controller = std::make_shared<IGlobalStateController>(system);
R_SUCCEED();
}
} // namespace Service::AM

Some files were not shown because too many files have changed in this diff Show More