early-access version 4160
This commit is contained in:
parent
cb22e3fb42
commit
89a3ee2eed
106 changed files with 4263 additions and 1073 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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*>(
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
175
src/core/file_sys/fs_save_data_types.h
Executable file
175
src/core/file_sys/fs_save_data_types.h
Executable 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
|
|
@ -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());
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
163
src/core/hle/service/audio/audio_device.cpp
Executable file
163
src/core/hle/service/audio/audio_device.cpp
Executable 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
|
58
src/core/hle/service/audio/audio_device.h
Executable file
58
src/core/hle/service/audio/audio_device.h
Executable 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
|
146
src/core/hle/service/audio/audio_in.cpp
Executable file
146
src/core/hle/service/audio/audio_in.cpp
Executable 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
|
53
src/core/hle/service/audio/audio_in.h
Executable file
53
src/core/hle/service/audio/audio_in.h
Executable 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
|
125
src/core/hle/service/audio/audio_in_manager.cpp
Executable file
125
src/core/hle/service/audio/audio_in_manager.cpp
Executable 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
|
57
src/core/hle/service/audio/audio_in_manager.h
Executable file
57
src/core/hle/service/audio/audio_in_manager.h
Executable 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
|
146
src/core/hle/service/audio/audio_out.cpp
Executable file
146
src/core/hle/service/audio/audio_out.cpp
Executable 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
|
58
src/core/hle/service/audio/audio_out.h
Executable file
58
src/core/hle/service/audio/audio_out.h
Executable 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
|
101
src/core/hle/service/audio/audio_out_manager.cpp
Executable file
101
src/core/hle/service/audio/audio_out_manager.cpp
Executable 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
|
44
src/core/hle/service/audio/audio_out_manager.h
Executable file
44
src/core/hle/service/audio/audio_out_manager.h
Executable 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
|
139
src/core/hle/service/audio/audio_renderer.cpp
Executable file
139
src/core/hle/service/audio/audio_renderer.cpp
Executable 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
|
54
src/core/hle/service/audio/audio_renderer.h
Executable file
54
src/core/hle/service/audio/audio_renderer.h
Executable 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
|
104
src/core/hle/service/audio/audio_renderer_manager.cpp
Executable file
104
src/core/hle/service/audio/audio_renderer_manager.cpp
Executable 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
|
37
src/core/hle/service/audio/audio_renderer_manager.h
Executable file
37
src/core/hle/service/audio/audio_renderer_manager.h
Executable 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
|
43
src/core/hle/service/audio/final_output_recorder_manager.cpp
Executable file
43
src/core/hle/service/audio/final_output_recorder_manager.cpp
Executable 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
|
20
src/core/hle/service/audio/final_output_recorder_manager.h
Executable file
20
src/core/hle/service/audio/final_output_recorder_manager.h
Executable 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
|
22
src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
Executable file
22
src/core/hle/service/audio/final_output_recorder_manager_for_applet.cpp
Executable 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
|
21
src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
Executable file
21
src/core/hle/service/audio/final_output_recorder_manager_for_applet.h
Executable 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
|
145
src/core/hle/service/audio/hardware_opus_decoder.cpp
Executable file
145
src/core/hle/service/audio/hardware_opus_decoder.cpp
Executable 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
|
63
src/core/hle/service/audio/hardware_opus_decoder.h
Executable file
63
src/core/hle/service/audio/hardware_opus_decoder.h
Executable 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
|
156
src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
Executable file
156
src/core/hle/service/audio/hardware_opus_decoder_manager.cpp
Executable 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
|
53
src/core/hle/service/audio/hardware_opus_decoder_manager.h
Executable file
53
src/core/hle/service/audio/hardware_opus_decoder_manager.h
Executable 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
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
33
src/core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
Executable file
33
src/core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.cpp
Executable 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
|
23
src/core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
Executable file
23
src/core/hle/service/filesystem/fsp/fs_i_multi_commit_manager.h
Executable 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
|
161
src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
Executable file
161
src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
Executable 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
|
50
src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
Executable file
50
src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
Executable 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
34
src/core/hle/service/filesystem/fsp/fsp_types.h
Executable file
34
src/core/hle/service/filesystem/fsp/fsp_types.h
Executable 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
|
40
src/core/hle/service/olsc/daemon_controller.cpp
Executable file
40
src/core/hle/service/olsc/daemon_controller.cpp
Executable 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
|
20
src/core/hle/service/olsc/daemon_controller.h
Executable file
20
src/core/hle/service/olsc/daemon_controller.h
Executable 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
|
28
src/core/hle/service/olsc/native_handle_holder.cpp
Executable file
28
src/core/hle/service/olsc/native_handle_holder.cpp
Executable 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
|
22
src/core/hle/service/olsc/native_handle_holder.h
Executable file
22
src/core/hle/service/olsc/native_handle_holder.h
Executable 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
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
63
src/core/hle/service/olsc/olsc_service_for_application.cpp
Executable file
63
src/core/hle/service/olsc/olsc_service_for_application.cpp
Executable 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
|
23
src/core/hle/service/olsc/olsc_service_for_application.h
Executable file
23
src/core/hle/service/olsc/olsc_service_for_application.h
Executable 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
|
117
src/core/hle/service/olsc/olsc_service_for_system_service.cpp
Executable file
117
src/core/hle/service/olsc/olsc_service_for_system_service.cpp
Executable 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
|
27
src/core/hle/service/olsc/olsc_service_for_system_service.h
Executable file
27
src/core/hle/service/olsc/olsc_service_for_system_service.h
Executable 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
|
54
src/core/hle/service/olsc/remote_storage_controller.cpp
Executable file
54
src/core/hle/service/olsc/remote_storage_controller.cpp
Executable 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
|
19
src/core/hle/service/olsc/remote_storage_controller.h
Executable file
19
src/core/hle/service/olsc/remote_storage_controller.h
Executable 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
|
55
src/core/hle/service/olsc/transfer_task_list_controller.cpp
Executable file
55
src/core/hle/service/olsc/transfer_task_list_controller.cpp
Executable 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
|
20
src/core/hle/service/olsc/transfer_task_list_controller.h
Executable file
20
src/core/hle/service/olsc/transfer_task_list_controller.h
Executable 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
|
434
src/core/hle/service/pctl/parental_control_service.cpp
Executable file
434
src/core/hle/service/pctl/parental_control_service.cpp
Executable 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
|
86
src/core/hle/service/pctl/parental_control_service.h
Executable file
86
src/core/hle/service/pctl/parental_control_service.h
Executable 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
|
40
src/core/hle/service/pctl/parental_control_service_factory.cpp
Executable file
40
src/core/hle/service/pctl/parental_control_service_factory.cpp
Executable 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
|
31
src/core/hle/service/pctl/parental_control_service_factory.h
Executable file
31
src/core/hle/service/pctl/parental_control_service_factory.h
Executable 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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
15
src/core/hle/service/pctl/pctl_results.h
Executable file
15
src/core/hle/service/pctl/pctl_results.h
Executable 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
|
43
src/core/hle/service/pctl/pctl_types.h
Executable file
43
src/core/hle/service/pctl/pctl_types.h
Executable 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
|
21
src/core/hle/service/psc/ovln/ovln_types.h
Executable file
21
src/core/hle/service/psc/ovln/ovln_types.h
Executable 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
|
24
src/core/hle/service/psc/ovln/receiver.cpp
Executable file
24
src/core/hle/service/psc/ovln/receiver.cpp
Executable 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
|
16
src/core/hle/service/psc/ovln/receiver.h
Executable file
16
src/core/hle/service/psc/ovln/receiver.h
Executable 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
|
28
src/core/hle/service/psc/ovln/receiver_service.cpp
Executable file
28
src/core/hle/service/psc/ovln/receiver_service.cpp
Executable 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
|
22
src/core/hle/service/psc/ovln/receiver_service.h
Executable file
22
src/core/hle/service/psc/ovln/receiver_service.h
Executable 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
|
32
src/core/hle/service/psc/ovln/sender.cpp
Executable file
32
src/core/hle/service/psc/ovln/sender.cpp
Executable 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
|
21
src/core/hle/service/psc/ovln/sender.h
Executable file
21
src/core/hle/service/psc/ovln/sender.h
Executable 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
|
30
src/core/hle/service/psc/ovln/sender_service.cpp
Executable file
30
src/core/hle/service/psc/ovln/sender_service.cpp
Executable 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
|
23
src/core/hle/service/psc/ovln/sender_service.h
Executable file
23
src/core/hle/service/psc/ovln/sender_service.h
Executable 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
|
28
src/core/hle/service/psc/pm_control.cpp
Executable file
28
src/core/hle/service/psc/pm_control.cpp
Executable 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
|
16
src/core/hle/service/psc/pm_control.h
Executable file
16
src/core/hle/service/psc/pm_control.h
Executable 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
|
24
src/core/hle/service/psc/pm_module.cpp
Executable file
24
src/core/hle/service/psc/pm_module.cpp
Executable 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
|
16
src/core/hle/service/psc/pm_module.h
Executable file
16
src/core/hle/service/psc/pm_module.h
Executable 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
Loading…
Reference in a new issue