early-access version 4160

This commit is contained in:
pineappleEA 2024-02-22 23:02:19 +01:00
parent cb22e3fb42
commit 89a3ee2eed
106 changed files with 4263 additions and 1073 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 4158. This is the source code for early-access 4160.
## Legal Notice ## Legal Notice

View file

@ -121,6 +121,7 @@ else()
-Wno-attributes -Wno-attributes
-Wno-invalid-offsetof -Wno-invalid-offsetof
-Wno-unused-parameter -Wno-unused-parameter
-Wno-missing-field-initializers
) )
if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang if (CMAKE_CXX_COMPILER_ID MATCHES Clang) # Clang or AppleClang

View file

@ -668,7 +668,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
ASSERT(user_id); ASSERT(user_id);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfs_nand_dir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, 1, {}, vfs_nand_dir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, 1,
user_id->AsU128(), 0); user_id->AsU128(), 0);
const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path); const auto full_path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);
@ -836,8 +836,8 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j
FileSys::OpenMode::Read); FileSys::OpenMode::Read);
const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(
{}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, {}, vfsNandDir, FileSys::SaveDataSpaceId::User, FileSys::SaveDataType::Account, program_id,
program_id, user_id->AsU128(), 0); user_id->AsU128(), 0);
return Common::Android::ToJString(env, user_save_data_path); return Common::Android::ToJString(env, user_save_data_path);
} }

View file

@ -73,16 +73,15 @@ void Manager::BufferReleaseAndRegister() {
} }
} }
u32 Manager::GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names,
[[maybe_unused]] const u32 max_count,
[[maybe_unused]] const bool filter) { [[maybe_unused]] const bool filter) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LinkToManager(); LinkToManager();
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)}; auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (input_devices.size() > 1) { if (!input_devices.empty() && !names.empty()) {
names.emplace_back("Uac"); names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
return 1; return 1;
} }
return 0; return 0;

View file

@ -60,13 +60,11 @@ public:
* Get a list of audio in device names. * Get a list of audio in device names.
* *
* @param names - Output container to write names to. * @param names - Output container to write names to.
* @param max_count - Maximum number of device names to write. Unused
* @param filter - Should the list be filtered? Unused. * @param filter - Should the list be filtered? Unused.
* *
* @return Number of names written. * @return Number of names written.
*/ */
u32 GetDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names, u32 max_count, u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
bool filter);
/// Core system /// Core system
Core::System& system; Core::System& system;

View file

@ -146,11 +146,11 @@ public:
break; break;
} }
tags[released++] = tag;
if (released >= tags.size()) { if (released >= tags.size()) {
break; break;
} }
tags[released++] = tag;
} }
return released; return released;

View file

@ -28,8 +28,8 @@ OpusDecoder::~OpusDecoder() {
} }
} }
Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, Result OpusDecoder::Initialize(const OpusParametersEx& params,
u64 transfer_memory_size) { Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
auto frame_size{params.use_large_frame_size ? 5760 : 1920}; auto frame_size{params.use_large_frame_size ? 5760 : 1920};
shared_buffer_size = transfer_memory_size; shared_buffer_size = transfer_memory_size;
shared_buffer = std::make_unique<u8[]>(shared_buffer_size); shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
@ -59,7 +59,7 @@ Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory
R_SUCCEED(); R_SUCCEED();
} }
Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, Result OpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
auto frame_size{params.use_large_frame_size ? 5760 : 1920}; auto frame_size{params.use_large_frame_size ? 5760 : 1920};
shared_buffer_size = transfer_memory_size; shared_buffer_size = transfer_memory_size;

View file

@ -22,10 +22,10 @@ public:
explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_); explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
~OpusDecoder(); ~OpusDecoder();
Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, Result Initialize(const OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size);
Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size); u64 transfer_memory_size);
Result Initialize(const OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count, Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
std::span<const u8> input_data, std::span<u8> output_data, bool reset); std::span<const u8> input_data, std::span<u8> output_data, bool reset);
Result SetContext([[maybe_unused]] std::span<const u8> context); Result SetContext([[maybe_unused]] std::span<const u8> context);

View file

@ -38,7 +38,7 @@ OpusDecoderManager::OpusDecoderManager(Core::System& system_)
} }
} }
Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { Result OpusDecoderManager::GetWorkBufferSize(const OpusParameters& params, u32& out_size) {
OpusParametersEx ex{ OpusParametersEx ex{
.sample_rate = params.sample_rate, .sample_rate = params.sample_rate,
.channel_count = params.channel_count, .channel_count = params.channel_count,
@ -47,11 +47,11 @@ Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_si
R_RETURN(GetWorkBufferSizeExEx(ex, out_size)); R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
} }
Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { Result OpusDecoderManager::GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size) {
R_RETURN(GetWorkBufferSizeExEx(params, out_size)); R_RETURN(GetWorkBufferSizeExEx(params, out_size));
} }
Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { Result OpusDecoderManager::GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size) {
R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount); R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
@ -63,8 +63,8 @@ Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64&
R_SUCCEED(); R_SUCCEED();
} }
Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params,
u64& out_size) { u32& out_size) {
OpusMultiStreamParametersEx ex{ OpusMultiStreamParametersEx ex{
.sample_rate = params.sample_rate, .sample_rate = params.sample_rate,
.channel_count = params.channel_count, .channel_count = params.channel_count,
@ -76,13 +76,13 @@ Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParame
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size)); R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
} }
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
u64& out_size) { const OpusMultiStreamParametersEx& params, u32& out_size) {
R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size)); R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
} }
Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
u64& out_size) { const OpusMultiStreamParametersEx& params, u32& out_size) {
R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount); R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count, R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,

View file

@ -22,17 +22,19 @@ public:
return hardware_opus; return hardware_opus;
} }
Result GetWorkBufferSize(OpusParameters& params, u64& out_size); Result GetWorkBufferSize(const OpusParameters& params, u32& out_size);
Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size); Result GetWorkBufferSizeEx(const OpusParametersEx& params, u32& out_size);
Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size); Result GetWorkBufferSizeExEx(const OpusParametersEx& params, u32& out_size);
Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size); Result GetWorkBufferSizeForMultiStream(const OpusMultiStreamParameters& params, u32& out_size);
Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size); Result GetWorkBufferSizeForMultiStreamEx(const OpusMultiStreamParametersEx& params,
Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size); u32& out_size);
Result GetWorkBufferSizeForMultiStreamExEx(const OpusMultiStreamParametersEx& params,
u32& out_size);
private: private:
Core::System& system; Core::System& system;
HardwareOpus hardware_opus; HardwareOpus hardware_opus;
std::array<u64, MaxChannels> required_workbuffer_sizes{}; std::array<u32, MaxChannels> required_workbuffer_sizes{};
}; };
} // namespace AudioCore::OpusDecoder } // namespace AudioCore::OpusDecoder

View file

@ -42,7 +42,7 @@ HardwareOpus::HardwareOpus(Core::System& system_)
opus_decoder.SetSharedMemory(shared_memory); opus_decoder.SetSharedMemory(shared_memory);
} }
u64 HardwareOpus::GetWorkBufferSize(u32 channel) { u32 HardwareOpus::GetWorkBufferSize(u32 channel) {
if (!opus_decoder.IsRunning()) { if (!opus_decoder.IsRunning()) {
return 0; return 0;
} }
@ -55,10 +55,10 @@ u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg); ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
return 0; return 0;
} }
return shared_memory.dsp_return_data[0]; return static_cast<u32>(shared_memory.dsp_return_data[0]);
} }
u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { u32 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
shared_memory.host_send_data[0] = total_stream_count; shared_memory.host_send_data[0] = total_stream_count;
shared_memory.host_send_data[1] = stereo_stream_count; shared_memory.host_send_data[1] = stereo_stream_count;
@ -70,7 +70,7 @@ u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 st
ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg); ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
return 0; return 0;
} }
return shared_memory.dsp_return_data[0]; return static_cast<u32>(shared_memory.dsp_return_data[0]);
} }
Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
@ -94,8 +94,9 @@ Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count,
Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
u32 total_stream_count, u32 total_stream_count,
u32 stereo_stream_count, void* mappings, u32 stereo_stream_count,
void* buffer, u64 buffer_size) { const void* mappings, void* buffer,
u64 buffer_size) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
shared_memory.host_send_data[0] = (u64)buffer; shared_memory.host_send_data[0] = (u64)buffer;
shared_memory.host_send_data[1] = buffer_size; shared_memory.host_send_data[1] = buffer_size;

View file

@ -16,14 +16,14 @@ class HardwareOpus {
public: public:
HardwareOpus(Core::System& system); HardwareOpus(Core::System& system);
u64 GetWorkBufferSize(u32 channel); u32 GetWorkBufferSize(u32 channel);
u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count); u32 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
u64 buffer_size); u64 buffer_size);
Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
u32 totaL_stream_count, u32 stereo_stream_count, u32 totaL_stream_count, u32 stereo_stream_count,
void* mappings, void* buffer, u64 buffer_size); const void* mappings, void* buffer, u64 buffer_size);
Result ShutdownDecodeObject(void* buffer, u64 buffer_size); Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size); Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size, Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,

View file

@ -20,7 +20,7 @@ struct OpusParametersEx {
/* 0x00 */ u32 sample_rate; /* 0x00 */ u32 sample_rate;
/* 0x04 */ u32 channel_count; /* 0x04 */ u32 channel_count;
/* 0x08 */ bool use_large_frame_size; /* 0x08 */ bool use_large_frame_size;
/* 0x09 */ INSERT_PADDING_BYTES(7); /* 0x09 */ INSERT_PADDING_BYTES_NOINIT(7);
}; // size = 0x10 }; // size = 0x10
static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!"); static_assert(sizeof(OpusParametersEx) == 0x10, "OpusParametersEx has the wrong size!");
@ -40,7 +40,7 @@ struct OpusMultiStreamParametersEx {
/* 0x08 */ u32 total_stream_count; /* 0x08 */ u32 total_stream_count;
/* 0x0C */ u32 stereo_stream_count; /* 0x0C */ u32 stereo_stream_count;
/* 0x10 */ bool use_large_frame_size; /* 0x10 */ bool use_large_frame_size;
/* 0x11 */ INSERT_PADDING_BYTES(7); /* 0x11 */ INSERT_PADDING_BYTES_NOINIT(7);
/* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings; /* 0x18 */ std::array<u8, OpusStreamCountMax + 1> mappings;
}; // size = 0x118 }; // size = 0x118
static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118, static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,

View file

@ -36,8 +36,7 @@ AudioDevice::AudioDevice(Core::System& system, const u64 applet_resource_user_id
: output_sink{system.AudioCore().GetOutputSink()}, : output_sink{system.AudioCore().GetOutputSink()},
applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {} applet_resource_user_id{applet_resource_user_id_}, user_revision{revision} {}
u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, u32 AudioDevice::ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const {
const size_t max_count) const {
std::span<const AudioDeviceName> names{}; std::span<const AudioDeviceName> names{};
if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) { if (CheckFeatureSupported(SupportTags::AudioUsbDeviceOutput, user_revision)) {
@ -46,19 +45,18 @@ u32 AudioDevice::ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer,
names = device_names; names = device_names;
} }
const u32 out_count{static_cast<u32>(std::min(max_count, names.size()))}; const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), names.size()))};
for (u32 i = 0; i < out_count; i++) { for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(names[i]); out_buffer[i] = names[i];
} }
return out_count; return out_count;
} }
u32 AudioDevice::ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, u32 AudioDevice::ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const {
const size_t max_count) const { const u32 out_count{static_cast<u32>(std::min(out_buffer.size(), output_device_names.size()))};
const u32 out_count{static_cast<u32>(std::min(max_count, output_device_names.size()))};
for (u32 i = 0; i < out_count; i++) { for (u32 i = 0; i < out_count; i++) {
out_buffer.push_back(output_device_names[i]); out_buffer[i] = output_device_names[i];
} }
return out_count; return out_count;
} }

View file

@ -36,20 +36,18 @@ public:
* Get a list of the available output devices. * Get a list of the available output devices.
* *
* @param out_buffer - Output buffer to write the available device names. * @param out_buffer - Output buffer to write the available device names.
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written. * @return Number of device names written.
*/ */
u32 ListAudioDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const; u32 ListAudioDeviceName(std::span<AudioDeviceName> out_buffer) const;
/** /**
* Get a list of the available output devices. * Get a list of the available output devices.
* Different to above somehow... * Different to above somehow...
* *
* @param out_buffer - Output buffer to write the available device names. * @param out_buffer - Output buffer to write the available device names.
* @param max_count - Maximum number of devices to write (count of out_buffer).
* @return Number of device names written. * @return Number of device names written.
*/ */
u32 ListAudioOutputDeviceName(std::vector<AudioDeviceName>& out_buffer, size_t max_count) const; u32 ListAudioOutputDeviceName(std::span<AudioDeviceName> out_buffer) const;
/** /**
* Set the volume of all streams in the backend sink. * Set the volume of all streams in the backend sink.

View file

@ -17,9 +17,8 @@ Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* ren
Result Renderer::Initialize(const AudioRendererParameterInternal& params, Result Renderer::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, const u32 process_handle, const u64 transfer_memory_size, Kernel::KProcess* process_handle,
Kernel::KProcess& process, const u64 applet_resource_user_id, const u64 applet_resource_user_id, const s32 session_id) {
const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) { if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) { if (!manager.AddSystem(system)) {
LOG_ERROR(Service_Audio, LOG_ERROR(Service_Audio,
@ -30,7 +29,7 @@ Result Renderer::Initialize(const AudioRendererParameterInternal& params,
} }
initialized = true; initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, process, system.Initialize(params, transfer_memory, transfer_memory_size, process_handle,
applet_resource_user_id, session_id); applet_resource_user_id, session_id);
return ResultSuccess; return ResultSuccess;

View file

@ -38,14 +38,14 @@ public:
* @param params - Input parameters to initialize the system with. * @param params - Input parameters to initialize the system with.
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused. * @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
* @param transfer_memory_size - Size of the transfer memory. Unused. * @param transfer_memory_size - Size of the transfer memory. Unused.
* @param process_handle - Process handle, also used for memory. Unused. * @param process_handle - Process handle, also used for memory.
* @param applet_resource_user_id - Applet id for this renderer. Unused. * @param applet_resource_user_id - Applet id for this renderer. Unused.
* @param session_id - Session id of this renderer. * @param session_id - Session id of this renderer.
* @return Result code. * @return Result code.
*/ */
Result Initialize(const AudioRendererParameterInternal& params, Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, Kernel::KProcess* process_handle, u64 applet_resource_user_id,
s32 session_id); s32 session_id);
/** /**

View file

@ -18,7 +18,7 @@
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_, InfoUpdater::InfoUpdater(std::span<const u8> input_, std::span<u8> output_,
const u32 process_handle_, BehaviorInfo& behaviour_) Kernel::KProcess* process_handle_, BehaviorInfo& behaviour_)
: input{input_.data() + sizeof(UpdateDataHeader)}, : input{input_.data() + sizeof(UpdateDataHeader)},
input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)}, input_origin{input_}, output{output_.data() + sizeof(UpdateDataHeader)},
output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>( output_origin{output_}, in_header{reinterpret_cast<const UpdateDataHeader*>(

View file

@ -8,6 +8,10 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/audio/errors.h" #include "core/hle/service/audio/errors.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
class BehaviorInfo; class BehaviorInfo;
class VoiceContext; class VoiceContext;
@ -39,8 +43,8 @@ class InfoUpdater {
static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!"); static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has the wrong size!");
public: public:
explicit InfoUpdater(std::span<const u8> input, std::span<u8> output, u32 process_handle, explicit InfoUpdater(std::span<const u8> input, std::span<u8> output,
BehaviorInfo& behaviour); Kernel::KProcess* process_handle, BehaviorInfo& behaviour);
/** /**
* Update the voice channel resources. * Update the voice channel resources.
@ -197,7 +201,7 @@ private:
/// Expected output size, see CheckConsumedSize /// Expected output size, see CheckConsumedSize
u64 expected_output_size; u64 expected_output_size;
/// Unused /// Unused
u32 process_handle; Kernel::KProcess* process_handle;
/// Behaviour /// Behaviour
BehaviorInfo& behaviour; BehaviorInfo& behaviour;
}; };

View file

@ -8,11 +8,11 @@
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
PoolMapper::PoolMapper(u32 process_handle_, bool force_map_) PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, bool force_map_)
: process_handle{process_handle_}, force_map{force_map_} {} : process_handle{process_handle_}, force_map{force_map_} {}
PoolMapper::PoolMapper(u32 process_handle_, std::span<MemoryPoolInfo> pool_infos_, u32 pool_count_, PoolMapper::PoolMapper(Kernel::KProcess* process_handle_, std::span<MemoryPoolInfo> pool_infos_,
bool force_map_) u32 pool_count_, bool force_map_)
: process_handle{process_handle_}, pool_infos{pool_infos_.data()}, : process_handle{process_handle_}, pool_infos{pool_infos_.data()},
pool_count{pool_count_}, force_map{force_map_} {} pool_count{pool_count_}, force_map{force_map_} {}
@ -106,15 +106,17 @@ bool PoolMapper::IsForceMapEnabled() const {
return force_map; return force_map;
} }
u32 PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const { Kernel::KProcess* PoolMapper::GetProcessHandle(const MemoryPoolInfo* pool) const {
switch (pool->GetLocation()) { switch (pool->GetLocation()) {
case MemoryPoolInfo::Location::CPU: case MemoryPoolInfo::Location::CPU:
return process_handle; return process_handle;
case MemoryPoolInfo::Location::DSP: case MemoryPoolInfo::Location::DSP:
return Kernel::Svc::CurrentProcess; // return Kernel::Svc::CurrentProcess;
return nullptr;
} }
LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!"); LOG_WARNING(Service_Audio, "Invalid MemoryPoolInfo location!");
return Kernel::Svc::CurrentProcess; // return Kernel::Svc::CurrentProcess;
return nullptr;
} }
bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr, bool PoolMapper::Map([[maybe_unused]] const u32 handle, [[maybe_unused]] const CpuAddr cpu_addr,
@ -147,14 +149,14 @@ bool PoolMapper::Unmap([[maybe_unused]] const u32 handle, [[maybe_unused]] const
} }
bool PoolMapper::Unmap(MemoryPoolInfo& pool) const { bool PoolMapper::Unmap(MemoryPoolInfo& pool) const {
[[maybe_unused]] u32 handle{0}; [[maybe_unused]] Kernel::KProcess* handle{};
switch (pool.GetLocation()) { switch (pool.GetLocation()) {
case MemoryPoolInfo::Location::CPU: case MemoryPoolInfo::Location::CPU:
handle = process_handle; handle = process_handle;
break; break;
case MemoryPoolInfo::Location::DSP: case MemoryPoolInfo::Location::DSP:
handle = Kernel::Svc::CurrentProcess; // handle = Kernel::Svc::CurrentProcess;
break; break;
} }
// nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size); // nn::audio::dsp::UnmapUserPointer(handle, pool->cpu_address, pool->size);

View file

@ -10,6 +10,10 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/audio/errors.h" #include "core/hle/service/audio/errors.h"
namespace Kernel {
class KProcess;
}
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
class AddressInfo; class AddressInfo;
@ -18,9 +22,9 @@ class AddressInfo;
*/ */
class PoolMapper { class PoolMapper {
public: public:
explicit PoolMapper(u32 process_handle, bool force_map); explicit PoolMapper(Kernel::KProcess* process_handle, bool force_map);
explicit PoolMapper(u32 process_handle, std::span<MemoryPoolInfo> pool_infos, u32 pool_count, explicit PoolMapper(Kernel::KProcess* process_handle, std::span<MemoryPoolInfo> pool_infos,
bool force_map); u32 pool_count, bool force_map);
/** /**
* Clear the usage state for all given pools. * Clear the usage state for all given pools.
@ -98,7 +102,7 @@ public:
* @return CurrentProcessHandle if location == DSP, * @return CurrentProcessHandle if location == DSP,
* the PoolMapper's process_handle if location == CPU * the PoolMapper's process_handle if location == CPU
*/ */
u32 GetProcessHandle(const MemoryPoolInfo* pool) const; Kernel::KProcess* GetProcessHandle(const MemoryPoolInfo* pool) const;
/** /**
* Map the given region with the given handle. This is a no-op. * Map the given region with the given handle. This is a no-op.
@ -167,7 +171,7 @@ public:
private: private:
/// Process handle for this mapper, used when location == CPU /// Process handle for this mapper, used when location == CPU
u32 process_handle; Kernel::KProcess* process_handle{};
/// List of memory pools assigned to this mapper /// List of memory pools assigned to this mapper
MemoryPoolInfo* pool_infos{}; MemoryPoolInfo* pool_infos{};
/// The number of pools /// The number of pools

View file

@ -102,8 +102,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
Result System::Initialize(const AudioRendererParameterInternal& params, Result System::Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle_, Kernel::KProcess& process_, Kernel::KProcess* process_handle_, u64 applet_resource_user_id_,
u64 applet_resource_user_id_, s32 session_id_) { s32 session_id_) {
if (!CheckValidRevision(params.revision)) { if (!CheckValidRevision(params.revision)) {
return Service::Audio::ResultInvalidRevision; return Service::Audio::ResultInvalidRevision;
} }
@ -119,7 +119,6 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
behavior.SetUserLibRevision(params.revision); behavior.SetUserLibRevision(params.revision);
process_handle = process_handle_; process_handle = process_handle_;
process = &process_;
applet_resource_user_id = applet_resource_user_id_; applet_resource_user_id = applet_resource_user_id_;
session_id = session_id_; session_id = session_id_;
@ -132,7 +131,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device; render_device = params.rendering_device;
execution_mode = params.execution_mode; execution_mode = params.execution_mode;
process->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(), transfer_memory_size); process_handle->GetMemory().ZeroBlock(transfer_memory->GetSourceAddress(),
transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for. // Note: We're not actually using the transfer memory because it's a pain to code for.
// Allocate the memory normally instead and hope the game doesn't try to read anything back // Allocate the memory normally instead and hope the game doesn't try to read anything back
@ -616,7 +616,7 @@ void System::SendCommandToDsp() {
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 * static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))}; (static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit, audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, process, applet_resource_user_id, process_handle,
reset_command_buffers); reset_command_buffers);
reset_command_buffers = false; reset_command_buffers = false;
command_buffer_size = command_size; command_buffer_size = command_size;

View file

@ -74,14 +74,14 @@ public:
* @param params - Input parameters to initialize the system with. * @param params - Input parameters to initialize the system with.
* @param transfer_memory - Game-supplied memory for all workbuffers. Unused. * @param transfer_memory - Game-supplied memory for all workbuffers. Unused.
* @param transfer_memory_size - Size of the transfer memory. Unused. * @param transfer_memory_size - Size of the transfer memory. Unused.
* @param process_handle - Process handle, also used for memory. Unused. * @param process_handle - Process handle, also used for memory.
* @param applet_resource_user_id - Applet id for this renderer. Unused. * @param applet_resource_user_id - Applet id for this renderer. Unused.
* @param session_id - Session id of this renderer. * @param session_id - Session id of this renderer.
* @return Result code. * @return Result code.
*/ */
Result Initialize(const AudioRendererParameterInternal& params, Result Initialize(const AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
u32 process_handle, Kernel::KProcess& process, u64 applet_resource_user_id, Kernel::KProcess* process_handle, u64 applet_resource_user_id,
s32 session_id); s32 session_id);
/** /**
@ -278,9 +278,7 @@ private:
/// Does what locks do /// Does what locks do
std::mutex lock{}; std::mutex lock{};
/// Process this audio render is operating within, used for memory reads/writes. /// Process this audio render is operating within, used for memory reads/writes.
Kernel::KProcess* process{}; Kernel::KProcess* process_handle{};
/// Handle for the process for this system, unused
u32 process_handle{};
/// Applet resource id for this system, unused /// Applet resource id for this system, unused
u64 applet_resource_user_id{}; u64 applet_resource_user_id{};
/// Controls performance input and output /// Controls performance input and output

View file

@ -38,6 +38,10 @@ std::string StringFromBuffer(std::span<const u8> data) {
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0')); return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
} }
std::string StringFromBuffer(std::span<const char> data) {
return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));
}
// Turns " hej " into "hej". Also handles tabs. // Turns " hej " into "hej". Also handles tabs.
std::string StripSpaces(const std::string& str) { std::string StripSpaces(const std::string& str) {
const std::size_t s = str.find_first_not_of(" \t\r\n"); const std::size_t s = str.find_first_not_of(" \t\r\n");

View file

@ -19,6 +19,7 @@ namespace Common {
[[nodiscard]] std::string ToUpper(std::string str); [[nodiscard]] std::string ToUpper(std::string str);
[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data); [[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
[[nodiscard]] std::string StringFromBuffer(std::span<const char> data);
[[nodiscard]] std::string StripSpaces(const std::string& s); [[nodiscard]] std::string StripSpaces(const std::string& s);
[[nodiscard]] std::string StripQuotes(const std::string& s); [[nodiscard]] std::string StripQuotes(const std::string& s);

View file

@ -58,6 +58,7 @@ add_library(core STATIC
file_sys/fs_operate_range.h file_sys/fs_operate_range.h
file_sys/fs_path.h file_sys/fs_path.h
file_sys/fs_path_utility.h file_sys/fs_path_utility.h
file_sys/fs_save_data_types.h
file_sys/fs_string_util.h file_sys/fs_string_util.h
file_sys/fsa/fs_i_directory.h file_sys/fsa/fs_i_directory.h
file_sys/fsa/fs_i_file.h file_sys/fsa/fs_i_file.h
@ -493,23 +494,33 @@ add_library(core STATIC
hle/service/apm/apm_controller.h hle/service/apm/apm_controller.h
hle/service/apm/apm_interface.cpp hle/service/apm/apm_interface.cpp
hle/service/apm/apm_interface.h hle/service/apm/apm_interface.h
hle/service/audio/audin_u.cpp
hle/service/audio/audin_u.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audio_controller.cpp hle/service/audio/audio_controller.cpp
hle/service/audio/audio_controller.h hle/service/audio/audio_controller.h
hle/service/audio/audout_u.cpp hle/service/audio/audio_device.cpp
hle/service/audio/audout_u.h hle/service/audio/audio_device.h
hle/service/audio/audrec_a.cpp hle/service/audio/audio_in_manager.cpp
hle/service/audio/audrec_a.h hle/service/audio/audio_in_manager.h
hle/service/audio/audrec_u.cpp hle/service/audio/audio_in.cpp
hle/service/audio/audrec_u.h hle/service/audio/audio_in.h
hle/service/audio/audren_u.cpp hle/service/audio/audio_out_manager.cpp
hle/service/audio/audren_u.h hle/service/audio/audio_out_manager.h
hle/service/audio/audio_out.cpp
hle/service/audio/audio_out.h
hle/service/audio/audio_renderer_manager.cpp
hle/service/audio/audio_renderer_manager.h
hle/service/audio/audio_renderer.cpp
hle/service/audio/audio_renderer.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/errors.h hle/service/audio/errors.h
hle/service/audio/hwopus.cpp hle/service/audio/final_output_recorder_manager_for_applet.cpp
hle/service/audio/hwopus.h hle/service/audio/final_output_recorder_manager_for_applet.h
hle/service/audio/final_output_recorder_manager.cpp
hle/service/audio/final_output_recorder_manager.h
hle/service/audio/hardware_opus_decoder_manager.cpp
hle/service/audio/hardware_opus_decoder_manager.h
hle/service/audio/hardware_opus_decoder.cpp
hle/service/audio/hardware_opus_decoder.h
hle/service/bcat/backend/backend.cpp hle/service/bcat/backend/backend.cpp
hle/service/bcat/backend/backend.h hle/service/bcat/backend/backend.h
hle/service/bcat/bcat.cpp hle/service/bcat/bcat.cpp
@ -599,6 +610,10 @@ add_library(core STATIC
hle/service/filesystem/fsp/fs_i_file.h hle/service/filesystem/fsp/fs_i_file.h
hle/service/filesystem/fsp/fs_i_filesystem.cpp hle/service/filesystem/fsp/fs_i_filesystem.cpp
hle/service/filesystem/fsp/fs_i_filesystem.h hle/service/filesystem/fsp/fs_i_filesystem.h
hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
hle/service/filesystem/fsp/fs_i_storage.cpp hle/service/filesystem/fsp/fs_i_storage.cpp
hle/service/filesystem/fsp/fs_i_storage.h hle/service/filesystem/fsp/fs_i_storage.h
hle/service/filesystem/fsp/fsp_ldr.cpp hle/service/filesystem/fsp/fsp_ldr.cpp
@ -607,7 +622,7 @@ add_library(core STATIC
hle/service/filesystem/fsp/fsp_pr.h hle/service/filesystem/fsp/fsp_pr.h
hle/service/filesystem/fsp/fsp_srv.cpp hle/service/filesystem/fsp/fsp_srv.cpp
hle/service/filesystem/fsp/fsp_srv.h hle/service/filesystem/fsp/fsp_srv.h
hle/service/filesystem/fsp/fsp_util.h hle/service/filesystem/fsp/fsp_types.h
hle/service/filesystem/romfs_controller.cpp hle/service/filesystem/romfs_controller.cpp
hle/service/filesystem/romfs_controller.h hle/service/filesystem/romfs_controller.h
hle/service/filesystem/save_data_controller.cpp hle/service/filesystem/save_data_controller.cpp
@ -864,8 +879,20 @@ add_library(core STATIC
hle/service/nvnflinger/ui/graphic_buffer.cpp hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h hle/service/nvnflinger/window.h
hle/service/olsc/daemon_controller.cpp
hle/service/olsc/daemon_controller.h
hle/service/olsc/native_handle_holder.cpp
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.cpp
hle/service/olsc/olsc.h hle/service/olsc/olsc.h
hle/service/olsc/remote_storage_controller.cpp
hle/service/olsc/remote_storage_controller.h
hle/service/olsc/transfer_task_list_controller.cpp
hle/service/olsc/transfer_task_list_controller.h
hle/service/omm/omm.cpp hle/service/omm/omm.cpp
hle/service/omm/omm.h hle/service/omm/omm.h
hle/service/omm/operation_mode_manager.cpp hle/service/omm/operation_mode_manager.cpp
@ -885,16 +912,35 @@ add_library(core STATIC
hle/service/os/mutex.h hle/service/os/mutex.h
hle/service/pcie/pcie.cpp hle/service/pcie/pcie.cpp
hle/service/pcie/pcie.h 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.cpp
hle/service/pctl/pctl.h hle/service/pctl/pctl.h
hle/service/pctl/pctl_module.cpp hle/service/pctl/pctl_results.h
hle/service/pctl/pctl_module.h hle/service/pctl/pctl_types.h
hle/service/pcv/pcv.cpp hle/service/pcv/pcv.cpp
hle/service/pcv/pcv.h hle/service/pcv/pcv.h
hle/service/pm/pm.cpp hle/service/pm/pm.cpp
hle/service/pm/pm.h hle/service/pm/pm.h
hle/service/prepo/prepo.cpp hle/service/prepo/prepo.cpp
hle/service/prepo/prepo.h hle/service/prepo/prepo.h
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.cpp
hle/service/psc/psc.h hle/service/psc/psc.h
hle/service/psc/time/alarms.cpp hle/service/psc/time/alarms.cpp

View file

@ -0,0 +1,175 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <fmt/format.h>
#include "common/common_funcs.h"
#include "common/common_types.h"
namespace FileSys {
using SaveDataId = u64;
using SystemSaveDataId = u64;
using SystemBcatSaveDataId = SystemSaveDataId;
using ProgramId = u64;
enum class SaveDataSpaceId : u8 {
System = 0,
User = 1,
SdSystem = 2,
Temporary = 3,
SdUser = 4,
ProperSystem = 100,
SafeMode = 101,
};
enum class SaveDataType : u8 {
System = 0,
Account = 1,
Bcat = 2,
Device = 3,
Temporary = 4,
Cache = 5,
SystemBcat = 6,
};
enum class SaveDataRank : u8 {
Primary = 0,
Secondary = 1,
};
struct SaveDataSize {
u64 normal;
u64 journal;
};
static_assert(sizeof(SaveDataSize) == 0x10, "SaveDataSize has invalid size.");
using UserId = u128;
static_assert(std::is_trivially_copyable_v<UserId>, "Data type must be trivially copyable.");
static_assert(sizeof(UserId) == 0x10, "UserId has invalid size.");
constexpr inline SystemSaveDataId InvalidSystemSaveDataId = 0;
constexpr inline UserId InvalidUserId = {};
enum class SaveDataFlags : u32 {
None = (0 << 0),
KeepAfterResettingSystemSaveData = (1 << 0),
KeepAfterRefurbishment = (1 << 1),
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
NeedsSecureDelete = (1 << 3),
};
enum class SaveDataMetaType : u8 {
None = 0,
Thumbnail = 1,
ExtensionContext = 2,
};
struct SaveDataMetaInfo {
u32 size;
SaveDataMetaType type;
INSERT_PADDING_BYTES(0xB);
};
static_assert(std::is_trivially_copyable_v<SaveDataMetaInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataMetaInfo) == 0x10, "SaveDataMetaInfo has invalid size.");
struct SaveDataCreationInfo {
s64 size;
s64 journal_size;
s64 block_size;
u64 owner_id;
u32 flags;
SaveDataSpaceId space_id;
bool pseudo;
INSERT_PADDING_BYTES(0x1A);
};
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo>,
"Data type must be trivially copyable.");
static_assert(sizeof(SaveDataCreationInfo) == 0x40, "SaveDataCreationInfo has invalid size.");
struct SaveDataAttribute {
ProgramId program_id;
UserId user_id;
SystemSaveDataId system_save_data_id;
SaveDataType type;
SaveDataRank rank;
u16 index;
INSERT_PADDING_BYTES(0x1C);
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id, u16 index,
SaveDataRank rank) {
return {
.program_id = program_id,
.user_id = user_id,
.system_save_data_id = system_save_data_id,
.type = type,
.rank = rank,
.index = index,
};
}
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id, u16 index) {
return Make(program_id, type, user_id, system_save_data_id, index, SaveDataRank::Primary);
}
static constexpr SaveDataAttribute Make(ProgramId program_id, SaveDataType type, UserId user_id,
SystemSaveDataId system_save_data_id) {
return Make(program_id, type, user_id, system_save_data_id, 0, SaveDataRank::Primary);
}
std::string DebugInfo() const {
return fmt::format(
"[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
"rank={}, index={}]",
program_id, user_id[1], user_id[0], system_save_data_id, static_cast<u8>(type),
static_cast<u8>(rank), index);
}
};
static_assert(sizeof(SaveDataAttribute) == 0x40);
static_assert(std::is_trivially_destructible<SaveDataAttribute>::value);
constexpr inline bool operator<(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.index, lhs.rank) <
std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id, rhs.index, rhs.rank);
}
constexpr inline bool operator==(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return std::tie(lhs.program_id, lhs.user_id, lhs.system_save_data_id, lhs.type, lhs.rank,
lhs.index) == std::tie(rhs.program_id, rhs.user_id, rhs.system_save_data_id,
rhs.type, rhs.rank, rhs.index);
}
constexpr inline bool operator!=(const SaveDataAttribute& lhs, const SaveDataAttribute& rhs) {
return !(lhs == rhs);
}
struct SaveDataExtraData {
SaveDataAttribute attr;
u64 owner_id;
s64 timestamp;
u32 flags;
INSERT_PADDING_BYTES(4);
s64 available_size;
s64 journal_size;
s64 commit_id;
INSERT_PADDING_BYTES(0x190);
};
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has invalid size.");
static_assert(std::is_trivially_copyable_v<SaveDataExtraData>,
"Data type must be trivially copyable.");
struct HashSalt {
static constexpr size_t Size = 32;
std::array<u8, Size> value;
};
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(HashSalt) == HashSalt::Size);
} // namespace FileSys

View file

@ -14,48 +14,11 @@ namespace FileSys {
namespace { namespace {
void PrintSaveDataAttributeWarnings(SaveDataAttribute meta) {
if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) {
if (meta.zero_1 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).",
meta.zero_1);
}
if (meta.zero_2 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).",
meta.zero_2);
}
if (meta.zero_3 != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is "
"SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).",
meta.zero_3);
}
}
if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is SystemSaveData but title_id is "
"non-zero ({:016X}).",
meta.title_id);
}
if (meta.type == SaveDataType::DeviceSaveData && meta.user_id != u128{0, 0}) {
LOG_WARNING(Service_FS,
"Possibly incorrect SaveDataAttribute, type is DeviceSaveData but user_id is "
"non-zero ({:016X}{:016X})",
meta.user_id[1], meta.user_id[0]);
}
}
bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) { bool ShouldSaveDataBeAutomaticallyCreated(SaveDataSpaceId space, const SaveDataAttribute& attr) {
return attr.type == SaveDataType::CacheStorage || attr.type == SaveDataType::TemporaryStorage || return attr.type == SaveDataType::Cache || attr.type == SaveDataType::Temporary ||
(space == SaveDataSpaceId::NandUser && ///< Normal Save Data -- Current Title & User (space == SaveDataSpaceId::User && ///< Normal Save Data -- Current Title & User
(attr.type == SaveDataType::SaveData || attr.type == SaveDataType::DeviceSaveData) && (attr.type == SaveDataType::Account || attr.type == SaveDataType::Device) &&
attr.title_id == 0 && attr.save_id == 0); attr.program_id == 0 && attr.system_save_data_id == 0);
} }
std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id, std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u64 title_id,
@ -63,7 +26,7 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
// Only detect nand user saves. // Only detect nand user saves.
const auto space_id_path = [space_id]() -> std::string_view { const auto space_id_path = [space_id]() -> std::string_view {
switch (space_id) { switch (space_id) {
case SaveDataSpaceId::NandUser: case SaveDataSpaceId::User:
return "/user/save"; return "/user/save";
default: default:
return ""; return "";
@ -79,9 +42,9 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
// Only detect account/device saves from the future location. // Only detect account/device saves from the future location.
switch (type) { switch (type) {
case SaveDataType::SaveData: case SaveDataType::Account:
return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id); return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id);
case SaveDataType::DeviceSaveData: case SaveDataType::Device:
return fmt::format("{}/device/{:016X}/0", space_id_path, title_id); return fmt::format("{}/device/{:016X}/0", space_id_path, title_id);
default: default:
return ""; return "";
@ -90,13 +53,6 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
} // Anonymous namespace } // Anonymous namespace
std::string SaveDataAttribute::DebugInfo() const {
return fmt::format("[title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}, type={:02X}, "
"rank={}, index={}]",
title_id, user_id[1], user_id[0], save_id, static_cast<u8>(type),
static_cast<u8>(rank), index);
}
SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_, SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
VirtualDir save_directory_) VirtualDir save_directory_)
: system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} { : system{system_}, program_id{program_id_}, dir{std::move(save_directory_)} {
@ -108,18 +64,16 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, ProgramId program_id_,
SaveDataFactory::~SaveDataFactory() = default; SaveDataFactory::~SaveDataFactory() = default;
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const { VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
PrintSaveDataAttributeWarnings(meta); const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
meta.user_id, meta.system_save_data_id);
const auto save_directory =
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
return dir->CreateDirectoryRelative(save_directory); return dir->CreateDirectoryRelative(save_directory);
} }
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const {
const auto save_directory = const auto save_directory = GetFullPath(program_id, dir, space, meta.type, meta.program_id,
GetFullPath(program_id, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); meta.user_id, meta.system_save_data_id);
auto out = dir->GetDirectoryRelative(save_directory); auto out = dir->GetDirectoryRelative(save_directory);
@ -136,11 +90,11 @@ VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) con
std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) { std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) {
switch (space) { switch (space) {
case SaveDataSpaceId::NandSystem: case SaveDataSpaceId::System:
return "/system/"; return "/system/";
case SaveDataSpaceId::NandUser: case SaveDataSpaceId::User:
return "/user/"; return "/user/";
case SaveDataSpaceId::TemporaryStorage: case SaveDataSpaceId::Temporary:
return "/temp/"; return "/temp/";
default: default:
ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space)); ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space));
@ -153,7 +107,7 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
u128 user_id, u64 save_id) { u128 user_id, u64 save_id) {
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
// be interpreted as the title id of the current process. // be interpreted as the title id of the current process.
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { if (type == SaveDataType::Account || type == SaveDataType::Device) {
if (title_id == 0) { if (title_id == 0) {
title_id = program_id; title_id = program_id;
} }
@ -173,16 +127,16 @@ std::string SaveDataFactory::GetFullPath(ProgramId program_id, VirtualDir dir,
std::string out = GetSaveDataSpaceIdPath(space); std::string out = GetSaveDataSpaceIdPath(space);
switch (type) { switch (type) {
case SaveDataType::SystemSaveData: case SaveDataType::System:
return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]); return fmt::format("{}save/{:016X}/{:016X}{:016X}", out, save_id, user_id[1], user_id[0]);
case SaveDataType::SaveData: case SaveDataType::Account:
case SaveDataType::DeviceSaveData: case SaveDataType::Device:
return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0], return fmt::format("{}save/{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
title_id); title_id);
case SaveDataType::TemporaryStorage: case SaveDataType::Temporary:
return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0], return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", out, 0, user_id[1], user_id[0],
title_id); title_id);
case SaveDataType::CacheStorage: case SaveDataType::Cache:
return fmt::format("{}save/cache/{:016X}", out, title_id); return fmt::format("{}save/cache/{:016X}", out, title_id);
default: default:
ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type)); ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type));
@ -202,7 +156,7 @@ std::string SaveDataFactory::GetUserGameSaveDataRoot(u128 user_id, bool future)
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
u128 user_id) const { u128 user_id) const {
const auto path = const auto path =
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName()); const auto size_file = relative_dir->GetFile(GetSaveDataSizeFileName());
@ -221,7 +175,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
SaveDataSize new_value) const { SaveDataSize new_value) const {
const auto path = const auto path =
GetFullPath(program_id, dir, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); GetFullPath(program_id, dir, SaveDataSpaceId::User, type, title_id, user_id, 0);
const auto relative_dir = GetOrCreateDirectoryRelative(dir, path); const auto relative_dir = GetOrCreateDirectoryRelative(dir, path);
const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName()); const auto size_file = relative_dir->CreateFile(GetSaveDataSizeFileName());

View file

@ -7,6 +7,7 @@
#include <string> #include <string>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/file_sys/fs_save_data_types.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/hle/result.h" #include "core/hle/result.h"
@ -16,73 +17,6 @@ class System;
namespace FileSys { namespace FileSys {
enum class SaveDataSpaceId : u8 {
NandSystem = 0,
NandUser = 1,
SdCardSystem = 2,
TemporaryStorage = 3,
SdCardUser = 4,
ProperSystem = 100,
SafeMode = 101,
};
enum class SaveDataType : u8 {
SystemSaveData = 0,
SaveData = 1,
BcatDeliveryCacheStorage = 2,
DeviceSaveData = 3,
TemporaryStorage = 4,
CacheStorage = 5,
SystemBcat = 6,
};
enum class SaveDataRank : u8 {
Primary = 0,
Secondary = 1,
};
enum class SaveDataFlags : u32 {
None = (0 << 0),
KeepAfterResettingSystemSaveData = (1 << 0),
KeepAfterRefurbishment = (1 << 1),
KeepAfterResettingSystemSaveDataWithoutUserSaveData = (1 << 2),
NeedsSecureDelete = (1 << 3),
};
struct SaveDataAttribute {
u64 title_id;
u128 user_id;
u64 save_id;
SaveDataType type;
SaveDataRank rank;
u16 index;
INSERT_PADDING_BYTES_NOINIT(4);
u64 zero_1;
u64 zero_2;
u64 zero_3;
std::string DebugInfo() const;
};
static_assert(sizeof(SaveDataAttribute) == 0x40, "SaveDataAttribute has incorrect size.");
struct SaveDataExtraData {
SaveDataAttribute attr;
u64 owner_id;
s64 timestamp;
SaveDataFlags flags;
INSERT_PADDING_BYTES_NOINIT(4);
s64 available_size;
s64 journal_size;
s64 commit_id;
std::array<u8, 0x190> unused;
};
static_assert(sizeof(SaveDataExtraData) == 0x200, "SaveDataExtraData has incorrect size.");
struct SaveDataSize {
u64 normal;
u64 journal;
};
constexpr const char* GetSaveDataSizeFileName() { constexpr const char* GetSaveDataSizeFileName() {
return ".yuzu_save_size"; return ".yuzu_save_size";
} }

View file

@ -123,13 +123,13 @@ Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID use
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString()); LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
FileSys::SaveDataAttribute attribute{}; FileSys::SaveDataAttribute attribute{};
attribute.title_id = m_applet->program_id; attribute.program_id = m_applet->program_id;
attribute.user_id = user_id.AsU128(); attribute.user_id = user_id.AsU128();
attribute.type = FileSys::SaveDataType::SaveData; attribute.type = FileSys::SaveDataType::Account;
FileSys::VirtualDir save_data{}; FileSys::VirtualDir save_data{};
R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData( R_TRY(system.GetFileSystemController().OpenSaveDataController()->CreateSaveData(
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute)); &save_data, FileSys::SaveDataSpaceId::User, attribute));
*out_size = 0; *out_size = 0;
R_SUCCEED(); R_SUCCEED();

View file

@ -2,14 +2,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h" #include "core/hle/service/audio/audio.h"
#include "core/hle/service/audio/audio_controller.h" #include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/audio/audout_u.h" #include "core/hle/service/audio/audio_in_manager.h"
#include "core/hle/service/audio/audrec_a.h" #include "core/hle/service/audio/audio_out_manager.h"
#include "core/hle/service/audio/audrec_u.h" #include "core/hle/service/audio/audio_renderer_manager.h"
#include "core/hle/service/audio/audren_u.h" #include "core/hle/service/audio/final_output_recorder_manager.h"
#include "core/hle/service/audio/hwopus.h" #include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
@ -19,12 +19,16 @@ void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system); auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system)); server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system)); server_manager->RegisterNamedService("audin:u", std::make_shared<IAudioInManager>(system));
server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system)); server_manager->RegisterNamedService("audout:u", std::make_shared<IAudioOutManager>(system));
server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system)); server_manager->RegisterNamedService(
server_manager->RegisterNamedService("audrec:u", std::make_shared<AudRecU>(system)); "audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system)); server_manager->RegisterNamedService("audrec:u",
server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system)); std::make_shared<IFinalOutputRecorderManager>(system));
server_manager->RegisterNamedService("audren:u",
std::make_shared<IAudioRendererManager>(system));
server_manager->RegisterNamedService("hwopus",
std::make_shared<IHardwareOpusDecoderManager>(system));
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }

View file

@ -16,27 +16,27 @@ IAudioController::IAudioController(Core::System& system_)
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"}, {0, nullptr, "GetTargetVolume"},
{1, nullptr, "SetTargetVolume"}, {1, nullptr, "SetTargetVolume"},
{2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"}, {2, D<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
{3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"}, {3, D<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
{4, nullptr, "IsTargetMute"}, {4, nullptr, "IsTargetMute"},
{5, nullptr, "SetTargetMute"}, {5, nullptr, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"}, {6, nullptr, "IsTargetConnected"},
{7, nullptr, "SetDefaultTarget"}, {7, nullptr, "SetDefaultTarget"},
{8, nullptr, "GetDefaultTarget"}, {8, nullptr, "GetDefaultTarget"},
{9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"}, {9, D<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
{10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"}, {10, D<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"}, {11, nullptr, "SetForceMutePolicy"},
{12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"}, {12, D<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
{13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"}, {13, D<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
{14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"}, {14, D<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"}, {15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"}, {16, nullptr, "SetInputTargetForceEnabled"},
{17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"}, {17, D<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
{18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"}, {18, D<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
{21, nullptr, "GetAudioOutputTargetForPlayReport"}, {21, nullptr, "GetAudioOutputTargetForPlayReport"},
{22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"}, {22, D<&IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent>, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
{23, nullptr, "SetSystemOutputMasterVolume"}, {23, nullptr, "SetSystemOutputMasterVolume"},
{24, nullptr, "GetSystemOutputMasterVolume"}, {24, nullptr, "GetSystemOutputMasterVolume"},
{25, nullptr, "GetAudioVolumeDataForPlayReport"}, {25, nullptr, "GetAudioVolumeDataForPlayReport"},
@ -44,11 +44,11 @@ IAudioController::IAudioController(Core::System& system_)
{27, nullptr, "SetVolumeMappingTableForDev"}, {27, nullptr, "SetVolumeMappingTableForDev"},
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"}, {30, D<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
{31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"}, {31, D<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"}, {32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"}, {33, nullptr, "GetTargetDeviceInfo"},
{34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"}, {34, D<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
{35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"}, {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
{37, nullptr, "SetHearingProtectionSafeguardEnabled"}, {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
@ -150,6 +150,11 @@ Result IAudioController::GetHeadphoneOutputLevelMode(
R_SUCCEED(); R_SUCCEED();
} }
Result IAudioController::NotifyHeadphoneVolumeWarningDisplayedEvent() {
LOG_WARNING(Service_Audio, "(STUBBED) called");
R_SUCCEED();
}
Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) { Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled); LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);

View file

@ -45,6 +45,7 @@ private:
Set::AudioOutputMode output_mode); Set::AudioOutputMode output_mode);
Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode); Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode); Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
Result NotifyHeadphoneVolumeWarningDisplayedEvent();
Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled); Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled); Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event); Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);

View file

@ -0,0 +1,163 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_core.h"
#include "common/string_util.h"
#include "core/hle/service/audio/audio_device.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::Renderer;
IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
u32 device_num)
: ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
static const FunctionInfo functions[] = {
{0, D<&IAudioDevice::ListAudioDeviceName>, "ListAudioDeviceName"},
{1, D<&IAudioDevice::SetAudioDeviceOutputVolume>, "SetAudioDeviceOutputVolume"},
{2, D<&IAudioDevice::GetAudioDeviceOutputVolume>, "GetAudioDeviceOutputVolume"},
{3, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioDeviceName"},
{4, D<&IAudioDevice::QueryAudioDeviceSystemEvent>, "QueryAudioDeviceSystemEvent"},
{5, D<&IAudioDevice::GetActiveChannelCount>, "GetActiveChannelCount"},
{6, D<&IAudioDevice::ListAudioDeviceNameAuto>, "ListAudioDeviceNameAuto"},
{7, D<&IAudioDevice::SetAudioDeviceOutputVolumeAuto>, "SetAudioDeviceOutputVolumeAuto"},
{8, D<&IAudioDevice::GetAudioDeviceOutputVolumeAuto>, "GetAudioDeviceOutputVolumeAuto"},
{10, D<&IAudioDevice::GetActiveAudioDeviceNameAuto>, "GetActiveAudioDeviceNameAuto"},
{11, D<&IAudioDevice::QueryAudioDeviceInputEvent>, "QueryAudioDeviceInputEvent"},
{12, D<&IAudioDevice::QueryAudioDeviceOutputEvent>, "QueryAudioDeviceOutputEvent"},
{13, D<&IAudioDevice::GetActiveAudioDeviceName>, "GetActiveAudioOutputDeviceName"},
{14, D<&IAudioDevice::ListAudioOutputDeviceName>, "ListAudioOutputDeviceName"},
};
RegisterHandlers(functions);
event->Signal();
}
IAudioDevice::~IAudioDevice() {
service_context.CloseEvent(event);
}
Result IAudioDevice::ListAudioDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
R_RETURN(this->ListAudioDeviceNameAuto(out_names, out_count));
}
Result IAudioDevice::SetAudioDeviceOutputVolume(
InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume) {
R_RETURN(this->SetAudioDeviceOutputVolumeAuto(name, volume));
}
Result IAudioDevice::GetAudioDeviceOutputVolume(
Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name) {
R_RETURN(this->GetAudioDeviceOutputVolumeAuto(out_volume, name));
}
Result IAudioDevice::GetActiveAudioDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name) {
R_RETURN(this->GetActiveAudioDeviceNameAuto(out_name));
}
Result IAudioDevice::ListAudioDeviceNameAuto(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
Out<s32> out_count) {
*out_count = impl->ListAudioDeviceName(out_names);
std::string out{};
for (s32 i = 0; i < *out_count; i++) {
std::string a{};
u32 j = 0;
while (out_names[i].name[j] != '\0') {
a += out_names[i].name[j];
j++;
}
out += "\n\t" + a;
}
LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
R_SUCCEED();
}
Result IAudioDevice::SetAudioDeviceOutputVolumeAuto(
InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume) {
R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
const std::string device_name = Common::StringFromBuffer(name[0].name);
LOG_DEBUG(Service_Audio, "called. name={}, volume={}", device_name, volume);
if (device_name == "AudioTvOutput") {
impl->SetDeviceVolumes(volume);
}
R_SUCCEED();
}
Result IAudioDevice::GetAudioDeviceOutputVolumeAuto(
Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name) {
R_UNLESS(!name.empty(), Audio::ResultInsufficientBuffer);
const std::string device_name = Common::StringFromBuffer(name[0].name);
LOG_DEBUG(Service_Audio, "called. Name={}", device_name);
*out_volume = 1.0f;
if (device_name == "AudioTvOutput") {
*out_volume = impl->GetDeviceVolume(device_name);
}
R_SUCCEED();
}
Result IAudioDevice::GetActiveAudioDeviceNameAuto(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name) {
R_UNLESS(!out_name.empty(), Audio::ResultInsufficientBuffer);
out_name[0] = AudioDevice::AudioDeviceName("AudioTvOutput");
LOG_DEBUG(Service_Audio, "(STUBBED) called");
R_SUCCEED();
}
Result IAudioDevice::QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "(STUBBED) called");
event->Signal();
*out_event = &event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioDevice::QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "(STUBBED) called");
*out_event = &event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioDevice::QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "called");
*out_event = &event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioDevice::GetActiveChannelCount(Out<u32> out_active_channel_count) {
*out_active_channel_count = system.AudioCore().GetOutputSink().GetSystemChannels();
LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", *out_active_channel_count);
R_SUCCEED();
}
Result IAudioDevice::ListAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names, Out<s32> out_count) {
*out_count = impl->ListAudioOutputDeviceName(out_names);
std::string out{};
for (s32 i = 0; i < *out_count; i++) {
std::string a{};
u32 j = 0;
while (out_names[i].name[j] != '\0') {
a += out_names[i].name[j];
j++;
}
out += "\n\t" + a;
}
LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/renderer/audio_device.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KReadableEvent;
}
namespace Service::Audio {
using AudioCore::Renderer::AudioDevice;
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
u32 device_num);
~IAudioDevice() override;
private:
Result ListAudioDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
Out<s32> out_count);
Result SetAudioDeviceOutputVolume(
InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name, f32 volume);
Result GetAudioDeviceOutputVolume(
Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> name);
Result GetActiveAudioDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_name);
Result ListAudioDeviceNameAuto(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_names,
Out<s32> out_count);
Result SetAudioDeviceOutputVolumeAuto(
InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name, f32 volume);
Result GetAudioDeviceOutputVolumeAuto(
Out<f32> out_volume, InArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> name);
Result GetActiveAudioDeviceNameAuto(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcAutoSelect> out_name);
Result QueryAudioDeviceSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result QueryAudioDeviceInputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result QueryAudioDeviceOutputEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetActiveChannelCount(Out<u32> out_active_channel_count);
Result ListAudioOutputDeviceName(
OutArray<AudioDevice::AudioDeviceName, BufferAttr_HipcMapAlias> out_names,
Out<s32> out_count);
KernelHelpers::ServiceContext service_context;
std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
Kernel::KEvent* event;
};
} // namespace Service::Audio

View file

@ -0,0 +1,146 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audio_in.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/ipc_helpers.h"
namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioInParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
manager, event,
session_id)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioIn::GetAudioInState>, "GetAudioInState"},
{1, D<&IAudioIn::Start>, "Start"},
{2, D<&IAudioIn::Stop>, "Stop"},
{3, D<&IAudioIn::AppendAudioInBuffer>, "AppendAudioInBuffer"},
{4, D<&IAudioIn::RegisterBufferEvent>, "RegisterBufferEvent"},
{5, D<&IAudioIn::GetReleasedAudioInBuffers>, "GetReleasedAudioInBuffers"},
{6, D<&IAudioIn::ContainsAudioInBuffer>, "ContainsAudioInBuffer"},
{7, D<&IAudioIn::AppendAudioInBuffer>, "AppendUacInBuffer"},
{8, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendAudioInBufferAuto"},
{9, D<&IAudioIn::GetReleasedAudioInBuffersAuto>, "GetReleasedAudioInBuffersAuto"},
{10, D<&IAudioIn::AppendAudioInBufferAuto>, "AppendUacInBufferAuto"},
{11, D<&IAudioIn::GetAudioInBufferCount>, "GetAudioInBufferCount"},
{12, D<&IAudioIn::SetDeviceGain>, "SetDeviceGain"},
{13, D<&IAudioIn::GetDeviceGain>, "GetDeviceGain"},
{14, D<&IAudioIn::FlushAudioInBuffers>, "FlushAudioInBuffers"},
};
// clang-format on
RegisterHandlers(functions);
process->Open();
if (impl->GetSystem()
.Initialize(device_name, in_params, handle, applet_resource_user_id)
.IsError()) {
LOG_ERROR(Service_Audio, "Failed to initialize the AudioIn System!");
}
}
IAudioIn::~IAudioIn() {
impl->Free();
service_context.CloseEvent(event);
process->Close();
}
Result IAudioIn::GetAudioInState(Out<u32> out_state) {
*out_state = static_cast<u32>(impl->GetState());
LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
R_SUCCEED();
}
Result IAudioIn::Start() {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->StartSystem());
}
Result IAudioIn::Stop() {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->StopSystem());
}
Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
}
Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
u64 buffer_client_ptr) {
if (buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
R_THROW(Audio::ResultInsufficientBuffer);
}
[[maybe_unused]] const auto session_id{impl->GetSystem().GetSessionId()};
LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}", session_id,
buffer_client_ptr);
R_RETURN(impl->AppendBuffer(buffer[0], buffer_client_ptr));
}
Result IAudioIn::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "called");
*out_event = &impl->GetBufferEvent();
R_SUCCEED();
}
Result IAudioIn::GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
Out<u32> out_count) {
R_RETURN(this->GetReleasedAudioInBuffersAuto(out_audio_buffer, out_count));
}
Result IAudioIn::GetReleasedAudioInBuffersAuto(
OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
if (!out_audio_buffer.empty()) {
out_audio_buffer[0] = 0;
}
*out_count = impl->GetReleasedBuffers(out_audio_buffer);
LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
impl->GetSystem().GetSessionId(), *out_count);
R_SUCCEED();
}
Result IAudioIn::ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
*out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
*out_contains_buffer);
R_SUCCEED();
}
Result IAudioIn::GetAudioInBufferCount(Out<u32> out_buffer_count) {
*out_buffer_count = impl->GetBufferCount();
LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
R_SUCCEED();
}
Result IAudioIn::SetDeviceGain(f32 device_gain) {
impl->SetVolume(device_gain);
LOG_DEBUG(Service_Audio, "called. Gain {}", device_gain);
R_SUCCEED();
}
Result IAudioIn::GetDeviceGain(Out<f32> out_device_gain) {
*out_device_gain = impl->GetVolume();
LOG_DEBUG(Service_Audio, "called. Gain {}", *out_device_gain);
R_SUCCEED();
}
Result IAudioIn::FlushAudioInBuffers(Out<bool> out_flushed) {
*out_flushed = impl->FlushAudioInBuffers();
LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/in/audio_in.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
class IAudioIn final : public ServiceFramework<IAudioIn> {
public:
explicit IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager,
size_t session_id, const std::string& device_name,
const AudioCore::AudioIn::AudioInParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id);
~IAudioIn() override;
std::shared_ptr<AudioCore::AudioIn::In> GetImpl() {
return impl;
}
Result GetAudioInState(Out<u32> out_state);
Result Start();
Result Stop();
Result AppendAudioInBuffer(
InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
u64 buffer_client_ptr);
Result AppendAudioInBufferAuto(
InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
u64 buffer_client_ptr);
Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetReleasedAudioInBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
Out<u32> out_count);
Result GetReleasedAudioInBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
Out<u32> out_count);
Result ContainsAudioInBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
Result GetAudioInBufferCount(Out<u32> out_buffer_count);
Result SetDeviceGain(f32 device_gain);
Result GetDeviceGain(Out<f32> out_device_gain);
Result FlushAudioInBuffers(Out<bool> out_flushed);
private:
Kernel::KProcess* process;
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event;
std::shared_ptr<AudioCore::AudioIn::In> impl;
Common::ScratchBuffer<u64> released_buffer;
};
} // namespace Service::Audio

View file

@ -0,0 +1,125 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/string_util.h"
#include "core/hle/service/audio/audio_in.h"
#include "core/hle/service/audio/audio_in_manager.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioInManager::IAudioInManager(Core::System& system_)
: ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioInManager::ListAudioIns>, "ListAudioIns"},
{1, D<&IAudioInManager::OpenAudioIn>, "OpenAudioIn"},
{2, D<&IAudioInManager::ListAudioIns>, "ListAudioInsAuto"},
{3, D<&IAudioInManager::OpenAudioIn>, "OpenAudioInAuto"},
{4, D<&IAudioInManager::ListAudioInsAutoFiltered>, "ListAudioInsAutoFiltered"},
{5, D<&IAudioInManager::OpenAudioInProtocolSpecified>, "OpenAudioInProtocolSpecified"},
};
// clang-format on
RegisterHandlers(functions);
}
IAudioInManager::~IAudioInManager() = default;
Result IAudioInManager::ListAudioIns(
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins, Out<u32> out_count) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
}
Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
name, {}, parameter, process_handle, aruid));
}
Result IAudioInManager::ListAudioInsAuto(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
}
Result IAudioInManager::OpenAudioInAuto(
Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
name, {}, parameter, process_handle, aruid));
}
Result IAudioInManager::ListAudioInsAutoFiltered(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
LOG_DEBUG(Service_Audio, "called");
*out_count = impl->GetDeviceNames(out_audio_ins, true);
R_SUCCEED();
}
Result IAudioInManager::OpenAudioInProtocolSpecified(
Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
if (!process_handle) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
R_THROW(ResultUnknown);
}
if (name.empty() || out_name.empty()) {
LOG_ERROR(Service_Audio, "Invalid buffers");
R_THROW(ResultUnknown);
}
std::scoped_lock l{impl->mutex};
size_t new_session_id{};
R_TRY(impl->LinkToManager());
R_TRY(impl->AcquireSessionId(new_session_id));
LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
impl->num_free_sessions);
const auto device_name = Common::StringFromBuffer(name[0].name);
*out_audio_in = std::make_shared<IAudioIn>(system, *impl, new_session_id, device_name,
parameter, process_handle.Get(), aruid.pid);
impl->sessions[new_session_id] = (*out_audio_in)->GetImpl();
impl->applet_resource_user_ids[new_session_id] = aruid.pid;
auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal =
AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())};
out_name[0] = AudioDeviceName(out_system.GetName());
if (protocol == Protocol{}) {
if (out_system.IsUac()) {
out_name[0] = AudioDeviceName("UacIn");
} else {
out_name[0] = AudioDeviceName("DeviceIn");
}
}
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/audio_in_manager.h"
#include "audio_core/in/audio_in_system.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
using Protocol = std::array<u32, 2>;
class IAudioIn;
class IAudioInManager final : public ServiceFramework<IAudioInManager> {
public:
explicit IAudioInManager(Core::System& system_);
~IAudioInManager() override;
private:
Result ListAudioIns(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_ins,
Out<u32> out_count);
Result OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioIn::AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid);
Result ListAudioInsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins,
Out<u32> out_count);
Result OpenAudioInAuto(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
AudioCore::AudioIn::AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid);
Result ListAudioInsAutoFiltered(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count);
Result OpenAudioInProtocolSpecified(
Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
AudioCore::AudioIn::AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
std::unique_ptr<AudioCore::AudioIn::Manager> impl;
};
} // namespace Service::Audio

View file

@ -0,0 +1,146 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/out/audio_out.h"
#include "audio_core/out/audio_out_system.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/audio/audio_out.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioOutParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioOut::GetAudioOutState>, "GetAudioOutState"},
{1, D<&IAudioOut::Start>, "Start"},
{2, D<&IAudioOut::Stop>, "Stop"},
{3, D<&IAudioOut::AppendAudioOutBuffer>, "AppendAudioOutBuffer"},
{4, D<&IAudioOut::RegisterBufferEvent>, "RegisterBufferEvent"},
{5, D<&IAudioOut::GetReleasedAudioOutBuffers>, "GetReleasedAudioOutBuffers"},
{6, D<&IAudioOut::ContainsAudioOutBuffer>, "ContainsAudioOutBuffer"},
{7, D<&IAudioOut::AppendAudioOutBufferAuto>, "AppendAudioOutBufferAuto"},
{8, D<&IAudioOut::GetReleasedAudioOutBuffersAuto>, "GetReleasedAudioOutBuffersAuto"},
{9, D<&IAudioOut::GetAudioOutBufferCount>, "GetAudioOutBufferCount"},
{10, D<&IAudioOut::GetAudioOutPlayedSampleCount>, "GetAudioOutPlayedSampleCount"},
{11, D<&IAudioOut::FlushAudioOutBuffers>, "FlushAudioOutBuffers"},
{12, D<&IAudioOut::SetAudioOutVolume>, "SetAudioOutVolume"},
{13, D<&IAudioOut::GetAudioOutVolume>, "GetAudioOutVolume"},
};
// clang-format on
RegisterHandlers(functions);
process->Open();
}
IAudioOut::~IAudioOut() {
impl->Free();
service_context.CloseEvent(event);
process->Close();
}
Result IAudioOut::GetAudioOutState(Out<u32> out_state) {
*out_state = static_cast<u32>(impl->GetState());
LOG_DEBUG(Service_Audio, "called. state={}", *out_state);
R_SUCCEED();
}
Result IAudioOut::Start() {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->StartSystem());
}
Result IAudioOut::Stop() {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->StopSystem());
}
Result IAudioOut::AppendAudioOutBuffer(
InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
}
Result IAudioOut::AppendAudioOutBufferAuto(
InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
if (audio_out_buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
R_THROW(Audio::ResultInsufficientBuffer);
}
LOG_TRACE(Service_Audio, "called. Session {} Appending buffer {:08X}",
impl->GetSystem().GetSessionId(), buffer_client_ptr);
R_RETURN(impl->AppendBuffer(audio_out_buffer[0], buffer_client_ptr));
}
Result IAudioOut::RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "called");
*out_event = &impl->GetBufferEvent();
R_SUCCEED();
}
Result IAudioOut::GetReleasedAudioOutBuffers(
OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer, Out<u32> out_count) {
R_RETURN(this->GetReleasedAudioOutBuffersAuto(out_audio_buffer, out_count));
}
Result IAudioOut::GetReleasedAudioOutBuffersAuto(
OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer, Out<u32> out_count) {
if (!out_audio_buffer.empty()) {
out_audio_buffer[0] = 0;
}
*out_count = impl->GetReleasedBuffers(out_audio_buffer);
LOG_TRACE(Service_Audio, "called. Session {} released {} buffers",
impl->GetSystem().GetSessionId(), *out_count);
R_SUCCEED();
}
Result IAudioOut::ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr) {
*out_contains_buffer = impl->ContainsAudioBuffer(buffer_client_ptr);
LOG_DEBUG(Service_Audio, "called. Is buffer {:08X} registered? {}", buffer_client_ptr,
*out_contains_buffer);
R_SUCCEED();
}
Result IAudioOut::GetAudioOutBufferCount(Out<u32> out_buffer_count) {
*out_buffer_count = impl->GetBufferCount();
LOG_DEBUG(Service_Audio, "called. Buffer count={}", *out_buffer_count);
R_SUCCEED();
}
Result IAudioOut::GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count) {
*out_played_sample_count = impl->GetPlayedSampleCount();
LOG_DEBUG(Service_Audio, "called. Played samples={}", *out_played_sample_count);
R_SUCCEED();
}
Result IAudioOut::FlushAudioOutBuffers(Out<bool> out_flushed) {
*out_flushed = impl->FlushAudioOutBuffers();
LOG_DEBUG(Service_Audio, "called. Were any buffers flushed? {}", *out_flushed);
R_SUCCEED();
}
Result IAudioOut::SetAudioOutVolume(f32 volume) {
LOG_DEBUG(Service_Audio, "called. Volume={}", volume);
impl->SetVolume(volume);
R_SUCCEED();
}
Result IAudioOut::GetAudioOutVolume(Out<f32> out_volume) {
*out_volume = impl->GetVolume();
LOG_DEBUG(Service_Audio, "called. Volume={}", *out_volume);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/audio_out_manager.h"
#include "audio_core/out/audio_out_system.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KReadableEvent;
}
namespace Service::Audio {
class IAudioOut : public ServiceFramework<IAudioOut> {
public:
explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
size_t session_id, const std::string& device_name,
const AudioCore::AudioOut::AudioOutParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id);
~IAudioOut() override;
std::shared_ptr<AudioCore::AudioOut::Out> GetImpl() {
return impl;
}
Result GetAudioOutState(Out<u32> out_state);
Result Start();
Result Stop();
Result AppendAudioOutBuffer(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer,
u64 buffer_client_ptr);
Result AppendAudioOutBufferAuto(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer,
u64 buffer_client_ptr);
Result RegisterBufferEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetReleasedAudioOutBuffers(OutArray<u64, BufferAttr_HipcMapAlias> out_audio_buffer,
Out<u32> out_count);
Result GetReleasedAudioOutBuffersAuto(OutArray<u64, BufferAttr_HipcAutoSelect> out_audio_buffer,
Out<u32> out_count);
Result ContainsAudioOutBuffer(Out<bool> out_contains_buffer, u64 buffer_client_ptr);
Result GetAudioOutBufferCount(Out<u32> out_buffer_count);
Result GetAudioOutPlayedSampleCount(Out<u64> out_played_sample_count);
Result FlushAudioOutBuffers(Out<bool> out_flushed);
Result SetAudioOutVolume(f32 volume);
Result GetAudioOutVolume(Out<f32> out_volume);
private:
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event;
Kernel::KProcess* process;
std::shared_ptr<AudioCore::AudioOut::Out> impl;
};
} // namespace Service::Audio

View file

@ -0,0 +1,101 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/string_util.h"
#include "core/hle/service/audio/audio_out.h"
#include "core/hle/service/audio/audio_out_manager.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/memory.h"
namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOutManager::IAudioOutManager(Core::System& system_)
: ServiceFramework{system_, "audout:u"}, impl{std::make_unique<Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioOutManager::ListAudioOuts>, "ListAudioOuts"},
{1, D<&IAudioOutManager::OpenAudioOut>, "OpenAudioOut"},
{2, D<&IAudioOutManager::ListAudioOutsAuto>, "ListAudioOutsAuto"},
{3, D<&IAudioOutManager::OpenAudioOutAuto>, "OpenAudioOutAuto"},
};
// clang-format on
RegisterHandlers(functions);
}
IAudioOutManager::~IAudioOutManager() = default;
Result IAudioOutManager::ListAudioOuts(
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs, Out<u32> out_count) {
R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
}
Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
parameter, process_handle, aruid));
}
Result IAudioOutManager::ListAudioOutsAuto(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs, Out<u32> out_count) {
if (!out_audio_outs.empty()) {
out_audio_outs[0] = AudioDeviceName("DeviceOut");
*out_count = 1;
LOG_DEBUG(Service_Audio, "called. \nName=DeviceOut");
} else {
*out_count = 0;
LOG_DEBUG(Service_Audio, "called. Empty buffer passed in.");
}
R_SUCCEED();
}
Result IAudioOutManager::OpenAudioOutAuto(
Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
if (!process_handle) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
R_THROW(ResultUnknown);
}
if (name.empty() || out_name.empty()) {
LOG_ERROR(Service_Audio, "Invalid buffers");
R_THROW(ResultUnknown);
}
size_t new_session_id{};
R_TRY(impl->LinkToManager());
R_TRY(impl->AcquireSessionId(new_session_id));
const auto device_name = Common::StringFromBuffer(name[0].name);
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
impl->num_free_sessions);
auto audio_out = std::make_shared<IAudioOut>(system, *impl, new_session_id, device_name,
parameter, process_handle.Get(), aruid.pid);
R_TRY(audio_out->GetImpl()->GetSystem().Initialize(device_name, parameter, process_handle.Get(),
aruid.pid));
*out_audio_out = audio_out;
impl->sessions[new_session_id] = audio_out->GetImpl();
impl->applet_resource_user_ids[new_session_id] = aruid.pid;
auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal =
AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())};
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/audio_out_manager.h"
#include "audio_core/out/audio_out.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
using AudioDeviceName = AudioCore::Renderer::AudioDevice::AudioDeviceName;
class IAudioOut;
class IAudioOutManager final : public ServiceFramework<IAudioOutManager> {
public:
explicit IAudioOutManager(Core::System& system_);
~IAudioOutManager() override;
private:
Result ListAudioOuts(OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_audio_outs,
Out<u32> out_count);
Result OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioOut::AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid);
Result ListAudioOutsAuto(OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_outs,
Out<u32> out_count);
Result OpenAudioOutAuto(
Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name,
AudioCore::AudioOut::AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid);
std::unique_ptr<AudioCore::AudioOut::Manager> impl;
};
} // namespace Service::Audio

View file

@ -0,0 +1,139 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::Renderer;
IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
process_handle_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
{1, D<&IAudioRenderer::GetSampleCount>, "GetSampleCount"},
{2, D<&IAudioRenderer::GetMixBufferCount>, "GetMixBufferCount"},
{3, D<&IAudioRenderer::GetState>, "GetState"},
{4, D<&IAudioRenderer::RequestUpdate>, "RequestUpdate"},
{5, D<&IAudioRenderer::Start>, "Start"},
{6, D<&IAudioRenderer::Stop>, "Stop"},
{7, D<&IAudioRenderer::QuerySystemEvent>, "QuerySystemEvent"},
{8, D<&IAudioRenderer::SetRenderingTimeLimit>, "SetRenderingTimeLimit"},
{9, D<&IAudioRenderer::GetRenderingTimeLimit>, "GetRenderingTimeLimit"},
{10, D<&IAudioRenderer::RequestUpdateAuto>, "RequestUpdateAuto"},
{11, nullptr, "ExecuteAudioRendererRendering"},
{12, D<&IAudioRenderer::SetVoiceDropParameter>, "SetVoiceDropParameter"},
{13, D<&IAudioRenderer::GetVoiceDropParameter>, "GetVoiceDropParameter"},
};
// clang-format on
RegisterHandlers(functions);
process_handle->Open();
impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle,
applet_resource_user_id, session_id);
}
IAudioRenderer::~IAudioRenderer() {
impl->Finalize();
service_context.CloseEvent(rendered_event);
process_handle->Close();
}
Result IAudioRenderer::GetSampleRate(Out<u32> out_sample_rate) {
*out_sample_rate = impl->GetSystem().GetSampleRate();
LOG_DEBUG(Service_Audio, "called. Sample rate {}", *out_sample_rate);
R_SUCCEED();
}
Result IAudioRenderer::GetSampleCount(Out<u32> out_sample_count) {
*out_sample_count = impl->GetSystem().GetSampleCount();
LOG_DEBUG(Service_Audio, "called. Sample count {}", *out_sample_count);
R_SUCCEED();
}
Result IAudioRenderer::GetState(Out<u32> out_state) {
*out_state = !impl->GetSystem().IsActive();
LOG_DEBUG(Service_Audio, "called, state {}", *out_state);
R_SUCCEED();
}
Result IAudioRenderer::GetMixBufferCount(Out<u32> out_mix_buffer_count) {
LOG_DEBUG(Service_Audio, "called");
*out_mix_buffer_count = impl->GetSystem().GetMixBufferCount();
R_SUCCEED();
}
Result IAudioRenderer::RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
InBuffer<BufferAttr_HipcMapAlias> input) {
R_RETURN(this->RequestUpdateAuto(out_buffer, out_performance_buffer, input));
}
Result IAudioRenderer::RequestUpdateAuto(
OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
InBuffer<BufferAttr_HipcAutoSelect> input) {
LOG_TRACE(Service_Audio, "called");
const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
if (result.IsFailure()) {
LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
}
R_RETURN(result);
}
Result IAudioRenderer::Start() {
LOG_DEBUG(Service_Audio, "called");
impl->Start();
R_SUCCEED();
}
Result IAudioRenderer::Stop() {
LOG_DEBUG(Service_Audio, "called");
impl->Stop();
R_SUCCEED();
}
Result IAudioRenderer::QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_DEBUG(Service_Audio, "called");
R_UNLESS(impl->GetSystem().GetExecutionMode() != AudioCore::ExecutionMode::Manual,
Audio::ResultNotSupported);
*out_event = &rendered_event->GetReadableEvent();
R_SUCCEED();
}
Result IAudioRenderer::SetRenderingTimeLimit(u32 rendering_time_limit) {
LOG_DEBUG(Service_Audio, "called");
impl->GetSystem().SetRenderingTimeLimit(rendering_time_limit);
;
R_SUCCEED();
}
Result IAudioRenderer::GetRenderingTimeLimit(Out<u32> out_rendering_time_limit) {
LOG_DEBUG(Service_Audio, "called");
*out_rendering_time_limit = impl->GetSystem().GetRenderingTimeLimit();
R_SUCCEED();
}
Result IAudioRenderer::SetVoiceDropParameter(f32 voice_drop_parameter) {
LOG_DEBUG(Service_Audio, "called");
impl->GetSystem().SetVoiceDropParameter(voice_drop_parameter);
R_SUCCEED();
}
Result IAudioRenderer::GetVoiceDropParameter(Out<f32> out_voice_drop_parameter) {
LOG_DEBUG(Service_Audio, "called");
*out_voice_drop_parameter = impl->GetSystem().GetVoiceDropParameter();
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/renderer/audio_renderer.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KReadableEvent;
}
namespace Service::Audio {
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
s32 session_id);
~IAudioRenderer() override;
private:
Result GetSampleRate(Out<u32> out_sample_rate);
Result GetSampleCount(Out<u32> out_sample_count);
Result GetState(Out<u32> out_state);
Result GetMixBufferCount(Out<u32> out_mix_buffer_count);
Result RequestUpdate(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
OutBuffer<BufferAttr_HipcMapAlias> out_performance_buffer,
InBuffer<BufferAttr_HipcMapAlias> input);
Result RequestUpdateAuto(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer,
OutBuffer<BufferAttr_HipcAutoSelect> out_performance_buffer,
InBuffer<BufferAttr_HipcAutoSelect> input);
Result Start();
Result Stop();
Result QuerySystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result SetRenderingTimeLimit(u32 rendering_time_limit);
Result GetRenderingTimeLimit(Out<u32> out_rendering_time_limit);
Result SetVoiceDropParameter(f32 voice_drop_parameter);
Result GetVoiceDropParameter(Out<f32> out_voice_drop_parameter);
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* rendered_event;
AudioCore::Renderer::Manager& manager;
std::unique_ptr<AudioCore::Renderer::Renderer> impl;
Kernel::KProcess* process_handle;
Common::ScratchBuffer<u8> output_buffer;
Common::ScratchBuffer<u8> performance_buffer;
};
} // namespace Service::Audio

View file

@ -0,0 +1,104 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_render_manager.h"
#include "audio_core/common/feature_support.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_transfer_memory.h"
#include "core/hle/service/audio/audio_device.h"
#include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/audio/audio_renderer_manager.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::Renderer;
IAudioRendererManager::IAudioRendererManager(Core::System& system_)
: ServiceFramework{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioRendererManager::OpenAudioRenderer>, "OpenAudioRenderer"},
{1, D<&IAudioRendererManager::GetWorkBufferSize>, "GetWorkBufferSize"},
{2, D<&IAudioRendererManager::GetAudioDeviceService>, "GetAudioDeviceService"},
{3, nullptr, "OpenAudioRendererForManualExecution"},
{4, D<&IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo>, "GetAudioDeviceServiceWithRevisionInfo"},
};
// clang-format on
RegisterHandlers(functions);
}
IAudioRendererManager::~IAudioRendererManager() = default;
Result IAudioRendererManager::OpenAudioRenderer(
Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
AudioCore::AudioRendererParameterInternal parameter,
InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
R_THROW(Audio::ResultOutOfSessions);
}
const auto session_id{impl->GetSessionId()};
if (session_id == -1) {
LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
R_THROW(Audio::ResultOutOfSessions);
}
LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
impl->GetSessionCount());
*out_audio_renderer =
std::make_shared<IAudioRenderer>(system, *impl, parameter, tmem_handle.Get(), tmem_size,
process_handle.Get(), aruid.pid, session_id);
R_SUCCEED();
}
Result IAudioRendererManager::GetWorkBufferSize(Out<u64> out_size,
AudioCore::AudioRendererParameterInternal params) {
LOG_DEBUG(Service_Audio, "called");
R_TRY(impl->GetWorkBufferSize(params, *out_size))
std::string output_info{};
output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
output_info +=
fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
output_info += fmt::format(
"\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
"{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
"Context {:04X}",
params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
params.splitter_destinations, params.voices, params.perf_frames,
params.external_context_size);
LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
output_info, *out_size);
R_SUCCEED();
}
Result IAudioRendererManager::GetAudioDeviceService(
Out<SharedPointer<IAudioDevice>> out_audio_device, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called, aruid={:#x}", aruid.pid);
*out_audio_device = std::make_shared<IAudioDevice>(
system, aruid.pid, Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
R_SUCCEED();
}
Result IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(
Out<SharedPointer<IAudioDevice>> out_audio_device, u32 revision,
ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called, revision={} aruid={:#x}", AudioCore::GetRevisionNum(revision),
aruid.pid);
*out_audio_device =
std::make_shared<IAudioDevice>(system, aruid.pid, revision, num_audio_devices++);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/audio_render_manager.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
class IAudioDevice;
class IAudioRenderer;
class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
public:
explicit IAudioRendererManager(Core::System& system_);
~IAudioRendererManager() override;
private:
Result OpenAudioRenderer(Out<SharedPointer<IAudioRenderer>> out_audio_renderer,
AudioCore::AudioRendererParameterInternal parameter,
InCopyHandle<Kernel::KTransferMemory> tmem_handle, u64 tmem_size,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid);
Result GetWorkBufferSize(Out<u64> out_size,
AudioCore::AudioRendererParameterInternal parameter);
Result GetAudioDeviceService(Out<SharedPointer<IAudioDevice>> out_audio_device,
ClientAppletResourceUserId aruid);
Result GetAudioDeviceServiceWithRevisionInfo(Out<SharedPointer<IAudioDevice>> out_audio_device,
u32 revision, ClientAppletResourceUserId aruid);
std::unique_ptr<AudioCore::Renderer::Manager> impl;
u32 num_audio_devices{0};
};
} // namespace Service::Audio

View file

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/final_output_recorder_manager.h"
namespace Service::Audio {
class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
public:
explicit IFinalOutputRecorder(Core::System& system_)
: ServiceFramework{system_, "IFinalOutputRecorder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetFinalOutputRecorderState"},
{1, nullptr, "Start"},
{2, nullptr, "Stop"},
{3, nullptr, "AppendFinalOutputRecorderBuffer"},
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedFinalOutputRecorderBuffers"},
{6, nullptr, "ContainsFinalOutputRecorderBuffer"},
{7, nullptr, "GetFinalOutputRecorderBufferEndTime"},
{8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
{9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
{10, nullptr, "FlushFinalOutputRecorderBuffers"},
{11, nullptr, "AttachWorkBuffer"},
};
// clang-format on
RegisterHandlers(functions);
}
};
IFinalOutputRecorderManager::IFinalOutputRecorderManager(Core::System& system_)
: ServiceFramework{system_, "audrec:u"} {
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFinalOutputRecorder"},
};
RegisterHandlers(functions);
}
IFinalOutputRecorderManager::~IFinalOutputRecorderManager() = default;
} // namespace Service::Audio

View file

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class IFinalOutputRecorderManager final : public ServiceFramework<IFinalOutputRecorderManager> {
public:
explicit IFinalOutputRecorderManager(Core::System& system_);
~IFinalOutputRecorderManager() override;
};
} // namespace Service::Audio

View file

@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
namespace Service::Audio {
IFinalOutputRecorderManagerForApplet::IFinalOutputRecorderManagerForApplet(Core::System& system_)
: ServiceFramework{system_, "audrec:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "RequestSuspend"},
{1, nullptr, "RequestResume"},
};
// clang-format on
RegisterHandlers(functions);
}
IFinalOutputRecorderManagerForApplet::~IFinalOutputRecorderManagerForApplet() = default;
} // namespace Service::Audio

View file

@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::Audio {
class IFinalOutputRecorderManagerForApplet final
: public ServiceFramework<IFinalOutputRecorderManagerForApplet> {
public:
explicit IFinalOutputRecorderManagerForApplet(Core::System& system_);
~IFinalOutputRecorderManagerForApplet() override;
};
} // namespace Service::Audio

View file

@ -0,0 +1,145 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/hardware_opus_decoder.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::OpusDecoder;
IHardwareOpusDecoder::IHardwareOpusDecoder(Core::System& system_, HardwareOpus& hardware_opus)
: ServiceFramework{system_, "IHardwareOpusDecoder"},
impl{std::make_unique<AudioCore::OpusDecoder::OpusDecoder>(system_, hardware_opus)} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IHardwareOpusDecoder::DecodeInterleavedOld>, "DecodeInterleavedOld"},
{1, D<&IHardwareOpusDecoder::SetContext>, "SetContext"},
{2, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld>, "DecodeInterleavedForMultiStreamOld"},
{3, D<&IHardwareOpusDecoder::SetContextForMultiStream>, "SetContextForMultiStream"},
{4, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfOld>, "DecodeInterleavedWithPerfOld"},
{5, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld>, "DecodeInterleavedForMultiStreamWithPerfOld"},
{6, D<&IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld>, "DecodeInterleavedWithPerfAndResetOld"},
{7, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld>, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
{8, D<&IHardwareOpusDecoder::DecodeInterleaved>, "DecodeInterleaved"},
{9, D<&IHardwareOpusDecoder::DecodeInterleavedForMultiStream>, "DecodeInterleavedForMultiStream"},
};
// clang-format on
RegisterHandlers(functions);
}
IHardwareOpusDecoder::~IHardwareOpusDecoder() = default;
Result IHardwareOpusDecoder::Initialize(const OpusParametersEx& params,
Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size) {
return impl->Initialize(params, transfer_memory, transfer_memory_size);
}
Result IHardwareOpusDecoder::Initialize(const OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory,
u64 transfer_memory_size) {
return impl->Initialize(params, transfer_memory, transfer_memory_size);
}
Result IHardwareOpusDecoder::DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count,
InBuffer<BufferAttr_HipcMapAlias> opus_data) {
R_TRY(impl->DecodeInterleaved(out_data_size, nullptr, out_sample_count, opus_data, out_pcm_data,
false));
LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
*out_sample_count);
R_SUCCEED();
}
Result IHardwareOpusDecoder::SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->SetContext(decoder_context));
}
Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamOld(
OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data, Out<u32> out_data_size,
Out<u32> out_sample_count, InBuffer<BufferAttr_HipcMapAlias> opus_data) {
R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, nullptr, out_sample_count, opus_data,
out_pcm_data, false));
LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {}", *out_data_size,
*out_sample_count);
R_SUCCEED();
}
Result IHardwareOpusDecoder::SetContextForMultiStream(
InBuffer<BufferAttr_HipcMapAlias> decoder_context) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(impl->SetContext(decoder_context));
}
Result IHardwareOpusDecoder::DecodeInterleavedWithPerfOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data) {
R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
out_pcm_data, false));
LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
*out_sample_count, *out_time_taken);
R_SUCCEED();
}
Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data) {
R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
opus_data, out_pcm_data, false));
LOG_DEBUG(Service_Audio, "bytes read {:#x} samples generated {} time taken {}", *out_data_size,
*out_sample_count, *out_time_taken);
R_SUCCEED();
}
Result IHardwareOpusDecoder::DecodeInterleavedWithPerfAndResetOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
out_pcm_data, reset));
LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
*out_data_size, *out_sample_count, *out_time_taken);
R_SUCCEED();
}
Result IHardwareOpusDecoder::DecodeInterleavedForMultiStreamWithPerfAndResetOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset) {
R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
opus_data, out_pcm_data, reset));
LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
*out_data_size, *out_sample_count, *out_time_taken);
R_SUCCEED();
}
Result IHardwareOpusDecoder::DecodeInterleaved(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
bool reset) {
R_TRY(impl->DecodeInterleaved(out_data_size, out_time_taken, out_sample_count, opus_data,
out_pcm_data, reset));
LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
*out_data_size, *out_sample_count, *out_time_taken);
R_SUCCEED();
}
Result IHardwareOpusDecoder::DecodeInterleavedForMultiStream(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
bool reset) {
R_TRY(impl->DecodeInterleavedForMultiStream(out_data_size, out_time_taken, out_sample_count,
opus_data, out_pcm_data, reset));
LOG_DEBUG(Service_Audio, "reset {} bytes read {:#x} samples generated {} time taken {}", reset,
*out_data_size, *out_sample_count, *out_time_taken);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/opus/decoder.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
class IHardwareOpusDecoder final : public ServiceFramework<IHardwareOpusDecoder> {
public:
explicit IHardwareOpusDecoder(Core::System& system_,
AudioCore::OpusDecoder::HardwareOpus& hardware_opus);
~IHardwareOpusDecoder() override;
Result Initialize(const AudioCore::OpusDecoder::OpusParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
Result Initialize(const AudioCore::OpusDecoder::OpusMultiStreamParametersEx& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size);
private:
Result DecodeInterleavedOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count,
InBuffer<BufferAttr_HipcMapAlias> opus_data);
Result SetContext(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
Result DecodeInterleavedForMultiStreamOld(OutBuffer<BufferAttr_HipcMapAlias> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count,
InBuffer<BufferAttr_HipcMapAlias> opus_data);
Result SetContextForMultiStream(InBuffer<BufferAttr_HipcMapAlias> decoder_context);
Result DecodeInterleavedWithPerfOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data);
Result DecodeInterleavedForMultiStreamWithPerfOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data);
Result DecodeInterleavedWithPerfAndResetOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
Result DecodeInterleavedForMultiStreamWithPerfAndResetOld(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias> opus_data, bool reset);
Result DecodeInterleaved(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
bool reset);
Result DecodeInterleavedForMultiStream(
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_pcm_data,
Out<u32> out_data_size, Out<u32> out_sample_count, Out<u64> out_time_taken,
InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> opus_data,
bool reset);
std::unique_ptr<AudioCore::OpusDecoder::OpusDecoder> impl;
Common::ScratchBuffer<u8> output_data;
};
} // namespace Service::Audio

View file

@ -0,0 +1,156 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/audio/hardware_opus_decoder.h"
#include "core/hle/service/audio/hardware_opus_decoder_manager.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::OpusDecoder;
IHardwareOpusDecoderManager::IHardwareOpusDecoderManager(Core::System& system_)
: ServiceFramework{system_, "hwopus"}, system{system_}, impl{system} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoder>, "OpenHardwareOpusDecoder"},
{1, D<&IHardwareOpusDecoderManager::GetWorkBufferSize>, "GetWorkBufferSize"},
{2, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream>, "OpenOpusDecoderForMultiStream"},
{3, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream>, "GetWorkBufferSizeForMultiStream"},
{4, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx>, "OpenHardwareOpusDecoderEx"},
{5, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeEx>, "GetWorkBufferSizeEx"},
{6, D<&IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx>, "OpenHardwareOpusDecoderForMultiStreamEx"},
{7, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx>, "GetWorkBufferSizeForMultiStreamEx"},
{8, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeExEx>, "GetWorkBufferSizeExEx"},
{9, D<&IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx>, "GetWorkBufferSizeForMultiStreamExEx"},
};
// clang-format on
RegisterHandlers(functions);
}
IHardwareOpusDecoderManager::~IHardwareOpusDecoderManager() = default;
Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoder(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParameters params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
params.sample_rate, params.channel_count, tmem_size);
auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
OpusParametersEx ex{
.sample_rate = params.sample_rate,
.channel_count = params.channel_count,
.use_large_frame_size = false,
};
R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
*out_decoder = decoder;
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSize(Out<u32> out_size, OpusParameters params) {
R_TRY(impl.GetWorkBufferSize(params, *out_size));
LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} -- returned size {:#x}",
params.sample_rate, params.channel_count, *out_size);
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStream(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
LOG_DEBUG(Service_Audio,
"sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
"transfer_memory_size {:#x}",
params->sample_rate, params->channel_count, params->total_stream_count,
params->stereo_stream_count, tmem_size);
auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
OpusMultiStreamParametersEx ex{
.sample_rate = params->sample_rate,
.channel_count = params->channel_count,
.total_stream_count = params->total_stream_count,
.stereo_stream_count = params->stereo_stream_count,
.use_large_frame_size = false,
.mappings{},
};
std::memcpy(ex.mappings.data(), params->mappings.data(), sizeof(params->mappings));
R_TRY(decoder->Initialize(ex, tmem_handle.Get(), tmem_size));
*out_decoder = decoder;
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStream(
Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params) {
R_TRY(impl.GetWorkBufferSizeForMultiStream(*params, *out_size));
LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder, OpusParametersEx params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size {:#x}",
params.sample_rate, params.channel_count, tmem_size);
auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
R_TRY(decoder->Initialize(params, tmem_handle.Get(), tmem_size));
*out_decoder = decoder;
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSizeEx(Out<u32> out_size,
OpusParametersEx params) {
R_TRY(impl.GetWorkBufferSizeEx(params, *out_size));
LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderForMultiStreamEx(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle) {
LOG_DEBUG(Service_Audio,
"sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
"use_large_frame_size {}"
"transfer_memory_size {:#x}",
params->sample_rate, params->channel_count, params->total_stream_count,
params->stereo_stream_count, params->use_large_frame_size, tmem_size);
auto decoder{std::make_shared<IHardwareOpusDecoder>(system, impl.GetHardwareOpus())};
R_TRY(decoder->Initialize(*params, tmem_handle.Get(), tmem_size));
*out_decoder = decoder;
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(
Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
R_TRY(impl.GetWorkBufferSizeForMultiStreamEx(*params, *out_size));
LOG_DEBUG(Service_Audio,
"sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} "
"use_large_frame_size {} -- returned size {:#x}",
params->sample_rate, params->channel_count, params->total_stream_count,
params->stereo_stream_count, params->use_large_frame_size, *out_size);
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSizeExEx(Out<u32> out_size,
OpusParametersEx params) {
R_TRY(impl.GetWorkBufferSizeExEx(params, *out_size));
LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
R_SUCCEED();
}
Result IHardwareOpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(
Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params) {
R_TRY(impl.GetWorkBufferSizeForMultiStreamExEx(*params, *out_size));
LOG_DEBUG(Service_Audio, "size {:#x}", *out_size);
R_SUCCEED();
}
} // namespace Service::Audio

View file

@ -0,0 +1,53 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "audio_core/opus/decoder_manager.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::Audio {
class IHardwareOpusDecoder;
using AudioCore::OpusDecoder::OpusMultiStreamParameters;
using AudioCore::OpusDecoder::OpusMultiStreamParametersEx;
using AudioCore::OpusDecoder::OpusParameters;
using AudioCore::OpusDecoder::OpusParametersEx;
class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
public:
explicit IHardwareOpusDecoderManager(Core::System& system_);
~IHardwareOpusDecoderManager() override;
private:
Result OpenHardwareOpusDecoder(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
OpusParameters params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle);
Result GetWorkBufferSize(Out<u32> out_size, OpusParameters params);
Result OpenHardwareOpusDecoderForMultiStream(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle);
Result GetWorkBufferSizeForMultiStream(
Out<u32> out_size, InLargeData<OpusMultiStreamParameters, BufferAttr_HipcPointer> params);
Result OpenHardwareOpusDecoderEx(Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
OpusParametersEx params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle);
Result GetWorkBufferSizeEx(Out<u32> out_size, OpusParametersEx params);
Result OpenHardwareOpusDecoderForMultiStreamEx(
Out<SharedPointer<IHardwareOpusDecoder>> out_decoder,
InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params, u32 tmem_size,
InCopyHandle<Kernel::KTransferMemory> tmem_handle);
Result GetWorkBufferSizeForMultiStreamEx(
Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
Result GetWorkBufferSizeExEx(Out<u32> out_size, OpusParametersEx params);
Result GetWorkBufferSizeForMultiStreamExEx(
Out<u32> out_size, InLargeData<OpusMultiStreamParametersEx, BufferAttr_HipcPointer> params);
Core::System& system;
AudioCore::OpusDecoder::OpusDecoderManager impl;
};
} // namespace Service::Audio

View file

@ -415,7 +415,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
auto& buffer = temp[OutBufferIndex]; auto& buffer = temp[OutBufferIndex];
const size_t size = buffer.size(); const size_t size = buffer.size();
if (ctx.CanWriteBuffer(OutBufferIndex)) { if (size > 0 && ctx.CanWriteBuffer(OutBufferIndex)) {
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) { if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
ctx.WriteBuffer(buffer.data(), size, OutBufferIndex); ctx.WriteBuffer(buffer.data(), size, OutBufferIndex);
} else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) { } else if constexpr (ArgType::Attr & BufferAttr_HipcMapAlias) {

View file

@ -9,7 +9,7 @@
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/hle/service/cmif_types.h" #include "core/hle/service/cmif_types.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp/fsp_util.h" #include "core/hle/service/filesystem/fsp/fsp_types.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace FileSys::Sf { namespace FileSys::Sf {

View file

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h"
namespace Service::FileSystem {
IMultiCommitManager::IMultiCommitManager(Core::System& system_)
: ServiceFramework{system_, "IMultiCommitManager"} {
static const FunctionInfo functions[] = {
{1, D<&IMultiCommitManager::Add>, "Add"},
{2, D<&IMultiCommitManager::Commit>, "Commit"},
};
RegisterHandlers(functions);
}
IMultiCommitManager::~IMultiCommitManager() = default;
Result IMultiCommitManager::Add(std::shared_ptr<IFileSystem> filesystem) {
LOG_WARNING(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
Result IMultiCommitManager::Commit() {
LOG_WARNING(Service_FS, "(STUBBED) called");
R_SUCCEED();
}
} // namespace Service::FileSystem

View file

@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/file_sys/vfs/vfs.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class IMultiCommitManager final : public ServiceFramework<IMultiCommitManager> {
public:
explicit IMultiCommitManager(Core::System& system_);
~IMultiCommitManager() override;
private:
Result Add(std::shared_ptr<IFileSystem> filesystem);
Result Commit();
FileSys::VirtualFile backend;
};
} // namespace Service::FileSystem

View file

@ -0,0 +1,161 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/hex_util.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h"
#include "core/hle/service/filesystem/save_data_controller.h"
namespace Service::FileSystem {
ISaveDataInfoReader::ISaveDataInfoReader(Core::System& system_,
std::shared_ptr<SaveDataController> save_data_controller_,
FileSys::SaveDataSpaceId space)
: ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{
save_data_controller_} {
static const FunctionInfo functions[] = {
{0, D<&ISaveDataInfoReader::ReadSaveDataInfo>, "ReadSaveDataInfo"},
};
RegisterHandlers(functions);
FindAllSaves(space);
}
ISaveDataInfoReader::~ISaveDataInfoReader() = default;
static u64 stoull_be(std::string_view str) {
if (str.size() != 16) {
return 0;
}
const auto bytes = Common::HexStringToArray<0x8>(str);
u64 out{};
std::memcpy(&out, bytes.data(), sizeof(u64));
return Common::swap64(out);
}
Result ISaveDataInfoReader::ReadSaveDataInfo(
Out<u64> out_count, OutArray<SaveDataInfo, BufferAttr_HipcMapAlias> out_entries) {
LOG_DEBUG(Service_FS, "called");
// Calculate how many entries we can fit in the output buffer
const u64 count_entries = out_entries.size();
// Cap at total number of entries.
const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index);
// Determine data start and end
const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index);
const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries);
const auto range_size = static_cast<std::size_t>(std::distance(begin, end));
next_entry_index += actual_entries;
// Write the data to memory
std::memcpy(out_entries.data(), begin, range_size);
*out_count = actual_entries;
R_SUCCEED();
}
void ISaveDataInfoReader::FindAllSaves(FileSys::SaveDataSpaceId space) {
FileSys::VirtualDir save_root{};
const auto result = save_data_controller->OpenSaveDataSpace(&save_root, space);
if (result != ResultSuccess || save_root == nullptr) {
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
return;
}
for (const auto& type : save_root->GetSubdirectories()) {
if (type->GetName() == "save") {
FindNormalSaves(space, type);
} else if (space == FileSys::SaveDataSpaceId::Temporary) {
FindTemporaryStorageSaves(space, type);
}
}
}
void ISaveDataInfoReader::FindNormalSaves(FileSys::SaveDataSpaceId space,
const FileSys::VirtualDir& type) {
for (const auto& save_id : type->GetSubdirectories()) {
for (const auto& user_id : save_id->GetSubdirectories()) {
// Skip non user id subdirectories
if (user_id->GetName().size() != 0x20) {
continue;
}
const auto save_id_numeric = stoull_be(save_id->GetName());
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
if (save_id_numeric != 0) {
// System Save Data
info.emplace_back(SaveDataInfo{
0,
space,
FileSys::SaveDataType::System,
{},
user_id_numeric,
save_id_numeric,
0,
user_id->GetSize(),
{},
{},
});
continue;
}
for (const auto& title_id : user_id->GetSubdirectories()) {
const auto device = std::all_of(user_id_numeric.begin(), user_id_numeric.end(),
[](u8 val) { return val == 0; });
info.emplace_back(SaveDataInfo{
0,
space,
device ? FileSys::SaveDataType::Device : FileSys::SaveDataType::Account,
{},
user_id_numeric,
save_id_numeric,
stoull_be(title_id->GetName()),
title_id->GetSize(),
{},
{},
});
}
}
}
}
void ISaveDataInfoReader::FindTemporaryStorageSaves(FileSys::SaveDataSpaceId space,
const FileSys::VirtualDir& type) {
for (const auto& user_id : type->GetSubdirectories()) {
// Skip non user id subdirectories
if (user_id->GetName().size() != 0x20) {
continue;
}
for (const auto& title_id : user_id->GetSubdirectories()) {
if (!title_id->GetFiles().empty() || !title_id->GetSubdirectories().empty()) {
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
info.emplace_back(SaveDataInfo{
0,
space,
FileSys::SaveDataType::Temporary,
{},
user_id_numeric,
stoull_be(type->GetName()),
stoull_be(title_id->GetName()),
title_id->GetSize(),
{},
{},
});
}
}
}
}
} // namespace Service::FileSystem

View file

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::FileSystem {
class SaveDataController;
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
public:
explicit ISaveDataInfoReader(Core::System& system_,
std::shared_ptr<SaveDataController> save_data_controller_,
FileSys::SaveDataSpaceId space);
~ISaveDataInfoReader() override;
struct SaveDataInfo {
u64_le save_id_unknown;
FileSys::SaveDataSpaceId space;
FileSys::SaveDataType type;
INSERT_PADDING_BYTES(0x6);
std::array<u8, 0x10> user_id;
u64_le save_id;
u64_le title_id;
u64_le save_image_size;
u16_le index;
FileSys::SaveDataRank rank;
INSERT_PADDING_BYTES(0x25);
};
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
Result ReadSaveDataInfo(Out<u64> out_count,
OutArray<SaveDataInfo, BufferAttr_HipcMapAlias> out_entries);
private:
void FindAllSaves(FileSys::SaveDataSpaceId space);
void FindNormalSaves(FileSys::SaveDataSpaceId space, const FileSys::VirtualDir& type);
void FindTemporaryStorageSaves(FileSys::SaveDataSpaceId space, const FileSys::VirtualDir& type);
std::shared_ptr<SaveDataController> save_data_controller;
std::vector<SaveDataInfo> info;
u64 next_entry_index = 0;
};
} // namespace Service::FileSystem

View file

@ -2,61 +2,44 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/file_sys/errors.h" #include "core/file_sys/errors.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/fsp/fs_i_storage.h" #include "core/hle/service/filesystem/fsp/fs_i_storage.h"
#include "core/hle/service/ipc_helpers.h"
namespace Service::FileSystem { namespace Service::FileSystem {
IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_) IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_)
: ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) {
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IStorage::Read, "Read"}, {0, D<&IStorage::Read>, "Read"},
{1, nullptr, "Write"}, {1, nullptr, "Write"},
{2, nullptr, "Flush"}, {2, nullptr, "Flush"},
{3, nullptr, "SetSize"}, {3, nullptr, "SetSize"},
{4, &IStorage::GetSize, "GetSize"}, {4, D<&IStorage::GetSize>, "GetSize"},
{5, nullptr, "OperateRange"}, {5, nullptr, "OperateRange"},
}; };
RegisterHandlers(functions); RegisterHandlers(functions);
} }
void IStorage::Read(HLERequestContext& ctx) { Result IStorage::Read(
IPC::RequestParser rp{ctx}; OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_bytes,
const s64 offset = rp.Pop<s64>(); s64 offset, s64 length) {
const s64 length = rp.Pop<s64>();
LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length);
// Error checking R_UNLESS(length >= 0, FileSys::ResultInvalidSize);
if (length < 0) { R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset);
LOG_ERROR(Service_FS, "Length is less than 0, length={}", length);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ResultInvalidSize);
return;
}
if (offset < 0) {
LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ResultInvalidOffset);
return;
}
// Read the data from the Storage backend // Read the data from the Storage backend
std::vector<u8> output = backend->ReadBytes(length, offset); backend->Read(out_bytes.data(), length, offset);
// Write the data to memory
ctx.WriteBuffer(output);
IPC::ResponseBuilder rb{ctx, 2}; R_SUCCEED();
rb.Push(ResultSuccess);
} }
void IStorage::GetSize(HLERequestContext& ctx) { Result IStorage::GetSize(Out<u64> out_size) {
const u64 size = backend->GetSize(); *out_size = backend->GetSize();
LOG_DEBUG(Service_FS, "called, size={}", size);
IPC::ResponseBuilder rb{ctx, 4}; LOG_DEBUG(Service_FS, "called, size={}", *out_size);
rb.Push(ResultSuccess);
rb.Push<u64>(size); R_SUCCEED();
} }
} // namespace Service::FileSystem } // namespace Service::FileSystem

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
@ -16,8 +17,10 @@ public:
private: private:
FileSys::VirtualFile backend; FileSys::VirtualFile backend;
void Read(HLERequestContext& ctx); Result Read(
void GetSize(HLERequestContext& ctx); OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_bytes,
s64 offset, s64 length);
Result GetSize(Out<u64> out_size);
}; };
} // namespace Service::FileSystem } // namespace Service::FileSystem

View file

@ -27,8 +27,11 @@
#include "core/file_sys/system_archive/system_archive.h" #include "core/file_sys/system_archive/system_archive.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#include "core/hle/result.h" #include "core/hle/result.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" #include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
#include "core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h"
#include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h"
#include "core/hle/service/filesystem/fsp/fs_i_storage.h" #include "core/hle/service/filesystem/fsp/fs_i_storage.h"
#include "core/hle/service/filesystem/fsp/fsp_srv.h" #include "core/hle/service/filesystem/fsp/fsp_srv.h"
#include "core/hle/service/filesystem/romfs_controller.h" #include "core/hle/service/filesystem/romfs_controller.h"
@ -39,182 +42,6 @@
#include "core/reporter.h" #include "core/reporter.h"
namespace Service::FileSystem { namespace Service::FileSystem {
enum class FileSystemProxyType : u8 {
Code = 0,
Rom = 1,
Logo = 2,
Control = 3,
Manual = 4,
Meta = 5,
Data = 6,
Package = 7,
RegisteredUpdate = 8,
};
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
public:
explicit ISaveDataInfoReader(Core::System& system_,
std::shared_ptr<SaveDataController> save_data_controller_,
FileSys::SaveDataSpaceId space)
: ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{
save_data_controller_} {
static const FunctionInfo functions[] = {
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
};
RegisterHandlers(functions);
FindAllSaves(space);
}
void ReadSaveDataInfo(HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called");
// Calculate how many entries we can fit in the output buffer
const u64 count_entries = ctx.GetWriteBufferNumElements<SaveDataInfo>();
// Cap at total number of entries.
const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index);
// Determine data start and end
const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index);
const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries);
const auto range_size = static_cast<std::size_t>(std::distance(begin, end));
next_entry_index += actual_entries;
// Write the data to memory
ctx.WriteBuffer(begin, range_size);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<u64>(actual_entries);
}
private:
static u64 stoull_be(std::string_view str) {
if (str.size() != 16)
return 0;
const auto bytes = Common::HexStringToArray<0x8>(str);
u64 out{};
std::memcpy(&out, bytes.data(), sizeof(u64));
return Common::swap64(out);
}
void FindAllSaves(FileSys::SaveDataSpaceId space) {
FileSys::VirtualDir save_root{};
const auto result = save_data_controller->OpenSaveDataSpace(&save_root, space);
if (result != ResultSuccess || save_root == nullptr) {
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
return;
}
for (const auto& type : save_root->GetSubdirectories()) {
if (type->GetName() == "save") {
for (const auto& save_id : type->GetSubdirectories()) {
for (const auto& user_id : save_id->GetSubdirectories()) {
// Skip non user id subdirectories
if (user_id->GetName().size() != 0x20) {
continue;
}
const auto save_id_numeric = stoull_be(save_id->GetName());
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
if (save_id_numeric != 0) {
// System Save Data
info.emplace_back(SaveDataInfo{
0,
space,
FileSys::SaveDataType::SystemSaveData,
{},
user_id_numeric,
save_id_numeric,
0,
user_id->GetSize(),
{},
{},
});
continue;
}
for (const auto& title_id : user_id->GetSubdirectories()) {
const auto device =
std::all_of(user_id_numeric.begin(), user_id_numeric.end(),
[](u8 val) { return val == 0; });
info.emplace_back(SaveDataInfo{
0,
space,
device ? FileSys::SaveDataType::DeviceSaveData
: FileSys::SaveDataType::SaveData,
{},
user_id_numeric,
save_id_numeric,
stoull_be(title_id->GetName()),
title_id->GetSize(),
{},
{},
});
}
}
}
} else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) {
// Temporary Storage
for (const auto& user_id : type->GetSubdirectories()) {
// Skip non user id subdirectories
if (user_id->GetName().size() != 0x20) {
continue;
}
for (const auto& title_id : user_id->GetSubdirectories()) {
if (!title_id->GetFiles().empty() ||
!title_id->GetSubdirectories().empty()) {
auto user_id_numeric =
Common::HexStringToArray<0x10>(user_id->GetName());
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
info.emplace_back(SaveDataInfo{
0,
space,
FileSys::SaveDataType::TemporaryStorage,
{},
user_id_numeric,
stoull_be(type->GetName()),
stoull_be(title_id->GetName()),
title_id->GetSize(),
{},
{},
});
}
}
}
}
}
}
struct SaveDataInfo {
u64_le save_id_unknown;
FileSys::SaveDataSpaceId space;
FileSys::SaveDataType type;
INSERT_PADDING_BYTES(0x6);
std::array<u8, 0x10> user_id;
u64_le save_id;
u64_le title_id;
u64_le save_image_size;
u16_le index;
FileSys::SaveDataRank rank;
INSERT_PADDING_BYTES(0x25);
};
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
ProcessId process_id = 0;
std::shared_ptr<SaveDataController> save_data_controller;
std::vector<SaveDataInfo> info;
u64 next_entry_index = 0;
};
FSP_SRV::FSP_SRV(Core::System& system_) FSP_SRV::FSP_SRV(Core::System& system_)
: ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()}, : ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()},
@ -222,20 +49,20 @@ FSP_SRV::FSP_SRV(Core::System& system_)
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, nullptr, "OpenFileSystem"}, {0, nullptr, "OpenFileSystem"},
{1, &FSP_SRV::SetCurrentProcess, "SetCurrentProcess"}, {1, D<&FSP_SRV::SetCurrentProcess>, "SetCurrentProcess"},
{2, nullptr, "OpenDataFileSystemByCurrentProcess"}, {2, nullptr, "OpenDataFileSystemByCurrentProcess"},
{7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"}, {7, D<&FSP_SRV::OpenFileSystemWithPatch>, "OpenFileSystemWithPatch"},
{8, nullptr, "OpenFileSystemWithId"}, {8, nullptr, "OpenFileSystemWithId"},
{9, nullptr, "OpenDataFileSystemByApplicationId"}, {9, nullptr, "OpenDataFileSystemByApplicationId"},
{11, nullptr, "OpenBisFileSystem"}, {11, nullptr, "OpenBisFileSystem"},
{12, nullptr, "OpenBisStorage"}, {12, nullptr, "OpenBisStorage"},
{13, nullptr, "InvalidateBisCache"}, {13, nullptr, "InvalidateBisCache"},
{17, nullptr, "OpenHostFileSystem"}, {17, nullptr, "OpenHostFileSystem"},
{18, &FSP_SRV::OpenSdCardFileSystem, "OpenSdCardFileSystem"}, {18, D<&FSP_SRV::OpenSdCardFileSystem>, "OpenSdCardFileSystem"},
{19, nullptr, "FormatSdCardFileSystem"}, {19, nullptr, "FormatSdCardFileSystem"},
{21, nullptr, "DeleteSaveDataFileSystem"}, {21, nullptr, "DeleteSaveDataFileSystem"},
{22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"}, {22, D<&FSP_SRV::CreateSaveDataFileSystem>, "CreateSaveDataFileSystem"},
{23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"}, {23, D<&FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId>, "CreateSaveDataFileSystemBySystemSaveDataId"},
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"}, {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"}, {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"}, {26, nullptr, "FormatSdCardDryRun"},
@ -245,26 +72,26 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{31, nullptr, "OpenGameCardFileSystem"}, {31, nullptr, "OpenGameCardFileSystem"},
{32, nullptr, "ExtendSaveDataFileSystem"}, {32, nullptr, "ExtendSaveDataFileSystem"},
{33, nullptr, "DeleteCacheStorage"}, {33, nullptr, "DeleteCacheStorage"},
{34, &FSP_SRV::GetCacheStorageSize, "GetCacheStorageSize"}, {34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"},
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"}, {35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
{36, nullptr, "OpenHostFileSystemWithOption"}, {36, nullptr, "OpenHostFileSystemWithOption"},
{51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"}, {51, D<&FSP_SRV::OpenSaveDataFileSystem>, "OpenSaveDataFileSystem"},
{52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"}, {52, D<&FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId>, "OpenSaveDataFileSystemBySystemSaveDataId"},
{53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"}, {53, D<&FSP_SRV::OpenReadOnlySaveDataFileSystem>, "OpenReadOnlySaveDataFileSystem"},
{57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
{58, nullptr, "ReadSaveDataFileSystemExtraData"}, {58, nullptr, "ReadSaveDataFileSystemExtraData"},
{59, nullptr, "WriteSaveDataFileSystemExtraData"}, {59, nullptr, "WriteSaveDataFileSystemExtraData"},
{60, nullptr, "OpenSaveDataInfoReader"}, {60, nullptr, "OpenSaveDataInfoReader"},
{61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, {61, D<&FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId>, "OpenSaveDataInfoReaderBySaveDataSpaceId"},
{62, &FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage, "OpenSaveDataInfoReaderOnlyCacheStorage"}, {62, D<&FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage>, "OpenSaveDataInfoReaderOnlyCacheStorage"},
{64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, {64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
{65, nullptr, "UpdateSaveDataMacForDebug"}, {65, nullptr, "UpdateSaveDataMacForDebug"},
{66, nullptr, "WriteSaveDataFileSystemExtraData2"}, {66, nullptr, "WriteSaveDataFileSystemExtraData2"},
{67, nullptr, "FindSaveDataWithFilter"}, {67, nullptr, "FindSaveDataWithFilter"},
{68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"}, {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"},
{69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, {69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"},
{70, &FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"}, {70, D<&FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute>, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"},
{71, &FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, {71, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"},
{80, nullptr, "OpenSaveDataMetaFile"}, {80, nullptr, "OpenSaveDataMetaFile"},
{81, nullptr, "OpenSaveDataTransferManager"}, {81, nullptr, "OpenSaveDataTransferManager"},
{82, nullptr, "OpenSaveDataTransferManagerVersion2"}, {82, nullptr, "OpenSaveDataTransferManagerVersion2"},
@ -279,12 +106,12 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{110, nullptr, "OpenContentStorageFileSystem"}, {110, nullptr, "OpenContentStorageFileSystem"},
{120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
{130, nullptr, "OpenCustomStorageFileSystem"}, {130, nullptr, "OpenCustomStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, {200, D<&FSP_SRV::OpenDataStorageByCurrentProcess>, "OpenDataStorageByCurrentProcess"},
{201, nullptr, "OpenDataStorageByProgramId"}, {201, nullptr, "OpenDataStorageByProgramId"},
{202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"}, {202, D<&FSP_SRV::OpenDataStorageByDataId>, "OpenDataStorageByDataId"},
{203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"}, {203, D<&FSP_SRV::OpenPatchDataStorageByCurrentProcess>, "OpenPatchDataStorageByCurrentProcess"},
{204, nullptr, "OpenDataFileSystemByProgramIndex"}, {204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, &FSP_SRV::OpenDataStorageWithProgramIndex, "OpenDataStorageWithProgramIndex"}, {205, D<&FSP_SRV::OpenDataStorageWithProgramIndex>, "OpenDataStorageWithProgramIndex"},
{206, nullptr, "OpenDataStorageByPath"}, {206, nullptr, "OpenDataStorageByPath"},
{400, nullptr, "OpenDeviceOperator"}, {400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"}, {500, nullptr, "OpenSdCardDetectionEventNotifier"},
@ -324,25 +151,25 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{1000, nullptr, "SetBisRootForHost"}, {1000, nullptr, "SetBisRootForHost"},
{1001, nullptr, "SetSaveDataSize"}, {1001, nullptr, "SetSaveDataSize"},
{1002, nullptr, "SetSaveDataRootPath"}, {1002, nullptr, "SetSaveDataRootPath"},
{1003, &FSP_SRV::DisableAutoSaveDataCreation, "DisableAutoSaveDataCreation"}, {1003, D<&FSP_SRV::DisableAutoSaveDataCreation>, "DisableAutoSaveDataCreation"},
{1004, &FSP_SRV::SetGlobalAccessLogMode, "SetGlobalAccessLogMode"}, {1004, D<&FSP_SRV::SetGlobalAccessLogMode>, "SetGlobalAccessLogMode"},
{1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"}, {1005, D<&FSP_SRV::GetGlobalAccessLogMode>, "GetGlobalAccessLogMode"},
{1006, &FSP_SRV::OutputAccessLogToSdCard, "OutputAccessLogToSdCard"}, {1006, D<&FSP_SRV::OutputAccessLogToSdCard>, "OutputAccessLogToSdCard"},
{1007, nullptr, "RegisterUpdatePartition"}, {1007, nullptr, "RegisterUpdatePartition"},
{1008, nullptr, "OpenRegisteredUpdatePartition"}, {1008, nullptr, "OpenRegisteredUpdatePartition"},
{1009, nullptr, "GetAndClearMemoryReportInfo"}, {1009, nullptr, "GetAndClearMemoryReportInfo"},
{1010, nullptr, "SetDataStorageRedirectTarget"}, {1010, nullptr, "SetDataStorageRedirectTarget"},
{1011, &FSP_SRV::GetProgramIndexForAccessLog, "GetProgramIndexForAccessLog"}, {1011, D<&FSP_SRV::GetProgramIndexForAccessLog>, "GetProgramIndexForAccessLog"},
{1012, nullptr, "GetFsStackUsage"}, {1012, nullptr, "GetFsStackUsage"},
{1013, nullptr, "UnsetSaveDataRootPath"}, {1013, nullptr, "UnsetSaveDataRootPath"},
{1014, nullptr, "OutputMultiProgramTagAccessLog"}, {1014, nullptr, "OutputMultiProgramTagAccessLog"},
{1016, &FSP_SRV::FlushAccessLogOnSdCard, "FlushAccessLogOnSdCard"}, {1016, D<&FSP_SRV::FlushAccessLogOnSdCard>, "FlushAccessLogOnSdCard"},
{1017, nullptr, "OutputApplicationInfoAccessLog"}, {1017, nullptr, "OutputApplicationInfoAccessLog"},
{1018, nullptr, "SetDebugOption"}, {1018, nullptr, "SetDebugOption"},
{1019, nullptr, "UnsetDebugOption"}, {1019, nullptr, "UnsetDebugOption"},
{1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
{1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"}, {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
{1200, &FSP_SRV::OpenMultiCommitManager, "OpenMultiCommitManager"}, {1200, D<&FSP_SRV::OpenMultiCommitManager>, "OpenMultiCommitManager"},
{1300, nullptr, "OpenBisWiper"}, {1300, nullptr, "OpenBisWiper"},
}; };
// clang-format on // clang-format on
@ -355,234 +182,177 @@ FSP_SRV::FSP_SRV(Core::System& system_)
FSP_SRV::~FSP_SRV() = default; FSP_SRV::~FSP_SRV() = default;
void FSP_SRV::SetCurrentProcess(HLERequestContext& ctx) { Result FSP_SRV::SetCurrentProcess(ClientProcessId pid) {
current_process_id = ctx.GetPID(); current_process_id = *pid;
LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id); LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id);
const auto res = R_RETURN(
fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id); fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res);
} }
void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) { Result FSP_SRV::OpenFileSystemWithPatch(OutInterface<IFileSystem> out_interface,
IPC::RequestParser rp{ctx}; FileSystemProxyType type, u64 open_program_id) {
LOG_ERROR(Service_FS, "(STUBBED) called with type={}, program_id={:016X}", type,
struct InputParameters { open_program_id);
FileSystemProxyType type;
u64 program_id;
};
static_assert(sizeof(InputParameters) == 0x10, "InputParameters has wrong size");
const auto params = rp.PopRaw<InputParameters>();
LOG_ERROR(Service_FS, "(STUBBED) called with type={}, program_id={:016X}", params.type,
params.program_id);
// FIXME: many issues with this // FIXME: many issues with this
ASSERT(params.type == FileSystemProxyType::Manual); ASSERT(type == FileSystemProxyType::Manual);
const auto manual_romfs = romfs_controller->OpenPatchedRomFS( const auto manual_romfs = romfs_controller->OpenPatchedRomFS(
params.program_id, FileSys::ContentRecordType::HtmlDocument); open_program_id, FileSys::ContentRecordType::HtmlDocument);
ASSERT(manual_romfs != nullptr); ASSERT(manual_romfs != nullptr);
const auto extracted_romfs = FileSys::ExtractRomFS(manual_romfs); const auto extracted_romfs = FileSys::ExtractRomFS(manual_romfs);
ASSERT(extracted_romfs != nullptr); ASSERT(extracted_romfs != nullptr);
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::make_shared<IFileSystem>(
rb.Push(ResultSuccess); system, extracted_romfs, SizeGetter::FromStorageId(fsc, FileSys::StorageId::NandUser));
rb.PushIpcInterface<IFileSystem>(system, extracted_romfs,
SizeGetter::FromStorageId(fsc, FileSys::StorageId::NandUser)); R_SUCCEED();
} }
void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { Result FSP_SRV::OpenSdCardFileSystem(OutInterface<IFileSystem> out_interface) {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
FileSys::VirtualDir sdmc_dir{}; FileSys::VirtualDir sdmc_dir{};
fsc.OpenSDMC(&sdmc_dir); fsc.OpenSDMC(&sdmc_dir);
auto filesystem = std::make_shared<IFileSystem>( *out_interface = std::make_shared<IFileSystem>(
system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; R_SUCCEED();
rb.Push(ResultSuccess);
rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
} }
void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) { Result FSP_SRV::CreateSaveDataFileSystem(FileSys::SaveDataCreationInfo save_create_struct,
IPC::RequestParser rp{ctx}; FileSys::SaveDataAttribute save_struct, u128 uid) {
auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>();
[[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
u128 uid = rp.PopRaw<u128>();
LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
uid[1], uid[0]); uid[1], uid[0]);
FileSys::VirtualDir save_data_dir{}; FileSys::VirtualDir save_data_dir{};
save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::User,
save_struct); save_struct));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) { Result FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(
IPC::RequestParser rp{ctx}; FileSys::SaveDataCreationInfo save_create_struct, FileSys::SaveDataAttribute save_struct) {
auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>();
[[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo()); LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
FileSys::VirtualDir save_data_dir{}; FileSys::VirtualDir save_data_dir{};
save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandSystem, R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::System,
save_struct); save_struct));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
} }
void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { Result FSP_SRV::OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
IPC::RequestParser rp{ctx}; FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute) {
struct Parameters {
FileSys::SaveDataSpaceId space_id;
FileSys::SaveDataAttribute attribute;
};
const auto parameters = rp.PopRaw<Parameters>();
LOG_INFO(Service_FS, "called."); LOG_INFO(Service_FS, "called.");
FileSys::VirtualDir dir{}; FileSys::VirtualDir dir{};
auto result = R_TRY(save_data_controller->OpenSaveData(&dir, space_id, attribute));
save_data_controller->OpenSaveData(&dir, parameters.space_id, parameters.attribute);
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(FileSys::ResultTargetNotFound);
return;
}
FileSys::StorageId id{}; FileSys::StorageId id{};
switch (parameters.space_id) { switch (space_id) {
case FileSys::SaveDataSpaceId::NandUser: case FileSys::SaveDataSpaceId::User:
id = FileSys::StorageId::NandUser; id = FileSys::StorageId::NandUser;
break; break;
case FileSys::SaveDataSpaceId::SdCardSystem: case FileSys::SaveDataSpaceId::SdSystem:
case FileSys::SaveDataSpaceId::SdCardUser: case FileSys::SaveDataSpaceId::SdUser:
id = FileSys::StorageId::SdCard; id = FileSys::StorageId::SdCard;
break; break;
case FileSys::SaveDataSpaceId::NandSystem: case FileSys::SaveDataSpaceId::System:
id = FileSys::StorageId::NandSystem; id = FileSys::StorageId::NandSystem;
break; break;
case FileSys::SaveDataSpaceId::TemporaryStorage: case FileSys::SaveDataSpaceId::Temporary:
case FileSys::SaveDataSpaceId::ProperSystem: case FileSys::SaveDataSpaceId::ProperSystem:
case FileSys::SaveDataSpaceId::SafeMode: case FileSys::SaveDataSpaceId::SafeMode:
ASSERT(false); ASSERT(false);
} }
auto filesystem = *out_interface =
std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id)); std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; R_SUCCEED();
rb.Push(ResultSuccess);
rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
} }
void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) { Result FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute) {
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
OpenSaveDataFileSystem(ctx); R_RETURN(OpenSaveDataFileSystem(out_interface, space_id, attribute));
} }
void FSP_SRV::OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx) { Result FSP_SRV::OpenReadOnlySaveDataFileSystem(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute) {
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
OpenSaveDataFileSystem(ctx); R_RETURN(OpenSaveDataFileSystem(out_interface, space_id, attribute));
} }
void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx) { Result FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(
IPC::RequestParser rp{ctx}; OutInterface<ISaveDataInfoReader> out_interface, FileSys::SaveDataSpaceId space) {
const auto space = rp.PopRaw<FileSys::SaveDataSpaceId>();
LOG_INFO(Service_FS, "called, space={}", space); LOG_INFO(Service_FS, "called, space={}", space);
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::make_shared<ISaveDataInfoReader>(system, save_data_controller, space);
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISaveDataInfoReader>( R_SUCCEED();
std::make_shared<ISaveDataInfoReader>(system, save_data_controller, space));
} }
void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) { Result FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(
OutInterface<ISaveDataInfoReader> out_interface) {
LOG_WARNING(Service_FS, "(STUBBED) called"); LOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::make_shared<ISaveDataInfoReader>(system, save_data_controller,
rb.Push(ResultSuccess); FileSys::SaveDataSpaceId::Temporary);
rb.PushIpcInterface<ISaveDataInfoReader>(system, save_data_controller,
FileSys::SaveDataSpaceId::TemporaryStorage); R_SUCCEED();
} }
void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx) { Result FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute() {
LOG_WARNING(Service_FS, "(STUBBED) called."); LOG_WARNING(Service_FS, "(STUBBED) called.");
IPC::ResponseBuilder rb{ctx, 2}; R_SUCCEED();
rb.Push(ResultSuccess);
} }
void FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(HLERequestContext& ctx) { Result FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
IPC::RequestParser rp{ctx}; FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute,
InBuffer<BufferAttr_HipcMapAlias> mask_buffer, OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
struct Parameters {
FileSys::SaveDataSpaceId space_id;
FileSys::SaveDataAttribute attribute;
};
const auto parameters = rp.PopRaw<Parameters>();
// Stub this to None for now, backend needs an impl to read/write the SaveDataExtraData // Stub this to None for now, backend needs an impl to read/write the SaveDataExtraData
constexpr auto flags = static_cast<u32>(FileSys::SaveDataFlags::None); // In an earlier version of the code, this was returned as an out argument, but this is not
// correct
[[maybe_unused]] constexpr auto flags = static_cast<u32>(FileSys::SaveDataFlags::None);
LOG_WARNING(Service_FS, LOG_WARNING(Service_FS,
"(STUBBED) called, flags={}, space_id={}, attribute.title_id={:016X}\n" "(STUBBED) called, flags={}, space_id={}, attribute.program_id={:016X}\n"
"attribute.user_id={:016X}{:016X}, attribute.save_id={:016X}\n" "attribute.user_id={:016X}{:016X}, attribute.save_id={:016X}\n"
"attribute.type={}, attribute.rank={}, attribute.index={}", "attribute.type={}, attribute.rank={}, attribute.index={}",
flags, parameters.space_id, parameters.attribute.title_id, flags, space_id, attribute.program_id, attribute.user_id[1], attribute.user_id[0],
parameters.attribute.user_id[1], parameters.attribute.user_id[0], attribute.system_save_data_id, attribute.type, attribute.rank, attribute.index);
parameters.attribute.save_id, parameters.attribute.type, parameters.attribute.rank,
parameters.attribute.index);
IPC::ResponseBuilder rb{ctx, 3}; R_SUCCEED();
rb.Push(ResultSuccess);
rb.Push(flags);
} }
void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) { Result FSP_SRV::OpenDataStorageByCurrentProcess(OutInterface<IStorage> out_interface) {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
if (!romfs) { if (!romfs) {
auto current_romfs = romfs_controller->OpenRomFSCurrentProcess(); auto current_romfs = romfs_controller->OpenRomFSCurrentProcess();
if (!current_romfs) { if (!current_romfs) {
// TODO (bunnei): Find the right error code to use here // TODO (bunnei): Find the right error code to use here
LOG_CRITICAL(Service_FS, "no file system interface available!"); LOG_CRITICAL(Service_FS, "No file system interface available!");
IPC::ResponseBuilder rb{ctx, 2}; R_RETURN(ResultUnknown);
rb.Push(ResultUnknown);
return;
} }
romfs = current_romfs; romfs = current_romfs;
} }
auto storage = std::make_shared<IStorage>(system, romfs); *out_interface = std::make_shared<IStorage>(system, romfs);
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; R_SUCCEED();
rb.Push(ResultSuccess);
rb.PushIpcInterface<IStorage>(std::move(storage));
} }
void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) { Result FSP_SRV::OpenDataStorageByDataId(OutInterface<IStorage> out_interface,
IPC::RequestParser rp{ctx}; FileSys::StorageId storage_id, u32 unknown, u64 title_id) {
const auto storage_id = rp.PopRaw<FileSys::StorageId>();
const auto unknown = rp.PopRaw<u32>();
const auto title_id = rp.PopRaw<u64>();
LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}", LOG_DEBUG(Service_FS, "called with storage_id={:02X}, unknown={:08X}, title_id={:016X}",
storage_id, unknown, title_id); storage_id, unknown, title_id);
@ -592,19 +362,15 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
if (archive != nullptr) { if (archive != nullptr) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::make_shared<IStorage>(system, archive);
rb.Push(ResultSuccess); R_SUCCEED();
rb.PushIpcInterface(std::make_shared<IStorage>(system, archive));
return;
} }
// TODO(DarkLordZach): Find the right error code to use here // TODO(DarkLordZach): Find the right error code to use here
LOG_ERROR(Service_FS, LOG_ERROR(Service_FS,
"could not open data storage with title_id={:016X}, storage_id={:02X}", title_id, "Could not open data storage with title_id={:016X}, storage_id={:02X}", title_id,
storage_id); storage_id);
IPC::ResponseBuilder rb{ctx, 2}; R_RETURN(ResultUnknown);
rb.Push(ResultUnknown);
return;
} }
const FileSys::PatchManager pm{title_id, fsc, content_provider}; const FileSys::PatchManager pm{title_id, fsc, content_provider};
@ -614,28 +380,20 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
auto storage = std::make_shared<IStorage>( auto storage = std::make_shared<IStorage>(
system, pm.PatchRomFS(base.get(), std::move(data), FileSys::ContentRecordType::Data)); system, pm.PatchRomFS(base.get(), std::move(data), FileSys::ContentRecordType::Data));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::move(storage);
rb.Push(ResultSuccess); R_SUCCEED();
rb.PushIpcInterface<IStorage>(std::move(storage));
} }
void FSP_SRV::OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx) { Result FSP_SRV::OpenPatchDataStorageByCurrentProcess(OutInterface<IStorage> out_interface,
IPC::RequestParser rp{ctx}; FileSys::StorageId storage_id, u64 title_id) {
LOG_WARNING(Service_FS, "(STUBBED) called with storage_id={:02X}, title_id={:016X}", storage_id,
title_id);
const auto storage_id = rp.PopRaw<FileSys::StorageId>(); R_RETURN(FileSys::ResultTargetNotFound);
const auto title_id = rp.PopRaw<u64>();
LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", storage_id, title_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(FileSys::ResultTargetNotFound);
} }
void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { Result FSP_SRV::OpenDataStorageWithProgramIndex(OutInterface<IStorage> out_interface,
IPC::RequestParser rp{ctx}; u8 program_index) {
const auto program_index = rp.PopRaw<u8>();
LOG_DEBUG(Service_FS, "called, program_index={}", program_index); LOG_DEBUG(Service_FS, "called, program_index={}", program_index);
auto patched_romfs = romfs_controller->OpenPatchedRomFSWithProgramIndex( auto patched_romfs = romfs_controller->OpenPatchedRomFSWithProgramIndex(
@ -643,123 +401,80 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
if (!patched_romfs) { if (!patched_romfs) {
// TODO: Find the right error code to use here // TODO: Find the right error code to use here
LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); LOG_ERROR(Service_FS, "Could not open storage with program_index={}", program_index);
R_RETURN(ResultUnknown);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultUnknown);
return;
} }
auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs)); *out_interface = std::make_shared<IStorage>(system, std::move(patched_romfs));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; R_SUCCEED();
rb.Push(ResultSuccess);
rb.PushIpcInterface<IStorage>(std::move(storage));
} }
void FSP_SRV::DisableAutoSaveDataCreation(HLERequestContext& ctx) { Result FSP_SRV::DisableAutoSaveDataCreation() {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
save_data_controller->SetAutoCreate(false); save_data_controller->SetAutoCreate(false);
IPC::ResponseBuilder rb{ctx, 2}; R_SUCCEED();
rb.Push(ResultSuccess);
} }
void FSP_SRV::SetGlobalAccessLogMode(HLERequestContext& ctx) { Result FSP_SRV::SetGlobalAccessLogMode(AccessLogMode access_log_mode_) {
IPC::RequestParser rp{ctx}; LOG_DEBUG(Service_FS, "called, access_log_mode={}", access_log_mode_);
access_log_mode = rp.PopEnum<AccessLogMode>();
LOG_DEBUG(Service_FS, "called, access_log_mode={}", access_log_mode); access_log_mode = access_log_mode_;
IPC::ResponseBuilder rb{ctx, 2}; R_SUCCEED();
rb.Push(ResultSuccess);
} }
void FSP_SRV::GetGlobalAccessLogMode(HLERequestContext& ctx) { Result FSP_SRV::GetGlobalAccessLogMode(Out<AccessLogMode> out_access_log_mode) {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 3}; *out_access_log_mode = access_log_mode;
rb.Push(ResultSuccess);
rb.PushEnum(access_log_mode); R_SUCCEED();
} }
void FSP_SRV::OutputAccessLogToSdCard(HLERequestContext& ctx) { Result FSP_SRV::OutputAccessLogToSdCard(InBuffer<BufferAttr_HipcMapAlias> log_message_buffer) {
const auto raw = ctx.ReadBufferCopy(); LOG_DEBUG(Service_FS, "called");
auto log = Common::StringFromFixedZeroTerminatedBuffer( auto log = Common::StringFromFixedZeroTerminatedBuffer(
reinterpret_cast<const char*>(raw.data()), raw.size()); reinterpret_cast<const char*>(log_message_buffer.data()), log_message_buffer.size());
LOG_DEBUG(Service_FS, "called");
reporter.SaveFSAccessLog(log); reporter.SaveFSAccessLog(log);
IPC::ResponseBuilder rb{ctx, 2}; R_SUCCEED();
rb.Push(ResultSuccess);
} }
void FSP_SRV::GetProgramIndexForAccessLog(HLERequestContext& ctx) { Result FSP_SRV::GetProgramIndexForAccessLog(Out<AccessLogVersion> out_access_log_version,
LOG_DEBUG(Service_FS, "called"); Out<u32> out_access_log_program_index) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.PushEnum(AccessLogVersion::Latest);
rb.Push(access_log_program_index);
}
void FSP_SRV::FlushAccessLogOnSdCard(HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "(STUBBED) called"); LOG_DEBUG(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; *out_access_log_version = AccessLogVersion::Latest;
rb.Push(ResultSuccess); *out_access_log_program_index = access_log_program_index;
R_SUCCEED();
} }
void FSP_SRV::GetCacheStorageSize(HLERequestContext& ctx) { Result FSP_SRV::FlushAccessLogOnSdCard() {
IPC::RequestParser rp{ctx}; LOG_DEBUG(Service_FS, "(STUBBED) called");
const auto index{rp.Pop<s32>()};
R_SUCCEED();
}
Result FSP_SRV::GetCacheStorageSize(s32 index, Out<s64> out_data_size, Out<s64> out_journal_size) {
LOG_WARNING(Service_FS, "(STUBBED) called with index={}", index); LOG_WARNING(Service_FS, "(STUBBED) called with index={}", index);
IPC::ResponseBuilder rb{ctx, 6}; *out_data_size = 0;
rb.Push(ResultSuccess); *out_journal_size = 0;
rb.Push(s64{0});
rb.Push(s64{0}); R_SUCCEED();
} }
class IMultiCommitManager final : public ServiceFramework<IMultiCommitManager> { Result FSP_SRV::OpenMultiCommitManager(OutInterface<IMultiCommitManager> out_interface) {
public:
explicit IMultiCommitManager(Core::System& system_)
: ServiceFramework{system_, "IMultiCommitManager"} {
static const FunctionInfo functions[] = {
{1, &IMultiCommitManager::Add, "Add"},
{2, &IMultiCommitManager::Commit, "Commit"},
};
RegisterHandlers(functions);
}
private:
FileSys::VirtualFile backend;
void Add(HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void Commit(HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
};
void FSP_SRV::OpenMultiCommitManager(HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; *out_interface = std::make_shared<IMultiCommitManager>(system);
rb.Push(ResultSuccess);
rb.PushIpcInterface<IMultiCommitManager>(std::make_shared<IMultiCommitManager>(system)); R_SUCCEED();
} }
} // namespace Service::FileSystem } // namespace Service::FileSystem

View file

@ -4,6 +4,9 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include "core/file_sys/fs_save_data_types.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/filesystem/fsp/fsp_types.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Core { namespace Core {
@ -20,6 +23,11 @@ namespace Service::FileSystem {
class RomFsController; class RomFsController;
class SaveDataController; class SaveDataController;
class IFileSystem;
class ISaveDataInfoReader;
class IStorage;
class IMultiCommitManager;
enum class AccessLogVersion : u32 { enum class AccessLogVersion : u32 {
V7_0_0 = 2, V7_0_0 = 2,
@ -38,30 +46,46 @@ public:
~FSP_SRV() override; ~FSP_SRV() override;
private: private:
void SetCurrentProcess(HLERequestContext& ctx); Result SetCurrentProcess(ClientProcessId pid);
void OpenFileSystemWithPatch(HLERequestContext& ctx); Result OpenFileSystemWithPatch(OutInterface<IFileSystem> out_interface,
void OpenSdCardFileSystem(HLERequestContext& ctx); FileSystemProxyType type, u64 open_program_id);
void CreateSaveDataFileSystem(HLERequestContext& ctx); Result OpenSdCardFileSystem(OutInterface<IFileSystem> out_interface);
void CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx); Result CreateSaveDataFileSystem(FileSys::SaveDataCreationInfo save_create_struct,
void OpenSaveDataFileSystem(HLERequestContext& ctx); FileSys::SaveDataAttribute save_struct, u128 uid);
void OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx); Result CreateSaveDataFileSystemBySystemSaveDataId(
void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx); FileSys::SaveDataCreationInfo save_create_struct, FileSys::SaveDataAttribute save_struct);
void OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx); Result OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
void OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx); FileSys::SaveDataSpaceId space_id,
void WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx); FileSys::SaveDataAttribute attribute);
void ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(HLERequestContext& ctx); Result OpenSaveDataFileSystemBySystemSaveDataId(OutInterface<IFileSystem> out_interface,
void OpenDataStorageByCurrentProcess(HLERequestContext& ctx); FileSys::SaveDataSpaceId space_id,
void OpenDataStorageByDataId(HLERequestContext& ctx); FileSys::SaveDataAttribute attribute);
void OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx); Result OpenReadOnlySaveDataFileSystem(OutInterface<IFileSystem> out_interface,
void OpenDataStorageWithProgramIndex(HLERequestContext& ctx); FileSys::SaveDataSpaceId space_id,
void DisableAutoSaveDataCreation(HLERequestContext& ctx); FileSys::SaveDataAttribute attribute);
void SetGlobalAccessLogMode(HLERequestContext& ctx); Result OpenSaveDataInfoReaderBySaveDataSpaceId(OutInterface<ISaveDataInfoReader> out_interface,
void GetGlobalAccessLogMode(HLERequestContext& ctx); FileSys::SaveDataSpaceId space);
void OutputAccessLogToSdCard(HLERequestContext& ctx); Result OpenSaveDataInfoReaderOnlyCacheStorage(OutInterface<ISaveDataInfoReader> out_interface);
void FlushAccessLogOnSdCard(HLERequestContext& ctx); Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute();
void GetProgramIndexForAccessLog(HLERequestContext& ctx); Result ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(
void OpenMultiCommitManager(HLERequestContext& ctx); FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute,
void GetCacheStorageSize(HLERequestContext& ctx); InBuffer<BufferAttr_HipcMapAlias> mask_buffer,
OutBuffer<BufferAttr_HipcMapAlias> out_buffer);
Result OpenDataStorageByCurrentProcess(OutInterface<IStorage> out_interface);
Result OpenDataStorageByDataId(OutInterface<IStorage> out_interface,
FileSys::StorageId storage_id, u32 unknown, u64 title_id);
Result OpenPatchDataStorageByCurrentProcess(OutInterface<IStorage> out_interface,
FileSys::StorageId storage_id, u64 title_id);
Result OpenDataStorageWithProgramIndex(OutInterface<IStorage> out_interface, u8 program_index);
Result DisableAutoSaveDataCreation();
Result SetGlobalAccessLogMode(AccessLogMode access_log_mode_);
Result GetGlobalAccessLogMode(Out<AccessLogMode> out_access_log_mode);
Result OutputAccessLogToSdCard(InBuffer<BufferAttr_HipcMapAlias> log_message_buffer);
Result FlushAccessLogOnSdCard();
Result GetProgramIndexForAccessLog(Out<AccessLogVersion> out_access_log_version,
Out<u32> out_access_log_program_index);
Result OpenMultiCommitManager(OutInterface<IMultiCommitManager> out_interface);
Result GetCacheStorageSize(s32 index, Out<s64> out_data_size, Out<s64> out_journal_size);
FileSystemController& fsc; FileSystemController& fsc;
const FileSys::ContentProvider& content_provider; const FileSys::ContentProvider& content_provider;

View file

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/service/filesystem/filesystem.h"
namespace Service::FileSystem {
enum class FileSystemProxyType : u8 {
Code = 0,
Rom = 1,
Logo = 2,
Control = 3,
Manual = 4,
Meta = 5,
Data = 6,
Package = 7,
RegisteredUpdate = 8,
};
struct SizeGetter {
std::function<u64()> get_free_size;
std::function<u64()> get_total_size;
static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) {
return {
[&fsc, id] { return fsc.GetFreeSpaceSize(id); },
[&fsc, id] { return fsc.GetTotalSpaceSize(id); },
};
}
};
} // namespace Service::FileSystem

View file

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/daemon_controller.h"
namespace Service::OLSC {
IDaemonController::IDaemonController(Core::System& system_)
: ServiceFramework{system_, "IDaemonController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IDaemonController::GetAutoTransferEnabledForAccountAndApplication>, "GetAutoTransferEnabledForAccountAndApplication"},
{1, nullptr, "SetAutoTransferEnabledForAccountAndApplication"},
{2, nullptr, "GetGlobalUploadEnabledForAccount"},
{3, nullptr, "SetGlobalUploadEnabledForAccount"},
{4, nullptr, "TouchAccount"},
{5, nullptr, "GetGlobalDownloadEnabledForAccount"},
{6, nullptr, "SetGlobalDownloadEnabledForAccount"},
{10, nullptr, "GetForbiddenSaveDataIndication"},
{11, nullptr, "GetStopperObject"},
{12, nullptr, "GetState"},
};
// clang-format on
RegisterHandlers(functions);
}
IDaemonController::~IDaemonController() = default;
Result IDaemonController::GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
Common::UUID user_id,
u64 application_id) {
LOG_WARNING(Service_OLSC, "(STUBBED) called, user_id={} application_id={:016X}",
user_id.FormattedString(), application_id);
*out_is_enabled = false;
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/uuid.h"
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
class IDaemonController final : public ServiceFramework<IDaemonController> {
public:
explicit IDaemonController(Core::System& system_);
~IDaemonController() override;
private:
Result GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
Common::UUID user_id, u64 application_id);
};
} // namespace Service::OLSC

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/native_handle_holder.h"
namespace Service::OLSC {
INativeHandleHolder::INativeHandleHolder(Core::System& system_)
: ServiceFramework{system_, "INativeHandleHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&INativeHandleHolder::GetNativeHandle>, "GetNativeHandle"},
};
// clang-format on
RegisterHandlers(functions);
}
INativeHandleHolder::~INativeHandleHolder() = default;
Result INativeHandleHolder::GetNativeHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
*out_event = nullptr;
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,22 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Kernel {
class KReadableEvent;
}
namespace Service::OLSC {
class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
public:
explicit INativeHandleHolder(Core::System& system_);
~INativeHandleHolder() override;
private:
Result GetNativeHandle(OutCopyHandle<Kernel::KReadableEvent> out_event);
};
} // namespace Service::OLSC

View file

@ -1,226 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/olsc/olsc.h" #include "core/hle/service/olsc/olsc.h"
#include "core/hle/service/olsc/olsc_service_for_application.h"
#include "core/hle/service/olsc/olsc_service_for_system_service.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Service::OLSC { namespace Service::OLSC {
class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
public:
explicit IOlscServiceForApplication(Core::System& system_)
: ServiceFramework{system_, "olsc:u"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IOlscServiceForApplication::Initialize, "Initialize"},
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
{13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
{14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
{15, nullptr, "SetCustomData"},
{16, nullptr, "DeleteSaveDataBackupSetting"},
{18, nullptr, "GetSaveDataBackupInfoCache"},
{19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"},
{22, nullptr, "DeleteSaveDataBackupAsync"},
{25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
{26, nullptr, "DownloadSaveDataBackupAsync"},
{27, nullptr, "UploadSaveDataBackupAsync"},
{9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
{9013, nullptr, "GetSaveDataBackupSettingForDebug"},
{9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
{9015, nullptr, "SetCustomDataForDebug"},
{9016, nullptr, "DeleteSaveDataBackupSettingForDebug"},
{9018, nullptr, "GetSaveDataBackupInfoCacheForDebug"},
{9019, nullptr, "UpdateSaveDataBackupInfoCacheAsyncForDebug"},
{9022, nullptr, "DeleteSaveDataBackupAsyncForDebug"},
{9025, nullptr, "ListDownloadableSaveDataBackupInfoAsyncForDebug"},
{9026, nullptr, "DownloadSaveDataBackupAsyncForDebug"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void Initialize(HLERequestContext& ctx) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
initialized = true;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetSaveDataBackupSetting(HLERequestContext& ctx) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
// backup_setting is set to 0 since real value is unknown
constexpr u64 backup_setting = 0;
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(backup_setting);
}
void SetSaveDataBackupSettingEnabled(HLERequestContext& ctx) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
bool initialized{};
};
class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
public:
explicit INativeHandleHolder(Core::System& system_)
: ServiceFramework{system_, "INativeHandleHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetNativeHandle"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
public:
explicit ITransferTaskListController(Core::System& system_)
: ServiceFramework{system_, "ITransferTaskListController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "GetRemoteStorageController"},
{9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
{25, nullptr, "Unknown25"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetNativeHandleHolder(HLERequestContext& ctx) {
LOG_INFO(Service_OLSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INativeHandleHolder>(system);
}
};
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
public:
explicit IOlscServiceForSystemService(Core::System& system_)
: ServiceFramework{system_, "olsc:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"},
{1, nullptr, "OpenRemoteStorageController"},
{2, nullptr, "OpenDaemonController"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{100, nullptr, "ListLastTransferTaskErrorInfo"},
{101, nullptr, "GetLastErrorInfoCount"},
{102, nullptr, "RemoveLastErrorInfoOld"},
{103, nullptr, "GetLastErrorInfo"},
{104, nullptr, "GetLastErrorEventHolder"},
{105, nullptr, "GetLastTransferTaskErrorInfo"},
{200, nullptr, "GetDataTransferPolicyInfo"},
{201, nullptr, "RemoveDataTransferPolicyInfo"},
{202, nullptr, "UpdateDataTransferPolicyOld"},
{203, nullptr, "UpdateDataTransferPolicy"},
{204, nullptr, "CleanupDataTransferPolicyInfo"},
{205, nullptr, "RequestDataTransferPolicy"},
{300, nullptr, "GetAutoTransferSeriesInfo"},
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
{900, nullptr, "CleanupTransferTask"},
{902, nullptr, "CleanupSeriesInfoType0"},
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
{905, nullptr, "CleanupErrorHistory"},
{906, nullptr, "SetLastError"},
{907, nullptr, "AddSaveDataArchiveInfoType0"},
{908, nullptr, "RemoveSeriesInfoType0"},
{909, nullptr, "GetSeriesInfoType0"},
{910, nullptr, "RemoveLastErrorInfo"},
{911, nullptr, "CleanupSeriesInfoType1"},
{912, nullptr, "RemoveSeriesInfoType1"},
{913, nullptr, "GetSeriesInfoType1"},
{1000, nullptr, "UpdateIssueOld"},
{1010, nullptr, "Unknown1010"},
{1011, nullptr, "ListIssueInfoOld"},
{1012, nullptr, "GetIssueOld"},
{1013, nullptr, "GetIssue2Old"},
{1014, nullptr, "GetIssue3Old"},
{1020, nullptr, "RepairIssueOld"},
{1021, nullptr, "RepairIssueWithUserIdOld"},
{1022, nullptr, "RepairIssue2Old"},
{1023, nullptr, "RepairIssue3Old"},
{1024, nullptr, "Unknown1024"},
{1100, nullptr, "UpdateIssue"},
{1110, nullptr, "Unknown1110"},
{1111, nullptr, "ListIssueInfo"},
{1112, nullptr, "GetIssue"},
{1113, nullptr, "GetIssue2"},
{1114, nullptr, "GetIssue3"},
{1120, nullptr, "RepairIssue"},
{1121, nullptr, "RepairIssueWithUserId"},
{1122, nullptr, "RepairIssue2"},
{1123, nullptr, "RepairIssue3"},
{1124, nullptr, "Unknown1124"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenTransferTaskListController(HLERequestContext& ctx) {
LOG_INFO(Service_OLSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ITransferTaskListController>(system);
}
};
void LoopProcess(Core::System& system) { void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system); auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("olsc:u", const auto OlscFactoryForApplication = [&] {
std::make_shared<IOlscServiceForApplication>(system)); return std::make_shared<IOlscServiceForApplication>(system);
server_manager->RegisterNamedService("olsc:s", };
std::make_shared<IOlscServiceForSystemService>(system));
const auto OlscFactoryForSystemService = [&] {
return std::make_shared<IOlscServiceForSystemService>(system);
};
server_manager->RegisterNamedService("olsc:u", OlscFactoryForApplication);
server_manager->RegisterNamedService("olsc:s", OlscFactoryForSystemService);
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }

View file

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/olsc_service_for_application.h"
namespace Service::OLSC {
IOlscServiceForApplication::IOlscServiceForApplication(Core::System& system_)
: ServiceFramework{system_, "olsc:u"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IOlscServiceForApplication::Initialize>, "Initialize"},
{10, nullptr, "VerifySaveDataBackupLicenseAsync"},
{13, D<&IOlscServiceForApplication::GetSaveDataBackupSetting>, "GetSaveDataBackupSetting"},
{14, D<&IOlscServiceForApplication::SetSaveDataBackupSettingEnabled>, "SetSaveDataBackupSettingEnabled"},
{15, nullptr, "SetCustomData"},
{16, nullptr, "DeleteSaveDataBackupSetting"},
{18, nullptr, "GetSaveDataBackupInfoCache"},
{19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"},
{22, nullptr, "DeleteSaveDataBackupAsync"},
{25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
{26, nullptr, "DownloadSaveDataBackupAsync"},
{27, nullptr, "UploadSaveDataBackupAsync"},
{9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
{9013, nullptr, "GetSaveDataBackupSettingForDebug"},
{9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
{9015, nullptr, "SetCustomDataForDebug"},
{9016, nullptr, "DeleteSaveDataBackupSettingForDebug"},
{9018, nullptr, "GetSaveDataBackupInfoCacheForDebug"},
{9019, nullptr, "UpdateSaveDataBackupInfoCacheAsyncForDebug"},
{9022, nullptr, "DeleteSaveDataBackupAsyncForDebug"},
{9025, nullptr, "ListDownloadableSaveDataBackupInfoAsyncForDebug"},
{9026, nullptr, "DownloadSaveDataBackupAsyncForDebug"},
};
// clang-format on
RegisterHandlers(functions);
}
IOlscServiceForApplication::~IOlscServiceForApplication() = default;
Result IOlscServiceForApplication::Initialize(ClientProcessId process_id) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
initialized = true;
R_SUCCEED();
}
Result IOlscServiceForApplication::GetSaveDataBackupSetting(Out<u8> out_save_data_backup_setting) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
// backup_setting is set to 0 since real value is unknown
*out_save_data_backup_setting = 0;
R_SUCCEED();
}
Result IOlscServiceForApplication::SetSaveDataBackupSettingEnabled(bool enabled,
NS::Uid account_id) {
LOG_WARNING(Service_OLSC, "(STUBBED) called, enabled={}, account_id={}", enabled,
account_id.uuid.FormattedString());
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/ns/ns_types.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> {
public:
explicit IOlscServiceForApplication(Core::System& system_);
~IOlscServiceForApplication() override;
private:
Result Initialize(ClientProcessId process_id);
Result GetSaveDataBackupSetting(Out<u8> out_save_data_backup_setting);
Result SetSaveDataBackupSettingEnabled(bool enabled, NS::Uid account_id);
bool initialized{};
};
} // namespace Service::OLSC

View file

@ -0,0 +1,117 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/daemon_controller.h"
#include "core/hle/service/olsc/olsc_service_for_system_service.h"
#include "core/hle/service/olsc/remote_storage_controller.h"
#include "core/hle/service/olsc/transfer_task_list_controller.h"
namespace Service::OLSC {
IOlscServiceForSystemService::IOlscServiceForSystemService(Core::System& system_)
: ServiceFramework{system_, "olsc:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IOlscServiceForSystemService::OpenTransferTaskListController>, "OpenTransferTaskListController"},
{1, D<&IOlscServiceForSystemService::OpenRemoteStorageController>, "OpenRemoteStorageController"},
{2, D<&IOlscServiceForSystemService::OpenDaemonController>, "OpenDaemonController"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{100, nullptr, "ListLastTransferTaskErrorInfo"},
{101, nullptr, "GetLastErrorInfoCount"},
{102, nullptr, "RemoveLastErrorInfoOld"},
{103, nullptr, "GetLastErrorInfo"},
{104, nullptr, "GetLastErrorEventHolder"},
{105, nullptr, "GetLastTransferTaskErrorInfo"},
{200, D<&IOlscServiceForSystemService::GetDataTransferPolicyInfo>, "GetDataTransferPolicyInfo"},
{201, nullptr, "RemoveDataTransferPolicyInfo"},
{202, nullptr, "UpdateDataTransferPolicyOld"},
{203, nullptr, "UpdateDataTransferPolicy"},
{204, nullptr, "CleanupDataTransferPolicyInfo"},
{205, nullptr, "RequestDataTransferPolicy"},
{300, nullptr, "GetAutoTransferSeriesInfo"},
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
{900, nullptr, "CleanupTransferTask"},
{902, nullptr, "CleanupSeriesInfoType0"},
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
{905, nullptr, "CleanupErrorHistory"},
{906, nullptr, "SetLastError"},
{907, nullptr, "AddSaveDataArchiveInfoType0"},
{908, nullptr, "RemoveSeriesInfoType0"},
{909, nullptr, "GetSeriesInfoType0"},
{910, nullptr, "RemoveLastErrorInfo"},
{911, nullptr, "CleanupSeriesInfoType1"},
{912, nullptr, "RemoveSeriesInfoType1"},
{913, nullptr, "GetSeriesInfoType1"},
{1000, nullptr, "UpdateIssueOld"},
{1010, nullptr, "Unknown1010"},
{1011, nullptr, "ListIssueInfoOld"},
{1012, nullptr, "GetIssueOld"},
{1013, nullptr, "GetIssue2Old"},
{1014, nullptr, "GetIssue3Old"},
{1020, nullptr, "RepairIssueOld"},
{1021, nullptr, "RepairIssueWithUserIdOld"},
{1022, nullptr, "RepairIssue2Old"},
{1023, nullptr, "RepairIssue3Old"},
{1024, nullptr, "Unknown1024"},
{1100, nullptr, "UpdateIssue"},
{1110, nullptr, "Unknown1110"},
{1111, nullptr, "ListIssueInfo"},
{1112, nullptr, "GetIssue"},
{1113, nullptr, "GetIssue2"},
{1114, nullptr, "GetIssue3"},
{1120, nullptr, "RepairIssue"},
{1121, nullptr, "RepairIssueWithUserId"},
{1122, nullptr, "RepairIssue2"},
{1123, nullptr, "RepairIssue3"},
{1124, nullptr, "Unknown1124"},
{10000, D<&IOlscServiceForSystemService::CloneService>, "CloneService"},
};
// clang-format on
RegisterHandlers(functions);
}
IOlscServiceForSystemService::~IOlscServiceForSystemService() = default;
Result IOlscServiceForSystemService::OpenTransferTaskListController(
Out<SharedPointer<ITransferTaskListController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<ITransferTaskListController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::OpenRemoteStorageController(
Out<SharedPointer<IRemoteStorageController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<IRemoteStorageController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::OpenDaemonController(
Out<SharedPointer<IDaemonController>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::make_shared<IDaemonController>(system);
R_SUCCEED();
}
Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(Out<u16> out_policy_info,
u64 application_id) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
*out_policy_info = 0;
R_SUCCEED();
}
Result IOlscServiceForSystemService::CloneService(
Out<SharedPointer<IOlscServiceForSystemService>> out_interface) {
LOG_INFO(Service_OLSC, "called");
*out_interface = std::static_pointer_cast<IOlscServiceForSystemService>(shared_from_this());
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
class IDaemonController;
class IRemoteStorageController;
class ITransferTaskListController;
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
public:
explicit IOlscServiceForSystemService(Core::System& system_);
~IOlscServiceForSystemService() override;
private:
Result OpenTransferTaskListController(
Out<SharedPointer<ITransferTaskListController>> out_interface);
Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
Result GetDataTransferPolicyInfo(Out<u16> out_policy_info, u64 application_id);
Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
};
} // namespace Service::OLSC

View file

@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/remote_storage_controller.h"
namespace Service::OLSC {
IRemoteStorageController::IRemoteStorageController(Core::System& system_)
: ServiceFramework{system_, "IRemoteStorageController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetSaveDataArchiveInfoBySaveDataId"},
{1, nullptr, "GetSaveDataArchiveInfoByApplicationId"},
{3, nullptr, "GetSaveDataArchiveCount"},
{6, nullptr, "CleanupSaveDataArchives"},
{7, nullptr, "CreateSaveDataArchiveCacheUpdationTask"},
{8, nullptr, "CreateSaveDataArchiveCacheUpdationForSpecifiedApplicationTask"},
{9, nullptr, "Delete"},
{10, nullptr, "GetSeriesInfo"},
{11, nullptr, "CreateDeleteDataTask"},
{12, nullptr, "DeleteSeriesInfo"},
{13, nullptr, "CreateRegisterNotificationTokenTask"},
{14, nullptr, "UpdateSeriesInfo"},
{15, nullptr, "RegisterUploadSaveDataTransferTaskForAutonomyRegistration"},
{16, nullptr, "CreateCleanupToDeleteSaveDataArchiveInfoTask"},
{17, nullptr, "ListDataInfo"},
{18, nullptr, "GetDataInfo"},
{19, nullptr, "Unknown19"},
{20, nullptr, "CreateSaveDataArchiveInfoCacheForSaveDataBackupUpdationTask"},
{21, nullptr, "ListSecondarySaves"},
{22, D<&IRemoteStorageController::GetSecondarySave>, "GetSecondarySave"},
{23, nullptr, "TouchSecondarySave"},
{24, nullptr, "GetSecondarySaveDataInfo"},
{25, nullptr, "RegisterDownloadSaveDataTransferTaskForAutonomyRegistration"},
{900, nullptr, "Unknown900"},
};
// clang-format on
RegisterHandlers(functions);
}
IRemoteStorageController::~IRemoteStorageController() = default;
Result IRemoteStorageController::GetSecondarySave(Out<bool> out_has_secondary_save,
Out<std::array<u64, 3>> out_unknown,
u64 application_id) {
LOG_ERROR(Service_OLSC, "(STUBBED) called, application_id={:016X}", application_id);
*out_has_secondary_save = false;
*out_unknown = {};
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
class IRemoteStorageController final : public ServiceFramework<IRemoteStorageController> {
public:
explicit IRemoteStorageController(Core::System& system_);
~IRemoteStorageController() override;
private:
Result GetSecondarySave(Out<bool> out_has_secondary_save, Out<std::array<u64, 3>> out_unknown,
u64 application_id);
};
} // namespace Service::OLSC

View file

@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/olsc/native_handle_holder.h"
#include "core/hle/service/olsc/transfer_task_list_controller.h"
namespace Service::OLSC {
ITransferTaskListController::ITransferTaskListController(Core::System& system_)
: ServiceFramework{system_, "ITransferTaskListController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "GetRemoteStorageController"},
{9, D<&ITransferTaskListController::GetNativeHandleHolder>, "GetNativeHandleHolder2"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
{25, nullptr, "Unknown25"},
};
// clang-format on
RegisterHandlers(functions);
}
ITransferTaskListController::~ITransferTaskListController() = default;
Result ITransferTaskListController::GetNativeHandleHolder(
Out<SharedPointer<INativeHandleHolder>> out_holder) {
LOG_WARNING(Service_OLSC, "(STUBBED) called");
*out_holder = std::make_shared<INativeHandleHolder>(system);
R_SUCCEED();
}
} // namespace Service::OLSC

View file

@ -0,0 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_types.h"
#include "core/hle/service/service.h"
namespace Service::OLSC {
class INativeHandleHolder;
class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
public:
explicit ITransferTaskListController(Core::System& system_);
~ITransferTaskListController() override;
private:
Result GetNativeHandleHolder(Out<SharedPointer<INativeHandleHolder>> out_holder);
};
} // namespace Service::OLSC

View file

@ -0,0 +1,434 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/pctl/parental_control_service.h"
#include "core/hle/service/pctl/pctl_results.h"
namespace Service::PCTL {
IParentalControlService::IParentalControlService(Core::System& system_, Capability capability_)
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_},
service_context{system_, "IParentalControlService"}, synchronization_event{service_context},
unlinked_event{service_context}, request_suspension_event{service_context} {
// clang-format off
static const FunctionInfo functions[] = {
{1, D<&IParentalControlService::Initialize>, "Initialize"},
{1001, D<&IParentalControlService::CheckFreeCommunicationPermission>, "CheckFreeCommunicationPermission"},
{1002, D<&IParentalControlService::ConfirmLaunchApplicationPermission>, "ConfirmLaunchApplicationPermission"},
{1003, D<&IParentalControlService::ConfirmResumeApplicationPermission>, "ConfirmResumeApplicationPermission"},
{1004, D<&IParentalControlService::ConfirmSnsPostPermission>, "ConfirmSnsPostPermission"},
{1005, nullptr, "ConfirmSystemSettingsPermission"},
{1006, D<&IParentalControlService::IsRestrictionTemporaryUnlocked>, "IsRestrictionTemporaryUnlocked"},
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
{1008, nullptr, "EnterRestrictedSystemSettings"},
{1009, nullptr, "LeaveRestrictedSystemSettings"},
{1010, D<&IParentalControlService::IsRestrictedSystemSettingsEntered>, "IsRestrictedSystemSettingsEntered"},
{1011, nullptr, "RevertRestrictedSystemSettingsEntered"},
{1012, nullptr, "GetRestrictedFeatures"},
{1013, D<&IParentalControlService::ConfirmStereoVisionPermission>, "ConfirmStereoVisionPermission"},
{1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
{1015, nullptr, "ConfirmPlayableApplicationVideo"},
{1016, nullptr, "ConfirmShowNewsPermission"},
{1017, D<&IParentalControlService::EndFreeCommunication>, "EndFreeCommunication"},
{1018, D<&IParentalControlService::IsFreeCommunicationAvailable>, "IsFreeCommunicationAvailable"},
{1031, D<&IParentalControlService::IsRestrictionEnabled>, "IsRestrictionEnabled"},
{1032, D<&IParentalControlService::GetSafetyLevel>, "GetSafetyLevel"},
{1033, nullptr, "SetSafetyLevel"},
{1034, nullptr, "GetSafetyLevelSettings"},
{1035, D<&IParentalControlService::GetCurrentSettings>, "GetCurrentSettings"},
{1036, nullptr, "SetCustomSafetyLevelSettings"},
{1037, nullptr, "GetDefaultRatingOrganization"},
{1038, nullptr, "SetDefaultRatingOrganization"},
{1039, D<&IParentalControlService::GetFreeCommunicationApplicationListCount>, "GetFreeCommunicationApplicationListCount"},
{1042, nullptr, "AddToFreeCommunicationApplicationList"},
{1043, nullptr, "DeleteSettings"},
{1044, nullptr, "GetFreeCommunicationApplicationList"},
{1045, nullptr, "UpdateFreeCommunicationApplicationList"},
{1046, nullptr, "DisableFeaturesForReset"},
{1047, nullptr, "NotifyApplicationDownloadStarted"},
{1048, nullptr, "NotifyNetworkProfileCreated"},
{1049, nullptr, "ResetFreeCommunicationApplicationList"},
{1061, D<&IParentalControlService::ConfirmStereoVisionRestrictionConfigurable>, "ConfirmStereoVisionRestrictionConfigurable"},
{1062, D<&IParentalControlService::GetStereoVisionRestriction>, "GetStereoVisionRestriction"},
{1063, D<&IParentalControlService::SetStereoVisionRestriction>, "SetStereoVisionRestriction"},
{1064, D<&IParentalControlService::ResetConfirmedStereoVisionPermission>, "ResetConfirmedStereoVisionPermission"},
{1065, D<&IParentalControlService::IsStereoVisionPermitted>, "IsStereoVisionPermitted"},
{1201, nullptr, "UnlockRestrictionTemporarily"},
{1202, nullptr, "UnlockSystemSettingsRestriction"},
{1203, nullptr, "SetPinCode"},
{1204, nullptr, "GenerateInquiryCode"},
{1205, nullptr, "CheckMasterKey"},
{1206, D<&IParentalControlService::GetPinCodeLength>, "GetPinCodeLength"},
{1207, nullptr, "GetPinCodeChangedEvent"},
{1208, nullptr, "GetPinCode"},
{1403, D<&IParentalControlService::IsPairingActive>, "IsPairingActive"},
{1406, nullptr, "GetSettingsLastUpdated"},
{1411, nullptr, "GetPairingAccountInfo"},
{1421, nullptr, "GetAccountNickname"},
{1424, nullptr, "GetAccountState"},
{1425, nullptr, "RequestPostEvents"},
{1426, nullptr, "GetPostEventInterval"},
{1427, nullptr, "SetPostEventInterval"},
{1432, D<&IParentalControlService::GetSynchronizationEvent>, "GetSynchronizationEvent"},
{1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
{1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
{1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"},
{1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
{1456, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"},
{1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
{1458, D<&IParentalControlService::IsPlayTimerAlarmDisabled>, "IsPlayTimerAlarmDisabled"},
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
{1472, nullptr, "CancelNetworkRequest"},
{1473, D<&IParentalControlService::GetUnlinkedEvent>, "GetUnlinkedEvent"},
{1474, nullptr, "ClearUnlinkedEvent"},
{1601, nullptr, "DisableAllFeatures"},
{1602, nullptr, "PostEnableAllFeatures"},
{1603, nullptr, "IsAllFeaturesDisabled"},
{1901, nullptr, "DeleteFromFreeCommunicationApplicationListForDebug"},
{1902, nullptr, "ClearFreeCommunicationApplicationListForDebug"},
{1903, nullptr, "GetExemptApplicationListCountForDebug"},
{1904, nullptr, "GetExemptApplicationListForDebug"},
{1905, nullptr, "UpdateExemptApplicationListForDebug"},
{1906, nullptr, "AddToExemptApplicationListForDebug"},
{1907, nullptr, "DeleteFromExemptApplicationListForDebug"},
{1908, nullptr, "ClearExemptApplicationListForDebug"},
{1941, nullptr, "DeletePairing"},
{1951, nullptr, "SetPlayTimerSettingsForDebug"},
{1952, nullptr, "GetPlayTimerSpentTimeForTest"},
{1953, nullptr, "SetPlayTimerAlarmDisabledForDebug"},
{2001, nullptr, "RequestPairingAsync"},
{2002, nullptr, "FinishRequestPairing"},
{2003, nullptr, "AuthorizePairingAsync"},
{2004, nullptr, "FinishAuthorizePairing"},
{2005, nullptr, "RetrievePairingInfoAsync"},
{2006, nullptr, "FinishRetrievePairingInfo"},
{2007, nullptr, "UnlinkPairingAsync"},
{2008, nullptr, "FinishUnlinkPairing"},
{2009, nullptr, "GetAccountMiiImageAsync"},
{2010, nullptr, "FinishGetAccountMiiImage"},
{2011, nullptr, "GetAccountMiiImageContentTypeAsync"},
{2012, nullptr, "FinishGetAccountMiiImageContentType"},
{2013, nullptr, "SynchronizeParentalControlSettingsAsync"},
{2014, nullptr, "FinishSynchronizeParentalControlSettings"},
{2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
{2016, nullptr, "RequestUpdateExemptionListAsync"},
};
// clang-format on
RegisterHandlers(functions);
}
IParentalControlService::~IParentalControlService() = default;
bool IParentalControlService::CheckFreeCommunicationPermissionImpl() const {
if (states.temporary_unlocked) {
return true;
}
if ((states.application_info.parental_control_flag & 1) == 0) {
return true;
}
if (pin_code[0] == '\0') {
return true;
}
if (!settings.is_free_communication_default_on) {
return true;
}
// TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here
// but as we don't have multiproceses support yet, we can just assume our application is
// valid for the time being
return true;
}
bool IParentalControlService::ConfirmStereoVisionPermissionImpl() const {
if (states.temporary_unlocked) {
return true;
}
if (pin_code[0] == '\0') {
return true;
}
if (!settings.is_stero_vision_restricted) {
return false;
}
return true;
}
void IParentalControlService::SetStereoVisionRestrictionImpl(bool is_restricted) {
if (settings.disabled) {
return;
}
if (pin_code[0] == '\0') {
return;
}
settings.is_stero_vision_restricted = is_restricted;
}
Result IParentalControlService::Initialize() {
LOG_DEBUG(Service_PCTL, "called");
if (False(capability & (Capability::Application | Capability::System))) {
LOG_ERROR(Service_PCTL, "Invalid capability! capability={:X}", capability);
R_THROW(PCTL::ResultNoCapability);
}
// TODO(ogniK): Recovery flag initialization for pctl:r
const auto program_id = system.GetApplicationProcessProgramID();
if (program_id != 0) {
const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
system.GetContentProvider()};
const auto control = pm.GetControlMetadata();
if (control.first) {
states.tid_from_event = 0;
states.launch_time_valid = false;
states.is_suspended = false;
states.free_communication = false;
states.stereo_vision = false;
states.application_info = ApplicationInfo{
.application_id = program_id,
.age_rating = control.first->GetRatingAge(),
.parental_control_flag = control.first->GetParentalControlFlag(),
.capability = capability,
};
if (False(capability & (Capability::System | Capability::Recovery))) {
// TODO(ogniK): Signal application launch event
}
}
}
R_SUCCEED();
}
Result IParentalControlService::CheckFreeCommunicationPermission() {
LOG_DEBUG(Service_PCTL, "called");
if (!CheckFreeCommunicationPermissionImpl()) {
R_THROW(PCTL::ResultNoFreeCommunication);
} else {
states.free_communication = true;
R_SUCCEED();
}
}
Result IParentalControlService::ConfirmLaunchApplicationPermission(
InBuffer<BufferAttr_HipcPointer> restriction_bitset, u64 nacp_flag, u64 application_id) {
LOG_WARNING(Service_PCTL, "(STUBBED) called, nacp_flag={:#x} application_id={:016X}", nacp_flag,
application_id);
R_SUCCEED();
}
Result IParentalControlService::ConfirmResumeApplicationPermission(
InBuffer<BufferAttr_HipcPointer> restriction_bitset, u64 nacp_flag, u64 application_id) {
LOG_WARNING(Service_PCTL, "(STUBBED) called, nacp_flag={:#x} application_id={:016X}", nacp_flag,
application_id);
R_SUCCEED();
}
Result IParentalControlService::ConfirmSnsPostPermission() {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
R_THROW(PCTL::ResultNoFreeCommunication);
}
Result IParentalControlService::IsRestrictionTemporaryUnlocked(
Out<bool> out_is_temporary_unlocked) {
*out_is_temporary_unlocked = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
*out_is_temporary_unlocked);
R_SUCCEED();
}
Result IParentalControlService::IsRestrictedSystemSettingsEntered(
Out<bool> out_is_restricted_system_settings_entered) {
*out_is_restricted_system_settings_entered = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
*out_is_restricted_system_settings_entered);
R_SUCCEED();
}
Result IParentalControlService::ConfirmStereoVisionPermission() {
LOG_DEBUG(Service_PCTL, "called");
states.stereo_vision = true;
R_SUCCEED();
}
Result IParentalControlService::EndFreeCommunication() {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
R_SUCCEED();
}
Result IParentalControlService::IsFreeCommunicationAvailable() {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
if (!CheckFreeCommunicationPermissionImpl()) {
R_THROW(PCTL::ResultNoFreeCommunication);
} else {
R_SUCCEED();
}
}
Result IParentalControlService::IsRestrictionEnabled(Out<bool> out_restriction_enabled) {
LOG_DEBUG(Service_PCTL, "called");
if (False(capability & (Capability::Status | Capability::Recovery))) {
LOG_ERROR(Service_PCTL, "Application does not have Status or Recovery capabilities!");
*out_restriction_enabled = false;
R_THROW(PCTL::ResultNoCapability);
}
*out_restriction_enabled = pin_code[0] != '\0';
R_SUCCEED();
}
Result IParentalControlService::GetSafetyLevel(Out<u32> out_safety_level) {
*out_safety_level = 0;
LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", *out_safety_level);
R_SUCCEED();
}
Result IParentalControlService::GetCurrentSettings(Out<RestrictionSettings> out_settings) {
LOG_INFO(Service_PCTL, "called");
*out_settings = restriction_settings;
R_SUCCEED();
}
Result IParentalControlService::GetFreeCommunicationApplicationListCount(Out<s32> out_count) {
*out_count = 4;
LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", *out_count);
R_SUCCEED();
}
Result IParentalControlService::ConfirmStereoVisionRestrictionConfigurable() {
LOG_DEBUG(Service_PCTL, "called");
if (False(capability & Capability::StereoVision)) {
LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
R_THROW(PCTL::ResultNoCapability);
}
if (pin_code[0] == '\0') {
R_THROW(PCTL::ResultNoRestrictionEnabled);
}
R_SUCCEED();
}
Result IParentalControlService::IsStereoVisionPermitted(Out<bool> out_is_permitted) {
LOG_DEBUG(Service_PCTL, "called");
if (!ConfirmStereoVisionPermissionImpl()) {
*out_is_permitted = false;
R_THROW(PCTL::ResultStereoVisionRestricted);
} else {
*out_is_permitted = true;
R_SUCCEED();
}
}
Result IParentalControlService::GetPinCodeLength(Out<s32> out_length) {
*out_length = 0;
LOG_WARNING(Service_PCTL, "(STUBBED) called, length={}", *out_length);
R_SUCCEED();
}
Result IParentalControlService::IsPairingActive(Out<bool> out_is_pairing_active) {
*out_is_pairing_active = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", *out_is_pairing_active);
R_SUCCEED();
}
Result IParentalControlService::GetSynchronizationEvent(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called");
*out_event = synchronization_event.GetHandle();
R_SUCCEED();
}
Result IParentalControlService::StartPlayTimer() {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
R_SUCCEED();
}
Result IParentalControlService::StopPlayTimer() {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
R_SUCCEED();
}
Result IParentalControlService::IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled) {
*out_is_play_timer_enabled = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, enabled={}", *out_is_play_timer_enabled);
R_SUCCEED();
}
Result IParentalControlService::IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer) {
*out_is_restricted_by_play_timer = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, restricted={}", *out_is_restricted_by_play_timer);
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerSettings(
Out<PlayTimerSettings> out_play_timer_settings) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
*out_play_timer_settings = {};
R_SUCCEED();
}
Result IParentalControlService::GetPlayTimerEventToRequestSuspension(
OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called");
*out_event = request_suspension_event.GetHandle();
R_SUCCEED();
}
Result IParentalControlService::IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled) {
*out_play_timer_alarm_disabled = false;
LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}",
*out_play_timer_alarm_disabled);
R_SUCCEED();
}
Result IParentalControlService::GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
LOG_INFO(Service_PCTL, "called");
*out_event = unlinked_event.GetHandle();
R_SUCCEED();
}
Result IParentalControlService::GetStereoVisionRestriction(
Out<bool> out_stereo_vision_restriction) {
LOG_DEBUG(Service_PCTL, "called");
if (False(capability & Capability::StereoVision)) {
LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
*out_stereo_vision_restriction = false;
R_THROW(PCTL::ResultNoCapability);
}
*out_stereo_vision_restriction = settings.is_stero_vision_restricted;
R_SUCCEED();
}
Result IParentalControlService::SetStereoVisionRestriction(bool stereo_vision_restriction) {
LOG_DEBUG(Service_PCTL, "called, can_use={}", stereo_vision_restriction);
if (False(capability & Capability::StereoVision)) {
LOG_ERROR(Service_PCTL, "Application does not have StereoVision capability!");
R_THROW(PCTL::ResultNoCapability);
}
SetStereoVisionRestrictionImpl(stereo_vision_restriction);
R_SUCCEED();
}
Result IParentalControlService::ResetConfirmedStereoVisionPermission() {
LOG_DEBUG(Service_PCTL, "called");
states.stereo_vision = false;
R_SUCCEED();
}
} // namespace Service::PCTL

View file

@ -0,0 +1,86 @@
// 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/kernel_helpers.h"
#include "core/hle/service/os/event.h"
#include "core/hle/service/pctl/pctl_types.h"
#include "core/hle/service/service.h"
namespace Service::PCTL {
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
public:
explicit IParentalControlService(Core::System& system_, Capability capability_);
~IParentalControlService() override;
private:
bool CheckFreeCommunicationPermissionImpl() const;
bool ConfirmStereoVisionPermissionImpl() const;
void SetStereoVisionRestrictionImpl(bool is_restricted);
Result Initialize();
Result CheckFreeCommunicationPermission();
Result ConfirmLaunchApplicationPermission(InBuffer<BufferAttr_HipcPointer> restriction_bitset,
u64 nacp_flag, u64 application_id);
Result ConfirmResumeApplicationPermission(InBuffer<BufferAttr_HipcPointer> restriction_bitset,
u64 nacp_flag, u64 application_id);
Result ConfirmSnsPostPermission();
Result IsRestrictionTemporaryUnlocked(Out<bool> out_is_temporary_unlocked);
Result IsRestrictedSystemSettingsEntered(Out<bool> out_is_restricted_system_settings_entered);
Result ConfirmStereoVisionPermission();
Result EndFreeCommunication();
Result IsFreeCommunicationAvailable();
Result IsRestrictionEnabled(Out<bool> out_restriction_enabled);
Result GetSafetyLevel(Out<u32> out_safety_level);
Result GetCurrentSettings(Out<RestrictionSettings> out_settings);
Result GetFreeCommunicationApplicationListCount(Out<s32> out_count);
Result ConfirmStereoVisionRestrictionConfigurable();
Result IsStereoVisionPermitted(Out<bool> out_is_permitted);
Result GetPinCodeLength(Out<s32> out_length);
Result IsPairingActive(Out<bool> out_is_pairing_active);
Result GetSynchronizationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result StartPlayTimer();
Result StopPlayTimer();
Result IsPlayTimerEnabled(Out<bool> out_is_play_timer_enabled);
Result IsRestrictedByPlayTimer(Out<bool> out_is_restricted_by_play_timer);
Result GetPlayTimerSettings(Out<PlayTimerSettings> out_play_timer_settings);
Result GetPlayTimerEventToRequestSuspension(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result IsPlayTimerAlarmDisabled(Out<bool> out_play_timer_alarm_disabled);
Result GetUnlinkedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
Result SetStereoVisionRestriction(bool stereo_vision_restriction);
Result ResetConfirmedStereoVisionPermission();
struct States {
u64 current_tid{};
ApplicationInfo application_info{};
u64 tid_from_event{};
bool launch_time_valid{};
bool is_suspended{};
bool temporary_unlocked{};
bool free_communication{};
bool stereo_vision{};
};
struct ParentalControlSettings {
bool is_stero_vision_restricted{};
bool is_free_communication_default_on{};
bool disabled{};
};
States states{};
ParentalControlSettings settings{};
RestrictionSettings restriction_settings{};
std::array<char, 8> pin_code{};
Capability capability{};
KernelHelpers::ServiceContext service_context;
Event synchronization_event;
Event unlinked_event;
Event request_suspension_event;
};
} // namespace Service::PCTL

View file

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/pctl/parental_control_service.h"
#include "core/hle/service/pctl/parental_control_service_factory.h"
namespace Service::PCTL {
IParentalControlServiceFactory::IParentalControlServiceFactory(Core::System& system_,
const char* name_,
Capability capability_)
: ServiceFramework{system_, name_}, capability{capability_} {
static const FunctionInfo functions[] = {
{0, D<&IParentalControlServiceFactory::CreateService>, "CreateService"},
{1, D<&IParentalControlServiceFactory::CreateServiceWithoutInitialize>,
"CreateServiceWithoutInitialize"},
};
RegisterHandlers(functions);
}
IParentalControlServiceFactory::~IParentalControlServiceFactory() = default;
Result IParentalControlServiceFactory::CreateService(
Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
LOG_DEBUG(Service_PCTL, "called");
// TODO(ogniK): Get application id from process
*out_service = std::make_shared<IParentalControlService>(system, capability);
R_SUCCEED();
}
Result IParentalControlServiceFactory::CreateServiceWithoutInitialize(
Out<SharedPointer<IParentalControlService>> out_service, ClientProcessId process_id) {
LOG_DEBUG(Service_PCTL, "called");
// TODO(ogniK): Get application id from process
*out_service = std::make_shared<IParentalControlService>(system, capability);
R_SUCCEED();
}
} // namespace Service::PCTL

View file

@ -0,0 +1,31 @@
// 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/pctl/pctl_types.h"
#include "core/hle/service/service.h"
namespace Service::PCTL {
class IParentalControlService;
class IParentalControlServiceFactory : public ServiceFramework<IParentalControlServiceFactory> {
public:
explicit IParentalControlServiceFactory(Core::System& system_, const char* name_,
Capability capability_);
~IParentalControlServiceFactory() override;
Result CreateService(Out<SharedPointer<IParentalControlService>> out_service,
ClientProcessId process_id);
Result CreateServiceWithoutInitialize(Out<SharedPointer<IParentalControlService>> out_service,
ClientProcessId process_id);
private:
Capability capability{};
};
void LoopProcess(Core::System& system);
} // namespace Service::PCTL

View file

@ -1,19 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/pctl/parental_control_service_factory.h"
#include "core/hle/service/pctl/pctl.h" #include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/server_manager.h"
namespace Service::PCTL { namespace Service::PCTL {
PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, void LoopProcess(Core::System& system) {
Capability capability_) auto server_manager = std::make_unique<ServerManager>(system);
: Interface{system_, std::move(module_), name, capability_} {
static const FunctionInfo functions[] = { server_manager->RegisterNamedService("pctl",
{0, &PCTL::CreateService, "CreateService"}, std::make_shared<IParentalControlServiceFactory>(
{1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, system, "pctl",
}; Capability::Application | Capability::SnsPost |
RegisterHandlers(functions); Capability::Status | Capability::StereoVision));
// TODO(ogniK): Implement remaining capabilities
server_manager->RegisterNamedService("pctl:a", std::make_shared<IParentalControlServiceFactory>(
system, "pctl:a", Capability::None));
server_manager->RegisterNamedService("pctl:r", std::make_shared<IParentalControlServiceFactory>(
system, "pctl:r", Capability::None));
server_manager->RegisterNamedService("pctl:s", std::make_shared<IParentalControlServiceFactory>(
system, "pctl:s", Capability::None));
ServerManager::RunServer(std::move(server_manager));
} }
PCTL::~PCTL() = default;
} // namespace Service::PCTL } // namespace Service::PCTL

View file

@ -3,19 +3,12 @@
#pragma once #pragma once
#include "core/hle/service/pctl/pctl_module.h"
namespace Core { namespace Core {
class System; class System;
} }
namespace Service::PCTL { namespace Service::PCTL {
class PCTL final : public Module::Interface { void LoopProcess(Core::System& system);
public:
explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name,
Capability capability_);
~PCTL() override;
};
} // namespace Service::PCTL } // namespace Service::PCTL

View file

@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/hle/result.h"
namespace Service::PCTL {
constexpr Result ResultNoFreeCommunication{ErrorModule::PCTL, 101};
constexpr Result ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
constexpr Result ResultNoCapability{ErrorModule::PCTL, 131};
constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
} // namespace Service::PCTL

View file

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_funcs.h"
namespace Service::PCTL {
enum class Capability : u32 {
None = 0,
Application = 1 << 0,
SnsPost = 1 << 1,
Recovery = 1 << 6,
Status = 1 << 8,
StereoVision = 1 << 9,
System = 1 << 15,
};
DECLARE_ENUM_FLAG_OPERATORS(Capability);
struct ApplicationInfo {
u64 application_id{};
std::array<u8, 32> age_rating{};
u32 parental_control_flag{};
Capability capability{};
};
static_assert(sizeof(ApplicationInfo) == 0x30, "ApplicationInfo has incorrect size.");
// This is nn::pctl::RestrictionSettings
struct RestrictionSettings {
u8 rating_age;
bool sns_post_restriction;
bool free_communication_restriction;
};
static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
// This is nn::pctl::PlayTimerSettings
struct PlayTimerSettings {
std::array<u32, 13> settings;
};
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
} // namespace Service::PCTL

View file

@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/bit_field.h"
#include "common/common_types.h"
namespace Service::PSC {
using OverlayNotification = std::array<u64, 0x10>;
static_assert(sizeof(OverlayNotification) == 0x80, "OverlayNotification has incorrect size");
union MessageFlags {
u64 raw;
BitField<0, 8, u64> message_type;
BitField<8, 8, u64> queue_type;
};
static_assert(sizeof(MessageFlags) == 0x8, "MessageFlags has incorrect size");
} // namespace Service::PSC

View file

@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/psc/ovln/receiver.h"
namespace Service::PSC {
IReceiver::IReceiver(Core::System& system_) : ServiceFramework{system_, "IReceiver"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "AddSource"},
{1, nullptr, "RemoveSource"},
{2, nullptr, "GetReceiveEventHandle"},
{3, nullptr, "Receive"},
{4, nullptr, "ReceiveWithTick"},
};
// clang-format on
RegisterHandlers(functions);
}
IReceiver::~IReceiver() = default;
} // namespace Service::PSC

View file

@ -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::PSC {
class IReceiver final : public ServiceFramework<IReceiver> {
public:
explicit IReceiver(Core::System& system_);
~IReceiver() override;
};
} // namespace Service::PSC

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/ovln/receiver.h"
#include "core/hle/service/psc/ovln/receiver_service.h"
namespace Service::PSC {
IReceiverService::IReceiverService(Core::System& system_) : ServiceFramework{system_, "ovln:rcv"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IReceiverService::OpenReceiver>, "OpenReceiver"},
};
// clang-format on
RegisterHandlers(functions);
}
IReceiverService::~IReceiverService() = default;
Result IReceiverService::OpenReceiver(Out<SharedPointer<IReceiver>> out_receiver) {
LOG_DEBUG(Service_PSC, "called");
*out_receiver = std::make_shared<IReceiver>(system);
R_SUCCEED();
}
} // namespace Service::PSC

View file

@ -0,0 +1,22 @@
// 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::PSC {
class IReceiver;
class IReceiverService final : public ServiceFramework<IReceiverService> {
public:
explicit IReceiverService(Core::System& system_);
~IReceiverService() override;
private:
Result OpenReceiver(Out<SharedPointer<IReceiver>> out_receiver);
};
} // namespace Service::PSC

View file

@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/ovln/sender.h"
namespace Service::PSC {
ISender::ISender(Core::System& system_) : ServiceFramework{system_, "ISender"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISender::Send>, "Send"},
{1, nullptr, "GetUnreceivedMessageCount"},
};
// clang-format on
RegisterHandlers(functions);
}
ISender::~ISender() = default;
Result ISender::Send(const OverlayNotification& notification, MessageFlags flags) {
std::string data;
for (const auto m : notification) {
data += fmt::format("{:016X} ", m);
}
LOG_WARNING(Service_PSC, "(STUBBED) called, flags={} notification={}", flags.raw, data);
R_SUCCEED();
}
} // namespace Service::PSC

View file

@ -0,0 +1,21 @@
// 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/psc/ovln/ovln_types.h"
#include "core/hle/service/service.h"
namespace Service::PSC {
class ISender final : public ServiceFramework<ISender> {
public:
explicit ISender(Core::System& system_);
~ISender() override;
private:
Result Send(const OverlayNotification& notification, MessageFlags flags);
};
} // namespace Service::PSC

View file

@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/cmif_serialization.h"
#include "core/hle/service/psc/ovln/sender.h"
#include "core/hle/service/psc/ovln/sender_service.h"
namespace Service::PSC {
ISenderService::ISenderService(Core::System& system_) : ServiceFramework{system_, "ovln:snd"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&ISenderService::OpenSender>, "OpenSender"},
};
// clang-format on
RegisterHandlers(functions);
}
ISenderService::~ISenderService() = default;
Result ISenderService::OpenSender(Out<SharedPointer<ISender>> out_sender, u32 sender_id,
std::array<u64, 2> data) {
LOG_WARNING(Service_PSC, "(STUBBED) called, sender_id={}, data={:016X} {:016X}", sender_id,
data[0], data[1]);
*out_sender = std::make_shared<ISender>(system);
R_SUCCEED();
}
} // namespace Service::PSC

View file

@ -0,0 +1,23 @@
// 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::PSC {
class ISender;
class ISenderService final : public ServiceFramework<ISenderService> {
public:
explicit ISenderService(Core::System& system_);
~ISenderService() override;
private:
Result OpenSender(Out<SharedPointer<ISender>> out_sender, u32 sender_id,
std::array<u64, 2> data);
};
} // namespace Service::PSC

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/psc/pm_control.h"
namespace Service::PSC {
IPmControl::IPmControl(Core::System& system_) : ServiceFramework{system_, "psc:c"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Initialize"},
{1, nullptr, "DispatchRequest"},
{2, nullptr, "GetResult"},
{3, nullptr, "GetState"},
{4, nullptr, "Cancel"},
{5, nullptr, "PrintModuleInformation"},
{6, nullptr, "GetModuleInformation"},
{10, nullptr, "AcquireStateLock"},
{11, nullptr, "HasStateLock"},
};
// clang-format on
RegisterHandlers(functions);
}
IPmControl::~IPmControl() = default;
} // namespace Service::PSC

View file

@ -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::PSC {
class IPmControl final : public ServiceFramework<IPmControl> {
public:
explicit IPmControl(Core::System& system_);
~IPmControl() override;
};
} // namespace Service::PSC

View file

@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/psc/pm_module.h"
namespace Service::PSC {
IPmModule::IPmModule(Core::System& system_) : ServiceFramework{system_, "IPmModule"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Initialize"},
{1, nullptr, "GetRequest"},
{2, nullptr, "Acknowledge"},
{3, nullptr, "Finalize"},
{4, nullptr, "AcknowledgeEx"},
};
// clang-format on
RegisterHandlers(functions);
}
IPmModule::~IPmModule() = default;
} // namespace Service::PSC

View file

@ -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::PSC {
class IPmModule final : public ServiceFramework<IPmModule> {
public:
explicit IPmModule(Core::System& system_);
~IPmModule() override;
};
} // namespace Service::PSC

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