diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/service/audio/hwopus.cpp | 49 | ||||
-rw-r--r-- | src/core/hle/service/audio/hwopus.h | 5 | ||||
-rw-r--r-- | src/core/hle/service/sockets/nsd.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/service/sockets/sfdnsres.cpp | 12 |
4 files changed, 72 insertions, 5 deletions
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index fa77007f3..4a8276ed1 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -174,7 +174,7 @@ public: {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, - {9, nullptr, "DecodeInterleavedForMultiStream"}, + {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"}, }; // clang-format on @@ -206,6 +206,16 @@ private: decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); } + void DecodeInterleavedForMultiStream(HLERequestContext& ctx) { + LOG_DEBUG(Audio, "called"); + + IPC::RequestParser rp{ctx}; + const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext + : OpusDecoderState::ExtraBehavior::None; + + decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); + } + OpusDecoderState decoder_state; }; @@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) { system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); } +void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) { + OpusMultiStreamParametersEx params; + std::memcpy(¶ms, ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); + + const auto& sample_rate = params.sample_rate; + const auto& channel_count = params.channel_count; + + LOG_INFO( + Audio, + "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}", + sample_rate, channel_count, params.number_streams, params.number_stereo_streams); + + ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 || + sample_rate == 12000 || sample_rate == 8000, + "Invalid sample rate"); + + int error = 0; + OpusDecoderPtr decoder{opus_multistream_decoder_create( + sample_rate, static_cast<int>(channel_count), params.number_streams, + params.number_stereo_streams, params.channel_mappings.data(), &error)}; + if (error != OPUS_OK || decoder == nullptr) { + LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error); + IPC::ResponseBuilder rb{ctx, 2}; + // TODO(ogniK): Use correct error code + rb.Push(ResultUnknown); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IHardwareOpusDecoderManager>( + system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); +} + HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { static const FunctionInfo functions[] = { {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, @@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { {3, nullptr, "GetWorkBufferSizeForMultiStream"}, {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, - {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, + {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx, + "OpenHardwareOpusDecoderForMultiStreamEx"}, {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, {8, nullptr, "GetWorkBufferSizeExEx"}, {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h index ece65c02c..91d9998ac 100644 --- a/src/core/hle/service/audio/hwopus.h +++ b/src/core/hle/service/audio/hwopus.h @@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx { u32 number_stereo_streams; u32 use_large_frame_size; u32 padding; - std::array<u32, 64> channel_mappings; + std::array<u8, 0x100> channel_mappings; }; +static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118, + "OpusMultiStreamParametersEx has incorrect size"); class HwOpus final : public ServiceFramework<HwOpus> { public: @@ -29,6 +31,7 @@ public: private: void OpenHardwareOpusDecoder(HLERequestContext& ctx); void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); + void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx); void GetWorkBufferSize(HLERequestContext& ctx); void GetWorkBufferSizeEx(HLERequestContext& ctx); void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index bac21752a..491b76d48 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp @@ -19,6 +19,12 @@ enum class ServerEnvironmentType : u8 { Dp, }; +// This is nn::nsd::EnvironmentIdentifier +struct EnvironmentIdentifier { + std::array<u8, 8> identifier; +}; +static_assert(sizeof(EnvironmentIdentifier) == 0x8); + NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { @@ -101,8 +107,9 @@ void NSD::ResolveEx(HLERequestContext& ctx) { } void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) { - const std::string environment_identifier = "lp1"; - ctx.WriteBuffer(environment_identifier); + constexpr EnvironmentIdentifier lp1 = { + .identifier = {'l', 'p', '1', '\0', '\0', '\0', '\0', '\0'}}; + ctx.WriteBuffer(lp1); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 22e4a6f49..c657c4efd 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -150,6 +150,12 @@ static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestConte const std::string host = Common::StringFromBuffer(host_buffer); // For now, ignore options, which are in input buffer 1 for GetHostByNameRequestWithOptions. + // Prevent resolution of Nintendo servers + if (host.find("srv.nintendo.net") != std::string::npos) { + LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); + return {0, GetAddrInfoError::AGAIN}; + } + auto res = Network::GetAddressInfo(host, /*service*/ std::nullopt); if (!res.has_value()) { return {0, Translate(res.error())}; @@ -261,6 +267,12 @@ static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext const auto host_buffer = ctx.ReadBuffer(0); const std::string host = Common::StringFromBuffer(host_buffer); + // Prevent resolution of Nintendo servers + if (host.find("srv.nintendo.net") != std::string::npos) { + LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host); + return {0, GetAddrInfoError::AGAIN}; + } + std::optional<std::string> service = std::nullopt; if (ctx.CanReadBuffer(1)) { const std::span<const u8> service_buffer = ctx.ReadBuffer(1); |