diff options
345 files changed, 4231 insertions, 4190 deletions
diff --git a/.ci/templates/build-msvc.yml b/.ci/templates/build-msvc.yml index d85a949aa..0b4bbd341 100644 --- a/.ci/templates/build-msvc.yml +++ b/.ci/templates/build-msvc.yml @@ -4,9 +4,11 @@ parameters: version: '' steps: +- script: choco install vulkan-sdk + displayName: 'Install vulkan-sdk' - script: python -m pip install --upgrade pip conan displayName: 'Install conan' -- script: mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 --config Release -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cd .. +- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 --config Release -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DDISPLAY_VERSION=${{ parameters['version'] }} .. && cd .. displayName: 'Configure CMake' - task: MSBuild@1 displayName: 'Build' diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbda528ce..a22b564d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,6 +66,7 @@ else() -Wextra -Wmissing-declarations -Wno-attributes + -Wno-invalid-offsetof -Wno-unused-parameter ) diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 8619a3f03..fe3a898ad 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp @@ -43,6 +43,10 @@ std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, return stream->GetTagsAndReleaseBuffers(max_count); } +std::vector<Buffer::Tag> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream) { + return stream->GetTagsAndReleaseBuffers(); +} + void AudioOut::StartStream(StreamPtr stream) { stream->Play(); } diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h index b07588287..6ce08cd0d 100644 --- a/src/audio_core/audio_out.h +++ b/src/audio_core/audio_out.h @@ -31,6 +31,9 @@ public: /// Returns a vector of recently released buffers specified by tag for the specified stream std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream, std::size_t max_count); + /// Returns a vector of all recently released buffers specified by tag for the specified stream + std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(StreamPtr stream); + /// Starts an audio stream for playback void StartStream(StreamPtr stream); diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index a7e851bb8..5f532ed31 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <limits> #include <vector> #include "audio_core/audio_out.h" @@ -14,6 +15,59 @@ #include "core/memory.h" #include "core/settings.h" +namespace { +[[nodiscard]] static constexpr s16 ClampToS16(s32 value) { + return static_cast<s16>(std::clamp(value, s32{std::numeric_limits<s16>::min()}, + s32{std::numeric_limits<s16>::max()})); +} + +[[nodiscard]] static constexpr s16 Mix2To1(s16 l_channel, s16 r_channel) { + // Mix 50% from left and 50% from right channel + constexpr float l_mix_amount = 50.0f / 100.0f; + constexpr float r_mix_amount = 50.0f / 100.0f; + return ClampToS16(static_cast<s32>((static_cast<float>(l_channel) * l_mix_amount) + + (static_cast<float>(r_channel) * r_mix_amount))); +} + +[[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2(s16 fl_channel, s16 fr_channel, + s16 fc_channel, + [[maybe_unused]] s16 lf_channel, + s16 bl_channel, s16 br_channel) { + // Front channels are mixed 36.94%, Center channels are mixed to be 26.12% & the back channels + // are mixed to be 36.94% + + constexpr float front_mix_amount = 36.94f / 100.0f; + constexpr float center_mix_amount = 26.12f / 100.0f; + constexpr float back_mix_amount = 36.94f / 100.0f; + + // Mix 50% from left and 50% from right channel + const auto left = front_mix_amount * static_cast<float>(fl_channel) + + center_mix_amount * static_cast<float>(fc_channel) + + back_mix_amount * static_cast<float>(bl_channel); + + const auto right = front_mix_amount * static_cast<float>(fr_channel) + + center_mix_amount * static_cast<float>(fc_channel) + + back_mix_amount * static_cast<float>(br_channel); + + return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))}; +} + +[[nodiscard]] static constexpr std::tuple<s16, s16> Mix6To2WithCoefficients( + s16 fl_channel, s16 fr_channel, s16 fc_channel, s16 lf_channel, s16 bl_channel, s16 br_channel, + const std::array<float_le, 4>& coeff) { + const auto left = + static_cast<float>(fl_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] + + static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(bl_channel) * coeff[0]; + + const auto right = + static_cast<float>(fr_channel) * coeff[0] + static_cast<float>(fc_channel) * coeff[1] + + static_cast<float>(lf_channel) * coeff[2] + static_cast<float>(br_channel) * coeff[0]; + + return {ClampToS16(static_cast<s32>(left)), ClampToS16(static_cast<s32>(right))}; +} + +} // namespace + namespace AudioCore { AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, AudioCommon::AudioRendererParameter params, @@ -25,8 +79,7 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory sink_context(params.sink_count), splitter_context(), voices(params.voice_count), memory{memory_}, command_generator(worker_params, voice_context, mix_context, splitter_context, effect_context, - memory), - temp_mix_buffer(AudioCommon::TOTAL_TEMP_MIX_SIZE) { + memory) { behavior_info.SetUserRevision(params.revision); splitter_context.Initialize(behavior_info, params.splitter_count, params.num_splitter_send_channels); @@ -62,10 +115,6 @@ Stream::State AudioRenderer::GetStreamState() const { return stream->GetState(); } -static constexpr s16 ClampToS16(s32 value) { - return static_cast<s16>(std::clamp(value, -32768, 32767)); -} - ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, std::vector<u8>& output_params) { @@ -104,8 +153,8 @@ ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_param } } - auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count, - splitter_context, effect_context); + const auto mix_result = info_updater.UpdateMixes(mix_context, worker_params.mix_buffer_count, + splitter_context, effect_context); if (mix_result.IsError()) { LOG_ERROR(Audio, "Failed to update mix parameters"); @@ -194,20 +243,22 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { for (std::size_t i = 0; i < BUFFER_SIZE; i++) { if (channel_count == 1) { const auto sample = ClampToS16(mix_buffers[0][i]); - buffer[i * stream_channel_count + 0] = sample; - if (stream_channel_count > 1) { - buffer[i * stream_channel_count + 1] = sample; + + // Place sample in all channels + for (u32 channel = 0; channel < stream_channel_count; channel++) { + buffer[i * stream_channel_count + channel] = sample; } + if (stream_channel_count == 6) { - buffer[i * stream_channel_count + 2] = sample; - buffer[i * stream_channel_count + 4] = sample; - buffer[i * stream_channel_count + 5] = sample; + // Output stream has a LF channel, mute it! + buffer[i * stream_channel_count + 3] = 0; } + } else if (channel_count == 2) { const auto l_sample = ClampToS16(mix_buffers[0][i]); const auto r_sample = ClampToS16(mix_buffers[1][i]); if (stream_channel_count == 1) { - buffer[i * stream_channel_count + 0] = l_sample; + buffer[i * stream_channel_count + 0] = Mix2To1(l_sample, r_sample); } else if (stream_channel_count == 2) { buffer[i * stream_channel_count + 0] = l_sample; buffer[i * stream_channel_count + 1] = r_sample; @@ -215,8 +266,8 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { buffer[i * stream_channel_count + 0] = l_sample; buffer[i * stream_channel_count + 1] = r_sample; - buffer[i * stream_channel_count + 2] = - ClampToS16((static_cast<s32>(l_sample) + static_cast<s32>(r_sample)) / 2); + // Combine both left and right channels to the center channel + buffer[i * stream_channel_count + 2] = Mix2To1(l_sample, r_sample); buffer[i * stream_channel_count + 4] = l_sample; buffer[i * stream_channel_count + 5] = r_sample; @@ -231,17 +282,25 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { const auto br_sample = ClampToS16(mix_buffers[5][i]); if (stream_channel_count == 1) { - buffer[i * stream_channel_count + 0] = fc_sample; + // Games seem to ignore the center channel half the time, we use the front left + // and right channel for mixing as that's where majority of the audio goes + buffer[i * stream_channel_count + 0] = Mix2To1(fl_sample, fr_sample); } else if (stream_channel_count == 2) { - buffer[i * stream_channel_count + 0] = - static_cast<s16>(0.3694f * static_cast<float>(fl_sample) + - 0.2612f * static_cast<float>(fc_sample) + - 0.3694f * static_cast<float>(bl_sample)); - buffer[i * stream_channel_count + 1] = - static_cast<s16>(0.3694f * static_cast<float>(fr_sample) + - 0.2612f * static_cast<float>(fc_sample) + - 0.3694f * static_cast<float>(br_sample)); + // Mix all channels into 2 channels + if (sink_context.HasDownMixingCoefficients()) { + const auto [left, right] = Mix6To2WithCoefficients( + fl_sample, fr_sample, fc_sample, lf_sample, bl_sample, br_sample, + sink_context.GetDownmixCoefficients()); + buffer[i * stream_channel_count + 0] = left; + buffer[i * stream_channel_count + 1] = right; + } else { + const auto [left, right] = Mix6To2(fl_sample, fr_sample, fc_sample, + lf_sample, bl_sample, br_sample); + buffer[i * stream_channel_count + 0] = left; + buffer[i * stream_channel_count + 1] = right; + } } else if (stream_channel_count == 6) { + // Pass through buffer[i * stream_channel_count + 0] = fl_sample; buffer[i * stream_channel_count + 1] = fr_sample; buffer[i * stream_channel_count + 2] = fc_sample; @@ -259,7 +318,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { } void AudioRenderer::ReleaseAndQueueBuffers() { - const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream, 2)}; + const auto released_buffers{audio_out->GetTagsAndReleaseBuffers(stream)}; for (const auto& tag : released_buffers) { QueueMixedBuffer(tag); } diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 2fd93e058..54ac68b80 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h @@ -36,16 +36,10 @@ class Memory; } namespace AudioCore { -using DSPStateHolder = std::array<VoiceState*, 6>; +using DSPStateHolder = std::array<VoiceState*, AudioCommon::MAX_CHANNEL_COUNT>; class AudioOut; -struct RendererInfo { - u64_le elasped_frame_count{}; - INSERT_PADDING_WORDS(2); -}; -static_assert(sizeof(RendererInfo) == 0x10, "RendererInfo is an invalid size"); - class AudioRenderer { public: AudioRenderer(Core::Timing::CoreTiming& core_timing, Core::Memory::Memory& memory_, @@ -53,14 +47,14 @@ public: std::shared_ptr<Kernel::WritableEvent> buffer_event, std::size_t instance_number); ~AudioRenderer(); - ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params, - std::vector<u8>& output_params); + [[nodiscard]] ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params, + std::vector<u8>& output_params); void QueueMixedBuffer(Buffer::Tag tag); void ReleaseAndQueueBuffers(); - u32 GetSampleRate() const; - u32 GetSampleCount() const; - u32 GetMixBufferCount() const; - Stream::State GetStreamState() const; + [[nodiscard]] u32 GetSampleRate() const; + [[nodiscard]] u32 GetSampleCount() const; + [[nodiscard]] u32 GetMixBufferCount() const; + [[nodiscard]] Stream::State GetStreamState() const; private: BehaviorInfo behavior_info{}; @@ -79,7 +73,6 @@ private: Core::Memory::Memory& memory; CommandGenerator command_generator; std::size_t elapsed_frame_count{}; - std::vector<s32> temp_mix_buffer{}; }; } // namespace AudioCore diff --git a/src/audio_core/behavior_info.h b/src/audio_core/behavior_info.h index 512a4ebe3..5a96bf75e 100644 --- a/src/audio_core/behavior_info.h +++ b/src/audio_core/behavior_info.h @@ -43,22 +43,22 @@ public: void ClearError(); void UpdateFlags(u64_le dest_flags); void SetUserRevision(u32_le revision); - u32_le GetUserRevision() const; - u32_le GetProcessRevision() const; + [[nodiscard]] u32_le GetUserRevision() const; + [[nodiscard]] u32_le GetProcessRevision() const; - bool IsAdpcmLoopContextBugFixed() const; - bool IsSplitterSupported() const; - bool IsLongSizePreDelaySupported() const; - bool IsAudioRendererProcessingTimeLimit80PercentSupported() const; - bool IsAudioRendererProcessingTimeLimit75PercentSupported() const; - bool IsAudioRendererProcessingTimeLimit70PercentSupported() const; - bool IsElapsedFrameCountSupported() const; - bool IsMemoryPoolForceMappingEnabled() const; - bool IsFlushVoiceWaveBuffersSupported() const; - bool IsVoicePlayedSampleCountResetAtLoopPointSupported() const; - bool IsVoicePitchAndSrcSkippedSupported() const; - bool IsMixInParameterDirtyOnlyUpdateSupported() const; - bool IsSplitterBugFixed() const; + [[nodiscard]] bool IsAdpcmLoopContextBugFixed() const; + [[nodiscard]] bool IsSplitterSupported() const; + [[nodiscard]] bool IsLongSizePreDelaySupported() const; + [[nodiscard]] bool IsAudioRendererProcessingTimeLimit80PercentSupported() const; + [[nodiscard]] bool IsAudioRendererProcessingTimeLimit75PercentSupported() const; + [[nodiscard]] bool IsAudioRendererProcessingTimeLimit70PercentSupported() const; + [[nodiscard]] bool IsElapsedFrameCountSupported() const; + [[nodiscard]] bool IsMemoryPoolForceMappingEnabled() const; + [[nodiscard]] bool IsFlushVoiceWaveBuffersSupported() const; + [[nodiscard]] bool IsVoicePlayedSampleCountResetAtLoopPointSupported() const; + [[nodiscard]] bool IsVoicePitchAndSrcSkippedSupported() const; + [[nodiscard]] bool IsMixInParameterDirtyOnlyUpdateSupported() const; + [[nodiscard]] bool IsSplitterBugFixed() const; void CopyErrorInfo(OutParams& dst); private: diff --git a/src/audio_core/command_generator.h b/src/audio_core/command_generator.h index 53e57748b..87ece00c4 100644 --- a/src/audio_core/command_generator.h +++ b/src/audio_core/command_generator.h @@ -39,13 +39,13 @@ public: void PreCommand(); void PostCommand(); - s32* GetChannelMixBuffer(s32 channel); - const s32* GetChannelMixBuffer(s32 channel) const; - s32* GetMixBuffer(std::size_t index); - const s32* GetMixBuffer(std::size_t index) const; - std::size_t GetMixChannelBufferOffset(s32 channel) const; + [[nodiscard]] s32* GetChannelMixBuffer(s32 channel); + [[nodiscard]] const s32* GetChannelMixBuffer(s32 channel) const; + [[nodiscard]] s32* GetMixBuffer(std::size_t index); + [[nodiscard]] const s32* GetMixBuffer(std::size_t index) const; + [[nodiscard]] std::size_t GetMixChannelBufferOffset(s32 channel) const; - std::size_t GetTotalMixBufferCount() const; + [[nodiscard]] std::size_t GetTotalMixBufferCount() const; private: void GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 channel); @@ -73,7 +73,7 @@ private: void GenerateI3dl2ReverbEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); void GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); void GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled); - ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index); + [[nodiscard]] ServerSplitterDestinationData* GetDestinationData(s32 splitter_id, s32 index); s32 WriteAuxBuffer(AuxInfoDSP& dsp_info, VAddr send_buffer, u32 max_samples, const s32* data, u32 sample_count, u32 write_offset, u32 write_count); diff --git a/src/audio_core/common.h b/src/audio_core/common.h index 7b4a1e9e8..ec59a3ba9 100644 --- a/src/audio_core/common.h +++ b/src/audio_core/common.h @@ -22,7 +22,7 @@ constexpr std::size_t MAX_CHANNEL_COUNT = 6; constexpr std::size_t MAX_WAVE_BUFFERS = 4; constexpr std::size_t MAX_SAMPLE_HISTORY = 4; constexpr u32 STREAM_SAMPLE_RATE = 48000; -constexpr u32 STREAM_NUM_CHANNELS = 6; +constexpr u32 STREAM_NUM_CHANNELS = 2; constexpr s32 NO_SPLITTER = -1; constexpr s32 NO_MIX = 0x7fffffff; constexpr s32 NO_FINAL_MIX = std::numeric_limits<s32>::min(); diff --git a/src/audio_core/effect_context.h b/src/audio_core/effect_context.h index 2c4ce53ef..03c5a0f04 100644 --- a/src/audio_core/effect_context.h +++ b/src/audio_core/effect_context.h @@ -189,11 +189,11 @@ public: virtual void Update(EffectInfo::InParams& in_params) = 0; virtual void UpdateForCommandGeneration() = 0; - UsageState GetUsage() const; - EffectType GetType() const; - bool IsEnabled() const; - s32 GetMixID() const; - s32 GetProcessingOrder() const; + [[nodiscard]] UsageState GetUsage() const; + [[nodiscard]] EffectType GetType() const; + [[nodiscard]] bool IsEnabled() const; + [[nodiscard]] s32 GetMixID() const; + [[nodiscard]] s32 GetProcessingOrder() const; protected: UsageState usage{UsageState::Invalid}; @@ -257,10 +257,10 @@ public: void Update(EffectInfo::InParams& in_params) override; void UpdateForCommandGeneration() override; - VAddr GetSendInfo() const; - VAddr GetSendBuffer() const; - VAddr GetRecvInfo() const; - VAddr GetRecvBuffer() const; + [[nodiscard]] VAddr GetSendInfo() const; + [[nodiscard]] VAddr GetSendBuffer() const; + [[nodiscard]] VAddr GetRecvInfo() const; + [[nodiscard]] VAddr GetRecvBuffer() const; private: VAddr send_info{}; @@ -309,10 +309,10 @@ public: explicit EffectContext(std::size_t effect_count); ~EffectContext(); - std::size_t GetCount() const; - EffectBase* GetInfo(std::size_t i); - EffectBase* RetargetEffect(std::size_t i, EffectType effect); - const EffectBase* GetInfo(std::size_t i) const; + [[nodiscard]] std::size_t GetCount() const; + [[nodiscard]] EffectBase* GetInfo(std::size_t i); + [[nodiscard]] EffectBase* RetargetEffect(std::size_t i, EffectType effect); + [[nodiscard]] const EffectBase* GetInfo(std::size_t i) const; private: std::size_t effect_count{}; diff --git a/src/audio_core/mix_context.h b/src/audio_core/mix_context.h index 6a588eeb4..68bc673c6 100644 --- a/src/audio_core/mix_context.h +++ b/src/audio_core/mix_context.h @@ -62,17 +62,17 @@ public: ServerMixInfo(); ~ServerMixInfo(); - const ServerMixInfo::InParams& GetInParams() const; - ServerMixInfo::InParams& GetInParams(); + [[nodiscard]] const ServerMixInfo::InParams& GetInParams() const; + [[nodiscard]] ServerMixInfo::InParams& GetInParams(); bool Update(EdgeMatrix& edge_matrix, const MixInfo::InParams& mix_in, BehaviorInfo& behavior_info, SplitterContext& splitter_context, EffectContext& effect_context); - bool HasAnyConnection() const; + [[nodiscard]] bool HasAnyConnection() const; void Cleanup(); void SetEffectCount(std::size_t count); void ResetEffectProcessingOrder(); - s32 GetEffectOrder(std::size_t i) const; + [[nodiscard]] s32 GetEffectOrder(std::size_t i) const; private: std::vector<s32> effect_processing_order; @@ -91,15 +91,15 @@ public: void SortInfo(); bool TsortInfo(SplitterContext& splitter_context); - std::size_t GetCount() const; - ServerMixInfo& GetInfo(std::size_t i); - const ServerMixInfo& GetInfo(std::size_t i) const; - ServerMixInfo& GetSortedInfo(std::size_t i); - const ServerMixInfo& GetSortedInfo(std::size_t i) const; - ServerMixInfo& GetFinalMixInfo(); - const ServerMixInfo& GetFinalMixInfo() const; - EdgeMatrix& GetEdgeMatrix(); - const EdgeMatrix& GetEdgeMatrix() const; + [[nodiscard]] std::size_t GetCount() const; + [[nodiscard]] ServerMixInfo& GetInfo(std::size_t i); + [[nodiscard]] const ServerMixInfo& GetInfo(std::size_t i) const; + [[nodiscard]] ServerMixInfo& GetSortedInfo(std::size_t i); + [[nodiscard]] const ServerMixInfo& GetSortedInfo(std::size_t i) const; + [[nodiscard]] ServerMixInfo& GetFinalMixInfo(); + [[nodiscard]] const ServerMixInfo& GetFinalMixInfo() const; + [[nodiscard]] EdgeMatrix& GetEdgeMatrix(); + [[nodiscard]] const EdgeMatrix& GetEdgeMatrix() const; private: void CalcMixBufferOffset(); diff --git a/src/audio_core/sink_context.cpp b/src/audio_core/sink_context.cpp index 0882b411a..b29b47890 100644 --- a/src/audio_core/sink_context.cpp +++ b/src/audio_core/sink_context.cpp @@ -12,10 +12,16 @@ std::size_t SinkContext::GetCount() const { return sink_count; } -void SinkContext::UpdateMainSink(SinkInfo::InParams& in) { +void SinkContext::UpdateMainSink(const SinkInfo::InParams& in) { + ASSERT(in.type == SinkTypes::Device); + + has_downmix_coefs = in.device.down_matrix_enabled; + if (has_downmix_coefs) { + downmix_coefficients = in.device.down_matrix_coef; + } in_use = in.in_use; use_count = in.device.input_count; - std::memcpy(buffers.data(), in.device.input.data(), AudioCommon::MAX_CHANNEL_COUNT); + buffers = in.device.input; } bool SinkContext::InUse() const { @@ -28,4 +34,12 @@ std::vector<u8> SinkContext::OutputBuffers() const { return buffer_ret; } +bool SinkContext::HasDownMixingCoefficients() const { + return has_downmix_coefs; +} + +const DownmixCoefficients& SinkContext::GetDownmixCoefficients() const { + return downmix_coefficients; +} + } // namespace AudioCore diff --git a/src/audio_core/sink_context.h b/src/audio_core/sink_context.h index d7aa72ba7..e2e7880b7 100644 --- a/src/audio_core/sink_context.h +++ b/src/audio_core/sink_context.h @@ -11,6 +11,8 @@ namespace AudioCore { +using DownmixCoefficients = std::array<float_le, 4>; + enum class SinkTypes : u8 { Invalid = 0, Device = 1, @@ -50,7 +52,7 @@ public: std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> input; INSERT_UNION_PADDING_BYTES(1); bool down_matrix_enabled; - std::array<float_le, 4> down_matrix_coef; + DownmixCoefficients down_matrix_coef; }; static_assert(sizeof(SinkInfo::DeviceIn) == 0x11c, "SinkInfo::DeviceIn is an invalid size"); @@ -74,16 +76,21 @@ public: explicit SinkContext(std::size_t sink_count); ~SinkContext(); - std::size_t GetCount() const; + [[nodiscard]] std::size_t GetCount() const; + + void UpdateMainSink(const SinkInfo::InParams& in); + [[nodiscard]] bool InUse() const; + [[nodiscard]] std::vector<u8> OutputBuffers() const; - void UpdateMainSink(SinkInfo::InParams& in); - bool InUse() const; - std::vector<u8> OutputBuffers() const; + [[nodiscard]] bool HasDownMixingCoefficients() const; + [[nodiscard]] const DownmixCoefficients& GetDownmixCoefficients() const; private: bool in_use{false}; s32 use_count{}; std::array<u8, AudioCommon::MAX_CHANNEL_COUNT> buffers{}; std::size_t sink_count{}; + bool has_downmix_coefs{false}; + DownmixCoefficients downmix_coefficients{}; }; } // namespace AudioCore diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 4bbb1e0c4..41bc2f4d6 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp @@ -136,4 +136,14 @@ std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers(std::size_t max_count) return tags; } +std::vector<Buffer::Tag> Stream::GetTagsAndReleaseBuffers() { + std::vector<Buffer::Tag> tags; + tags.reserve(released_buffers.size()); + while (!released_buffers.empty()) { + tags.push_back(released_buffers.front()->GetTag()); + released_buffers.pop(); + } + return tags; +} + } // namespace AudioCore diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 6437b8591..71c2d0b4f 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h @@ -57,37 +57,40 @@ public: bool QueueBuffer(BufferPtr&& buffer); /// Returns true if the audio stream contains a buffer with the specified tag - bool ContainsBuffer(Buffer::Tag tag) const; + [[nodiscard]] bool ContainsBuffer(Buffer::Tag tag) const; /// Returns a vector of recently released buffers specified by tag - std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count); + [[nodiscard]] std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(std::size_t max_count); + + /// Returns a vector of all recently released buffers specified by tag + [[nodiscard]] std::vector<Buffer::Tag> GetTagsAndReleaseBuffers(); void SetVolume(float volume); - float GetVolume() const { + [[nodiscard]] float GetVolume() const { return game_volume; } /// Returns true if the stream is currently playing - bool IsPlaying() const { + [[nodiscard]] bool IsPlaying() const { return state == State::Playing; } /// Returns the number of queued buffers - std::size_t GetQueueSize() const { + [[nodiscard]] std::size_t GetQueueSize() const { return queued_buffers.size(); } /// Gets the sample rate - u32 GetSampleRate() const { + [[nodiscard]] u32 GetSampleRate() const { return sample_rate; } /// Gets the number of channels - u32 GetNumChannels() const; + [[nodiscard]] u32 GetNumChannels() const; /// Get the state - State GetState() const; + [[nodiscard]] State GetState() const; private: /// Plays the next queued buffer in the audio stream, starting playback if necessary @@ -97,7 +100,7 @@ private: void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {}); /// Gets the number of core cycles when the specified buffer will be released - std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const; + [[nodiscard]] std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const; u32 sample_rate; ///< Sample rate of the stream Format format; ///< Format of the stream diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 207c7a0a6..56c7e21f5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -102,6 +102,7 @@ add_library(common STATIC atomic_ops.h detached_tasks.cpp detached_tasks.h + bit_cast.h bit_field.h bit_util.h cityhash.cpp @@ -111,6 +112,7 @@ add_library(common STATIC common_paths.h common_types.h concepts.h + div_ceil.h dynamic_library.cpp dynamic_library.h fiber.cpp diff --git a/src/common/bit_cast.h b/src/common/bit_cast.h new file mode 100644 index 000000000..a32a063d1 --- /dev/null +++ b/src/common/bit_cast.h @@ -0,0 +1,22 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <cstring> +#include <type_traits> + +namespace Common { + +template <typename To, typename From> +[[nodiscard]] std::enable_if_t<sizeof(To) == sizeof(From) && std::is_trivially_copyable_v<From> && + std::is_trivially_copyable_v<To>, + To> +BitCast(const From& src) noexcept { + To dst; + std::memcpy(&dst, &src, sizeof(To)); + return dst; +} + +} // namespace Common diff --git a/src/common/div_ceil.h b/src/common/div_ceil.h new file mode 100644 index 000000000..6b2c48f91 --- /dev/null +++ b/src/common/div_ceil.h @@ -0,0 +1,26 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <cstddef> +#include <type_traits> + +namespace Common { + +/// Ceiled integer division. +template <typename N, typename D> +requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr auto DivCeil( + N number, D divisor) { + return (static_cast<D>(number) + divisor - 1) / divisor; +} + +/// Ceiled integer division with logarithmic divisor in base 2 +template <typename N, typename D> +requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr auto DivCeilLog2( + N value, D alignment_log2) { + return (static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2; +} + +} // namespace Common diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 90dfa22ca..631f64d05 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -23,6 +23,7 @@ #include "common/logging/text_formatter.h" #include "common/string_util.h" #include "common/threadsafe_queue.h" +#include "core/settings.h" namespace Log { @@ -152,10 +153,19 @@ FileBackend::FileBackend(const std::string& filename) void FileBackend::Write(const Entry& entry) { // prevent logs from going over the maximum size (in case its spamming and the user doesn't // know) - constexpr std::size_t MAX_BYTES_WRITTEN = 50 * 1024L * 1024L; - if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) { + constexpr std::size_t MAX_BYTES_WRITTEN = 100 * 1024 * 1024; + constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1024 * 1024 * 1024; + + if (!file.IsOpen()) { + return; + } + + if (Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN_EXTENDED) { + return; + } else if (!Settings::values.extended_logging && bytes_written > MAX_BYTES_WRITTEN) { return; } + bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); if (entry.log_level >= Level::Error) { file.Flush(); @@ -222,6 +232,7 @@ void DebuggerBackend::Write(const Entry& entry) { SUB(Service, NPNS) \ SUB(Service, NS) \ SUB(Service, NVDRV) \ + SUB(Service, OLSC) \ SUB(Service, PCIE) \ SUB(Service, PCTL) \ SUB(Service, PCV) \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 13a4f1e30..835894918 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -95,6 +95,7 @@ enum class Class : ClassType { Service_NPNS, ///< The NPNS service Service_NS, ///< The NS services Service_NVDRV, ///< The NVDRV (Nvidia driver) service + Service_OLSC, ///< The OLSC service Service_PCIE, ///< The PCIe service Service_PCTL, ///< The PCTL (Parental control) service Service_PCV, ///< The PCV service diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a1d8dcfa5..66de33799 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -135,8 +135,6 @@ add_library(core STATIC frontend/framebuffer_layout.cpp frontend/framebuffer_layout.h frontend/input.h - gdbstub/gdbstub.cpp - gdbstub/gdbstub.h hardware_interrupt_manager.cpp hardware_interrupt_manager.h hle/ipc.h @@ -458,6 +456,8 @@ add_library(core STATIC hle/service/nvflinger/buffer_queue.h hle/service/nvflinger/nvflinger.cpp hle/service/nvflinger/nvflinger.h + hle/service/olsc/olsc.cpp + hle/service/olsc/olsc.h hle/service/pcie/pcie.cpp hle/service/pcie/pcie.h hle/service/pctl/module.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 9f170a224..5c2060d78 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -14,7 +14,6 @@ #include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" -#include "core/gdbstub/gdbstub.h" #include "core/hardware_properties.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" @@ -96,16 +95,6 @@ public: case Dynarmic::A64::Exception::Yield: return; case Dynarmic::A64::Exception::Breakpoint: - if (GDBStub::IsServerEnabled()) { - parent.jit->HaltExecution(); - parent.SetPC(pc); - Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread(); - parent.SaveContext(thread->GetContext64()); - GDBStub::Break(); - GDBStub::SendTrap(thread, 5); - return; - } - [[fallthrough]]; default: ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); diff --git a/src/core/core.cpp b/src/core/core.cpp index 242796008..76a38ea2a 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -25,7 +25,6 @@ #include "core/file_sys/sdmc_factory.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" -#include "core/gdbstub/gdbstub.h" #include "core/hardware_interrupt_manager.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" @@ -92,33 +91,43 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, std::string dir_name; std::string filename; Common::SplitPath(path, &dir_name, &filename, nullptr); + if (filename == "00") { const auto dir = vfs->OpenDirectory(dir_name, FileSys::Mode::Read); std::vector<FileSys::VirtualFile> concat; - for (u8 i = 0; i < 0x10; ++i) { - auto next = dir->GetFile(fmt::format("{:02X}", i)); - if (next != nullptr) + + for (u32 i = 0; i < 0x10; ++i) { + const auto file_name = fmt::format("{:02X}", i); + auto next = dir->GetFile(file_name); + + if (next != nullptr) { concat.push_back(std::move(next)); - else { - next = dir->GetFile(fmt::format("{:02x}", i)); - if (next != nullptr) - concat.push_back(std::move(next)); - else + } else { + next = dir->GetFile(file_name); + + if (next == nullptr) { break; + } + + concat.push_back(std::move(next)); } } - if (concat.empty()) + if (concat.empty()) { return nullptr; + } - return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(concat, dir->GetName()); + return FileSys::ConcatenatedVfsFile::MakeConcatenatedFile(std::move(concat), + dir->GetName()); } - if (Common::FS::IsDirectory(path)) - return vfs->OpenFile(path + "/" + "main", FileSys::Mode::Read); + if (Common::FS::IsDirectory(path)) { + return vfs->OpenFile(path + "/main", FileSys::Mode::Read); + } return vfs->OpenFile(path, FileSys::Mode::Read); } + struct System::Impl { explicit Impl(System& system) : kernel{system}, fs_controller{system}, memory{system}, @@ -145,7 +154,7 @@ struct System::Impl { } ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) { - LOG_DEBUG(HW_Memory, "initialized OK"); + LOG_DEBUG(Core, "initialized OK"); device_memory = std::make_unique<Core::DeviceMemory>(); @@ -186,11 +195,8 @@ struct System::Impl { } service_manager = std::make_shared<Service::SM::ServiceManager>(kernel); - - Service::Init(service_manager, system); - GDBStub::DeferStart(); - - interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system); + services = std::make_unique<Service::Services>(service_manager, system); + interrupt_manager = std::make_unique<Hardware::InterruptManager>(system); // Initialize time manager, which must happen after kernel is created time_manager.Initialize(); @@ -208,9 +214,11 @@ struct System::Impl { return ResultStatus::Success; } - ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, - const std::string& filepath) { - app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); + ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, + std::size_t program_index) { + app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), + program_index); + if (!app_loader) { LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); return ResultStatus::ErrorGetLoader; @@ -224,7 +232,7 @@ struct System::Impl { return init_result; } - telemetry_session->AddInitialInfo(*app_loader); + telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); auto main_process = Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); @@ -295,8 +303,7 @@ struct System::Impl { } // Shutdown emulation session - GDBStub::Shutdown(); - Service::Shutdown(); + services.reset(); service_manager.reset(); cheat_engine.reset(); telemetry_session.reset(); @@ -306,8 +313,8 @@ struct System::Impl { cpu_manager.Shutdown(); // Shutdown kernel and core timing - kernel.Shutdown(); core_timing.Shutdown(); + kernel.Shutdown(); // Close app loader app_loader.reset(); @@ -338,7 +345,7 @@ struct System::Impl { Service::Glue::ApplicationLaunchProperty launch{}; launch.title_id = process.GetTitleID(); - FileSys::PatchManager pm{launch.title_id}; + FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider}; launch.version = pm.GetGameVersion().value_or(0); // TODO(DarkLordZach): When FSController/Game Card Support is added, if @@ -398,6 +405,9 @@ struct System::Impl { /// Service manager std::shared_ptr<Service::SM::ServiceManager> service_manager; + /// Services + std::unique_ptr<Service::Services> services; + /// Telemetry session for this emulation session std::unique_ptr<Core::TelemetrySession> telemetry_session; @@ -413,6 +423,8 @@ struct System::Impl { bool is_multicore{}; bool is_async_gpu{}; + ExecuteProgramCallback execute_program_callback; + std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; }; @@ -444,8 +456,13 @@ void System::InvalidateCpuInstructionCaches() { impl->kernel.InvalidateAllInstructionCaches(); } -System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { - return impl->Load(*this, emu_window, filepath); +void System::Shutdown() { + impl->Shutdown(); +} + +System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath, + std::size_t program_index) { + return impl->Load(*this, emu_window, filepath, program_index); } bool System::IsPoweredOn() const { @@ -632,7 +649,11 @@ const std::string& System::GetStatusDetails() const { return impl->status_details; } -Loader::AppLoader& System::GetAppLoader() const { +Loader::AppLoader& System::GetAppLoader() { + return *impl->app_loader; +} + +const Loader::AppLoader& System::GetAppLoader() const { return *impl->app_loader; } @@ -748,14 +769,6 @@ const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const { return impl->build_id; } -System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { - return impl->Init(*this, emu_window); -} - -void System::Shutdown() { - impl->Shutdown(); -} - Service::SM::ServiceManager& System::ServiceManager() { return *impl->service_manager; } @@ -786,4 +799,16 @@ bool System::IsMulticore() const { return impl->is_multicore; } +void System::RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback) { + impl->execute_program_callback = std::move(callback); +} + +void System::ExecuteProgram(std::size_t program_index) { + if (impl->execute_program_callback) { + impl->execute_program_callback(program_index); + } else { + LOG_CRITICAL(Core, "execute_program_callback must be initialized by the frontend"); + } +} + } // namespace Core diff --git a/src/core/core.h b/src/core/core.h index 6db896bae..f642befc0 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -5,6 +5,7 @@ #pragma once #include <cstddef> +#include <functional> #include <memory> #include <string> #include <vector> @@ -144,19 +145,19 @@ public: * Run the OS and Application * This function will start emulation and run the relevant devices */ - ResultStatus Run(); + [[nodiscard]] ResultStatus Run(); /** * Pause the OS and Application * This function will pause emulation and stop the relevant devices */ - ResultStatus Pause(); + [[nodiscard]] ResultStatus Pause(); /** * Step the CPU one instruction * @return Result status, indicating whether or not the operation succeeded. */ - ResultStatus SingleStep(); + [[nodiscard]] ResultStatus SingleStep(); /** * Invalidate the CPU instruction caches @@ -173,22 +174,24 @@ public: * @param emu_window Reference to the host-system window used for video output and keyboard * input. * @param filepath String path to the executable application to load on the host file system. + * @param program_index Specifies the index within the container of the program to launch. * @returns ResultStatus code, indicating if the operation succeeded. */ - ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath); + [[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath, + std::size_t program_index = 0); /** * Indicates if the emulated system is powered on (all subsystems initialized and able to run an * application). * @returns True if the emulated system is powered on, otherwise false. */ - bool IsPoweredOn() const; + [[nodiscard]] bool IsPoweredOn() const; /// Gets a reference to the telemetry session for this emulation session. - Core::TelemetrySession& TelemetrySession(); + [[nodiscard]] Core::TelemetrySession& TelemetrySession(); /// Gets a reference to the telemetry session for this emulation session. - const Core::TelemetrySession& TelemetrySession() const; + [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; /// Prepare the core emulation for a reschedule void PrepareReschedule(); @@ -197,185 +200,178 @@ public: void PrepareReschedule(u32 core_index); /// Gets and resets core performance statistics - PerfStatsResults GetAndResetPerfStats(); + [[nodiscard]] PerfStatsResults GetAndResetPerfStats(); /// Gets an ARM interface to the CPU core that is currently running - ARM_Interface& CurrentArmInterface(); + [[nodiscard]] ARM_Interface& CurrentArmInterface(); /// Gets an ARM interface to the CPU core that is currently running - const ARM_Interface& CurrentArmInterface() const; + [[nodiscard]] const ARM_Interface& CurrentArmInterface() const; /// Gets the index of the currently running CPU core - std::size_t CurrentCoreIndex() const; + [[nodiscard]] std::size_t CurrentCoreIndex() const; /// Gets the scheduler for the CPU core that is currently running - Kernel::Scheduler& CurrentScheduler(); + [[nodiscard]] Kernel::Scheduler& CurrentScheduler(); /// Gets the scheduler for the CPU core that is currently running - const Kernel::Scheduler& CurrentScheduler() const; + [[nodiscard]] const Kernel::Scheduler& CurrentScheduler() const; /// Gets the physical core for the CPU core that is currently running - Kernel::PhysicalCore& CurrentPhysicalCore(); + [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); /// Gets the physical core for the CPU core that is currently running - const Kernel::PhysicalCore& CurrentPhysicalCore() const; + [[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const; /// Gets a reference to an ARM interface for the CPU core with the specified index - ARM_Interface& ArmInterface(std::size_t core_index); + [[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index); /// Gets a const reference to an ARM interface from the CPU core with the specified index - const ARM_Interface& ArmInterface(std::size_t core_index) const; + [[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const; - CpuManager& GetCpuManager(); + /// Gets a reference to the underlying CPU manager. + [[nodiscard]] CpuManager& GetCpuManager(); - const CpuManager& GetCpuManager() const; + /// Gets a const reference to the underlying CPU manager + [[nodiscard]] const CpuManager& GetCpuManager() const; /// Gets a reference to the exclusive monitor - ExclusiveMonitor& Monitor(); + [[nodiscard]] ExclusiveMonitor& Monitor(); /// Gets a constant reference to the exclusive monitor - const ExclusiveMonitor& Monitor() const; + [[nodiscard]] const ExclusiveMonitor& Monitor() const; /// Gets a mutable reference to the system memory instance. - Core::Memory::Memory& Memory(); + [[nodiscard]] Core::Memory::Memory& Memory(); /// Gets a constant reference to the system memory instance. - const Core::Memory::Memory& Memory() const; + [[nodiscard]] const Core::Memory::Memory& Memory() const; /// Gets a mutable reference to the GPU interface - Tegra::GPU& GPU(); + [[nodiscard]] Tegra::GPU& GPU(); /// Gets an immutable reference to the GPU interface. - const Tegra::GPU& GPU() const; + [[nodiscard]] const Tegra::GPU& GPU() const; /// Gets a mutable reference to the renderer. - VideoCore::RendererBase& Renderer(); + [[nodiscard]] VideoCore::RendererBase& Renderer(); /// Gets an immutable reference to the renderer. - const VideoCore::RendererBase& Renderer() const; + [[nodiscard]] const VideoCore::RendererBase& Renderer() const; /// Gets the scheduler for the CPU core with the specified index - Kernel::Scheduler& Scheduler(std::size_t core_index); + [[nodiscard]] Kernel::Scheduler& Scheduler(std::size_t core_index); /// Gets the scheduler for the CPU core with the specified index - const Kernel::Scheduler& Scheduler(std::size_t core_index) const; + [[nodiscard]] const Kernel::Scheduler& Scheduler(std::size_t core_index) const; /// Gets the global scheduler - Kernel::GlobalScheduler& GlobalScheduler(); + [[nodiscard]] Kernel::GlobalScheduler& GlobalScheduler(); /// Gets the global scheduler - const Kernel::GlobalScheduler& GlobalScheduler() const; + [[nodiscard]] const Kernel::GlobalScheduler& GlobalScheduler() const; /// Gets the manager for the guest device memory - Core::DeviceMemory& DeviceMemory(); + [[nodiscard]] Core::DeviceMemory& DeviceMemory(); /// Gets the manager for the guest device memory - const Core::DeviceMemory& DeviceMemory() const; + [[nodiscard]] const Core::DeviceMemory& DeviceMemory() const; /// Provides a pointer to the current process - Kernel::Process* CurrentProcess(); + [[nodiscard]] Kernel::Process* CurrentProcess(); /// Provides a constant pointer to the current process. - const Kernel::Process* CurrentProcess() const; + [[nodiscard]] const Kernel::Process* CurrentProcess() const; /// Provides a reference to the core timing instance. - Timing::CoreTiming& CoreTiming(); + [[nodiscard]] Timing::CoreTiming& CoreTiming(); /// Provides a constant reference to the core timing instance. - const Timing::CoreTiming& CoreTiming() const; + [[nodiscard]] const Timing::CoreTiming& CoreTiming() const; /// Provides a reference to the interrupt manager instance. - Core::Hardware::InterruptManager& InterruptManager(); + [[nodiscard]] Core::Hardware::InterruptManager& InterruptManager(); /// Provides a constant reference to the interrupt manager instance. - const Core::Hardware::InterruptManager& InterruptManager() const; + [[nodiscard]] const Core::Hardware::InterruptManager& InterruptManager() const; /// Provides a reference to the kernel instance. - Kernel::KernelCore& Kernel(); + [[nodiscard]] Kernel::KernelCore& Kernel(); /// Provides a constant reference to the kernel instance. - const Kernel::KernelCore& Kernel() const; + [[nodiscard]] const Kernel::KernelCore& Kernel() const; /// Provides a reference to the internal PerfStats instance. - Core::PerfStats& GetPerfStats(); + [[nodiscard]] Core::PerfStats& GetPerfStats(); /// Provides a constant reference to the internal PerfStats instance. - const Core::PerfStats& GetPerfStats() const; + [[nodiscard]] const Core::PerfStats& GetPerfStats() const; /// Provides a reference to the frame limiter; - Core::FrameLimiter& FrameLimiter(); + [[nodiscard]] Core::FrameLimiter& FrameLimiter(); /// Provides a constant referent to the frame limiter - const Core::FrameLimiter& FrameLimiter() const; + [[nodiscard]] const Core::FrameLimiter& FrameLimiter() const; /// Gets the name of the current game - Loader::ResultStatus GetGameName(std::string& out) const; + [[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const; void SetStatus(ResultStatus new_status, const char* details); - const std::string& GetStatusDetails() const; + [[nodiscard]] const std::string& GetStatusDetails() const; - Loader::AppLoader& GetAppLoader() const; + [[nodiscard]] Loader::AppLoader& GetAppLoader(); + [[nodiscard]] const Loader::AppLoader& GetAppLoader() const; - Service::SM::ServiceManager& ServiceManager(); - const Service::SM::ServiceManager& ServiceManager() const; + [[nodiscard]] Service::SM::ServiceManager& ServiceManager(); + [[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const; void SetFilesystem(FileSys::VirtualFilesystem vfs); - FileSys::VirtualFilesystem GetFilesystem() const; + [[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const; void RegisterCheatList(const std::vector<Memory::CheatEntry>& list, const std::array<u8, 0x20>& build_id, VAddr main_region_begin, u64 main_region_size); void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); - void SetDefaultAppletFrontendSet(); - Service::AM::Applets::AppletManager& GetAppletManager(); - - const Service::AM::Applets::AppletManager& GetAppletManager() const; + [[nodiscard]] Service::AM::Applets::AppletManager& GetAppletManager(); + [[nodiscard]] const Service::AM::Applets::AppletManager& GetAppletManager() const; void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); - FileSys::ContentProvider& GetContentProvider(); - - const FileSys::ContentProvider& GetContentProvider() const; + [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); + [[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const; - Service::FileSystem::FileSystemController& GetFileSystemController(); - - const Service::FileSystem::FileSystemController& GetFileSystemController() const; + [[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController(); + [[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const; void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot, FileSys::ContentProvider* provider); void ClearContentProvider(FileSys::ContentProviderUnionSlot slot); - const Reporter& GetReporter() const; - - Service::Glue::ARPManager& GetARPManager(); + [[nodiscard]] const Reporter& GetReporter() const; - const Service::Glue::ARPManager& GetARPManager() const; + [[nodiscard]] Service::Glue::ARPManager& GetARPManager(); + [[nodiscard]] const Service::Glue::ARPManager& GetARPManager() const; - Service::APM::Controller& GetAPMController(); + [[nodiscard]] Service::APM::Controller& GetAPMController(); + [[nodiscard]] const Service::APM::Controller& GetAPMController() const; - const Service::APM::Controller& GetAPMController() const; + [[nodiscard]] Service::LM::Manager& GetLogManager(); + [[nodiscard]] const Service::LM::Manager& GetLogManager() const; - Service::LM::Manager& GetLogManager(); - - const Service::LM::Manager& GetLogManager() const; - - Service::Time::TimeManager& GetTimeManager(); - - const Service::Time::TimeManager& GetTimeManager() const; + [[nodiscard]] Service::Time::TimeManager& GetTimeManager(); + [[nodiscard]] const Service::Time::TimeManager& GetTimeManager() const; void SetExitLock(bool locked); - - bool GetExitLock() const; + [[nodiscard]] bool GetExitLock() const; void SetCurrentProcessBuildID(const CurrentBuildProcessID& id); - - const CurrentBuildProcessID& GetCurrentProcessBuildID() const; + [[nodiscard]] const CurrentBuildProcessID& GetCurrentProcessBuildID() const; /// Register a host thread as an emulated CPU Core. void RegisterCoreThread(std::size_t id); @@ -390,18 +386,27 @@ public: void ExitDynarmicProfile(); /// Tells if system is running on multicore. - bool IsMulticore() const; + [[nodiscard]] bool IsMulticore() const; -private: - System(); + /// Type used for the frontend to designate a callback for System to re-launch the application + /// using a specified program index. + using ExecuteProgramCallback = std::function<void(std::size_t)>; /** - * Initialize the emulated system. - * @param emu_window Reference to the host-system window used for video output and keyboard - * input. - * @return ResultStatus code, indicating if the operation succeeded. + * Registers a callback from the frontend for System to re-launch the application using a + * specified program index. + * @param callback Callback from the frontend to relaunch the application. + */ + void RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback); + + /** + * Instructs the frontend to re-launch the application using the specified program_index. + * @param program_index Specifies the index within the application of the program to launch. */ - ResultStatus Init(Frontend::EmuWindow& emu_window); + void ExecuteProgram(std::size_t program_index); + +private: + System(); struct Impl; std::unique_ptr<Impl> impl; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 983210197..eeeb6e8df 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -4,12 +4,12 @@ #include "common/fiber.h" #include "common/microprofile.h" +#include "common/scope_exit.h" #include "common/thread.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" #include "core/cpu_manager.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/scheduler.h" @@ -343,6 +343,16 @@ void CpuManager::RunThread(std::size_t core) { data.initialized = true; const bool sc_sync = !is_async_gpu && !is_multicore; bool sc_sync_first_use = sc_sync; + + // Cleanup + SCOPE_EXIT({ + data.host_context->Exit(); + data.enter_barrier.reset(); + data.exit_barrier.reset(); + data.initialized = false; + MicroProfileOnThreadExit(); + }); + /// Running while (running_mode) { data.is_running = false; @@ -351,6 +361,12 @@ void CpuManager::RunThread(std::size_t core) { system.GPU().ObtainContext(); sc_sync_first_use = false; } + + // Abort if emulation was killed before the session really starts + if (!system.IsPoweredOn()) { + return; + } + auto& scheduler = system.Kernel().CurrentScheduler(); Kernel::Thread* current_thread = scheduler.GetCurrentThread(); data.is_running = true; @@ -360,13 +376,6 @@ void CpuManager::RunThread(std::size_t core) { data.exit_barrier->Wait(); data.is_paused = false; } - /// Time to cleanup - data.host_context->Exit(); - data.enter_barrier.reset(); - data.exit_barrier.reset(); - data.initialized = false; - - MicroProfileOnThreadExit(); } } // namespace Core diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp index 956da68f7..8dee5590b 100644 --- a/src/core/file_sys/card_image.cpp +++ b/src/core/file_sys/card_image.cpp @@ -29,7 +29,7 @@ constexpr std::array partition_names{ "logo", }; -XCI::XCI(VirtualFile file_) +XCI::XCI(VirtualFile file_, std::size_t program_index) : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, partitions(partition_names.size()), partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} { @@ -62,7 +62,8 @@ XCI::XCI(VirtualFile file_) } secure_partition = std::make_shared<NSP>( - main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)])); + main_hfs.GetFile(partition_names[static_cast<std::size_t>(XCIPartition::Secure)]), + program_index); ncas = secure_partition->GetNCAsCollapsed(); program = diff --git a/src/core/file_sys/card_image.h b/src/core/file_sys/card_image.h index 2d0a0f285..4960e90fe 100644 --- a/src/core/file_sys/card_image.h +++ b/src/core/file_sys/card_image.h @@ -78,7 +78,7 @@ enum class XCIPartition : u8 { Update, Normal, Secure, Logo }; class XCI : public ReadOnlyVfsDirectory { public: - explicit XCI(VirtualFile file); + explicit XCI(VirtualFile file, std::size_t program_index = 0); ~XCI() override; Loader::ResultStatus GetStatus() const; diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 807b05821..e9d1607d0 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -112,7 +112,10 @@ bool IsDirValidAndNonEmpty(const VirtualDir& dir) { } } // Anonymous namespace -PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} +PatchManager::PatchManager(u64 title_id_, + const Service::FileSystem::FileSystemController& fs_controller_, + const ContentProvider& content_provider_) + : title_id{title_id_}, fs_controller{fs_controller_}, content_provider{content_provider_} {} PatchManager::~PatchManager() = default; @@ -128,34 +131,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { if (Settings::values.dump_exefs) { LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); - const auto dump_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id); + const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id); if (dump_dir != nullptr) { const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); VfsRawCopyD(exefs, exefs_dir); } } - const auto& installed = Core::System::GetInstance().GetContentProvider(); - const auto& disabled = Settings::values.disabled_addons[title_id]; const auto update_disabled = std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); // Game Updates const auto update_tid = GetUpdateTitleID(title_id); - const auto update = installed.GetEntry(update_tid, ContentRecordType::Program); + const auto update = content_provider.GetEntry(update_tid, ContentRecordType::Program); if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr && update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", - FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); + FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0))); exefs = update->GetExeFS(); } // LayeredExeFS - const auto load_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); + const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if (load_dir != nullptr && load_dir->GetSize() > 0) { auto patch_dirs = load_dir->GetSubdirectories(); std::sort( @@ -241,8 +240,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st if (Settings::values.dump_nso) { LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id, title_id); - const auto dump_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id); + const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id); if (dump_dir != nullptr) { const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso"); const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id)); @@ -254,8 +252,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id); - const auto load_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); + const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return nso; @@ -298,8 +295,7 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const { LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id); - const auto load_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); + const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return false; @@ -313,8 +309,8 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const { } std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( - const Core::System& system, const BuildID& build_id_) const { - const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id); + const BuildID& build_id_) const { + const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return {}; @@ -347,9 +343,9 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( return out; } -static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { - const auto load_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); +static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type, + const Service::FileSystem::FileSystemController& fs_controller) { + const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || load_dir == nullptr || load_dir->GetSize() <= 0) { return; @@ -411,19 +407,19 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}", title_id, static_cast<u8>(type)); - if (type == ContentRecordType::Program || type == ContentRecordType::Data) + if (type == ContentRecordType::Program || type == ContentRecordType::Data) { LOG_INFO(Loader, "{}", log_string); - else + } else { LOG_DEBUG(Loader, "{}", log_string); + } - if (romfs == nullptr) + if (romfs == nullptr) { return romfs; - - const auto& installed = Core::System::GetInstance().GetContentProvider(); + } // Game Updates const auto update_tid = GetUpdateTitleID(title_id); - const auto update = installed.GetEntryRaw(update_tid, type); + const auto update = content_provider.GetEntryRaw(update_tid, type); const auto& disabled = Settings::values.disabled_addons[title_id]; const auto update_disabled = @@ -434,7 +430,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content if (new_nca->GetStatus() == Loader::ResultStatus::Success && new_nca->GetRomFS() != nullptr) { LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", - FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); + FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0))); romfs = new_nca->GetRomFS(); } } else if (!update_disabled && update_raw != nullptr) { @@ -447,7 +443,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content } // LayeredFS - ApplyLayeredFS(romfs, title_id, type); + ApplyLayeredFS(romfs, title_id, type, fs_controller); return romfs; } @@ -458,12 +454,11 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } std::map<std::string, std::string, std::less<>> out; - const auto& installed = Core::System::GetInstance().GetContentProvider(); const auto& disabled = Settings::values.disabled_addons[title_id]; // Game Updates const auto update_tid = GetUpdateTitleID(title_id); - PatchManager update{update_tid}; + PatchManager update{update_tid, fs_controller, content_provider}; const auto metadata = update.GetControlMetadata(); const auto& nacp = metadata.first; @@ -474,8 +469,8 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u if (nacp != nullptr) { out.insert_or_assign(update_label, nacp->GetVersionString()); } else { - if (installed.HasEntry(update_tid, ContentRecordType::Program)) { - const auto meta_ver = installed.GetEntryVersion(update_tid); + if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { + const auto meta_ver = content_provider.GetEntryVersion(update_tid); if (meta_ver.value_or(0) == 0) { out.insert_or_assign(update_label, ""); } else { @@ -487,8 +482,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } // General Mods (LayeredFS and IPS) - const auto mod_dir = - Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); + const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id); if (mod_dir != nullptr && mod_dir->GetSize() > 0) { for (const auto& mod : mod_dir->GetSubdirectories()) { std::string types; @@ -532,13 +526,15 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } // DLC - const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); + const auto dlc_entries = + content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); std::vector<ContentProviderEntry> dlc_match; dlc_match.reserve(dlc_entries.size()); std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), - [this, &installed](const ContentProviderEntry& entry) { + [this](const ContentProviderEntry& entry) { return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && - installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; + content_provider.GetEntry(entry)->GetStatus() == + Loader::ResultStatus::Success; }); if (!dlc_match.empty()) { // Ensure sorted so DLC IDs show in order. @@ -559,19 +555,16 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u } std::optional<u32> PatchManager::GetGameVersion() const { - const auto& installed = Core::System::GetInstance().GetContentProvider(); const auto update_tid = GetUpdateTitleID(title_id); - if (installed.HasEntry(update_tid, ContentRecordType::Program)) { - return installed.GetEntryVersion(update_tid); + if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { + return content_provider.GetEntryVersion(update_tid); } - return installed.GetEntryVersion(title_id); + return content_provider.GetEntryVersion(title_id); } PatchManager::Metadata PatchManager::GetControlMetadata() const { - const auto& installed = Core::System::GetInstance().GetContentProvider(); - - const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control); + const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control); if (base_control_nca == nullptr) { return {}; } diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 1f28c6241..fb1853035 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -17,8 +17,13 @@ namespace Core { class System; } +namespace Service::FileSystem { +class FileSystemController; +} + namespace FileSys { +class ContentProvider; class NCA; class NACP; @@ -29,7 +34,9 @@ public: using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; using PatchVersionNames = std::map<std::string, std::string, std::less<>>; - explicit PatchManager(u64 title_id); + explicit PatchManager(u64 title_id_, + const Service::FileSystem::FileSystemController& fs_controller_, + const ContentProvider& content_provider_); ~PatchManager(); [[nodiscard]] u64 GetTitleID() const; @@ -50,7 +57,7 @@ public: // Creates a CheatList object with all [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList( - const Core::System& system, const BuildID& build_id) const; + const BuildID& build_id) const; // Currently tracked RomFS patches: // - Game Updates @@ -80,6 +87,8 @@ private: const std::string& build_id) const; u64 title_id; + const Service::FileSystem::FileSystemController& fs_controller; + const ContentProvider& content_provider; }; } // namespace FileSys diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index e967a254e..987199747 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp @@ -37,10 +37,12 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw) { } ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { - if (!updatable) + if (!updatable) { return MakeResult<VirtualFile>(file); + } - const PatchManager patch_manager(current_process_title_id); + const PatchManager patch_manager{current_process_title_id, filesystem_controller, + content_provider}; return MakeResult<VirtualFile>( patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw)); } diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index ba4efee3a..b7bfe0928 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp @@ -70,7 +70,8 @@ std::string SaveDataAttribute::DebugInfo() const { static_cast<u8>(rank), index); } -SaveDataFactory::SaveDataFactory(VirtualDir save_directory) : dir(std::move(save_directory)) { +SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_directory_) + : dir{std::move(save_directory_)}, system{system_} { // Delete all temporary storages // On hardware, it is expected that temporary storage be empty at first use. dir->DeleteSubdirectoryRecursive("temp"); @@ -83,7 +84,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space, PrintSaveDataAttributeWarnings(meta); const auto save_directory = - GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); + GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id); auto out = dir->CreateDirectoryRelative(save_directory); @@ -100,7 +101,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { const auto save_directory = - GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); + GetFullPath(system, space, meta.type, meta.title_id, meta.user_id, meta.save_id); auto out = dir->GetDirectoryRelative(save_directory); @@ -135,13 +136,14 @@ std::string SaveDataFactory::GetSaveDataSpaceIdPath(SaveDataSpaceId space) { } } -std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, - u128 user_id, u64 save_id) { +std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId space, + SaveDataType type, u64 title_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 // be interpreted as the title id of the current process. if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) { if (title_id == 0) { - title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID(); + title_id = system.CurrentProcess()->GetTitleID(); } } @@ -167,7 +169,7 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const { - const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0); + const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); const auto dir = GetOrCreateDirectoryRelative(this->dir, path); const auto size_file = dir->GetFile(SAVE_DATA_SIZE_FILENAME); @@ -182,7 +184,7 @@ SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id, void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, SaveDataSize new_value) const { - const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0); + const auto path = GetFullPath(system, SaveDataSpaceId::NandUser, type, title_id, user_id, 0); const auto dir = GetOrCreateDirectoryRelative(this->dir, path); const auto size_file = dir->CreateFile(SAVE_DATA_SIZE_FILENAME); diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index 6625bbbd8..17f774baa 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h @@ -12,6 +12,10 @@ #include "core/file_sys/vfs.h" #include "core/hle/result.h" +namespace Core { +class System; +} + namespace FileSys { enum class SaveDataSpaceId : u8 { @@ -84,7 +88,7 @@ struct SaveDataSize { /// File system interface to the SaveData archive class SaveDataFactory { public: - explicit SaveDataFactory(VirtualDir dir); + explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); ~SaveDataFactory(); ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; @@ -93,8 +97,8 @@ public: VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; static std::string GetSaveDataSpaceIdPath(SaveDataSpaceId space); - static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, - u128 user_id, u64 save_id); + static std::string GetFullPath(Core::System& system, SaveDataSpaceId space, SaveDataType type, + u64 title_id, u128 user_id, u64 save_id); SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const; void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, @@ -102,6 +106,7 @@ public: private: VirtualDir dir; + Core::System& system; }; } // namespace FileSys diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 90641d23b..c05735ddd 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp @@ -20,8 +20,8 @@ namespace FileSys { -NSP::NSP(VirtualFile file_) - : file(std::move(file_)), status{Loader::ResultStatus::Success}, +NSP::NSP(VirtualFile file_, std::size_t program_index) + : file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success}, pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { if (pfs->GetStatus() != Loader::ResultStatus::Success) { status = pfs->GetStatus(); @@ -146,7 +146,7 @@ std::shared_ptr<NCA> NSP::GetNCA(u64 title_id, ContentRecordType type, TitleType if (extracted) LOG_WARNING(Service_FS, "called on an NSP that is of type extracted."); - const auto title_id_iter = ncas.find(title_id); + const auto title_id_iter = ncas.find(title_id + program_index); if (title_id_iter == ncas.end()) return nullptr; diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index c70a11b5b..54581a6f3 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h @@ -27,7 +27,7 @@ enum class ContentRecordType : u8; class NSP : public ReadOnlyVfsDirectory { public: - explicit NSP(VirtualFile file); + explicit NSP(VirtualFile file, std::size_t program_index = 0); ~NSP() override; Loader::ResultStatus GetStatus() const; @@ -69,6 +69,8 @@ private: VirtualFile file; + const std::size_t program_index; + bool extracted = false; Loader::ResultStatus status; std::map<u64, Loader::ResultStatus> program_status; diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 3e8780243..276d2b906 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -102,8 +102,8 @@ public: float render_surface_scale = 1.0f; }; - /// Polls window events - virtual void PollEvents() = 0; + /// Called from GPU thread when a frame is displayed. + virtual void OnFrameDisplayed() {} /** * Returns a GraphicsContext that the frontend provides to be used for rendering. diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index 93251e3aa..de51a754e 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h @@ -30,10 +30,12 @@ public: virtual StatusType GetStatus() const { return {}; } - virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { + virtual bool GetAnalogDirectionStatus([[maybe_unused]] AnalogDirection direction) const { return {}; } - virtual bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const { + virtual bool SetRumblePlay([[maybe_unused]] f32 amp_low, [[maybe_unused]] f32 freq_low, + [[maybe_unused]] f32 amp_high, + [[maybe_unused]] f32 freq_high) const { return {}; } }; diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp deleted file mode 100644 index 97ee65464..000000000 --- a/src/core/gdbstub/gdbstub.cpp +++ /dev/null @@ -1,1397 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// Originally written by Sven Peter <sven@fail0verflow.com> for anergistic. - -#include <algorithm> -#include <atomic> -#include <climits> -#include <csignal> -#include <cstdarg> -#include <cstdio> -#include <cstring> -#include <map> -#include <numeric> -#include <fcntl.h> - -#ifdef _WIN32 -#include <winsock2.h> -// winsock2.h needs to be included first to prevent winsock.h being included by other includes -#include <io.h> -#include <iphlpapi.h> -#include <ws2tcpip.h> -#define SHUT_RDWR 2 -#else -#include <netinet/in.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#endif - -#include "common/logging/log.h" -#include "common/string_util.h" -#include "common/swap.h" -#include "core/arm/arm_interface.h" -#include "core/core.h" -#include "core/gdbstub/gdbstub.h" -#include "core/hle/kernel/memory/page_table.h" -#include "core/hle/kernel/process.h" -#include "core/hle/kernel/scheduler.h" -#include "core/loader/loader.h" -#include "core/memory.h" - -namespace GDBStub { -namespace { -constexpr int GDB_BUFFER_SIZE = 10000; - -constexpr char GDB_STUB_START = '$'; -constexpr char GDB_STUB_END = '#'; -constexpr char GDB_STUB_ACK = '+'; -constexpr char GDB_STUB_NACK = '-'; - -#ifndef SIGTRAP -constexpr u32 SIGTRAP = 5; -#endif - -#ifndef SIGTERM -constexpr u32 SIGTERM = 15; -#endif - -#ifndef MSG_WAITALL -constexpr u32 MSG_WAITALL = 8; -#endif - -constexpr u32 LR_REGISTER = 30; -constexpr u32 SP_REGISTER = 31; -constexpr u32 PC_REGISTER = 32; -constexpr u32 PSTATE_REGISTER = 33; -constexpr u32 UC_ARM64_REG_Q0 = 34; -constexpr u32 FPCR_REGISTER = 66; - -// For sample XML files see the GDB source /gdb/features -// GDB also wants the l character at the start -// This XML defines what the registers are for this specific ARM device -constexpr char target_xml[] = - R"(l<?xml version="1.0"?> -<!DOCTYPE target SYSTEM "gdb-target.dtd"> -<target version="1.0"> - <feature name="org.gnu.gdb.aarch64.core"> - <reg name="x0" bitsize="64"/> - <reg name="x1" bitsize="64"/> - <reg name="x2" bitsize="64"/> - <reg name="x3" bitsize="64"/> - <reg name="x4" bitsize="64"/> - <reg name="x5" bitsize="64"/> - <reg name="x6" bitsize="64"/> - <reg name="x7" bitsize="64"/> - <reg name="x8" bitsize="64"/> - <reg name="x9" bitsize="64"/> - <reg name="x10" bitsize="64"/> - <reg name="x11" bitsize="64"/> - <reg name="x12" bitsize="64"/> - <reg name="x13" bitsize="64"/> - <reg name="x14" bitsize="64"/> - <reg name="x15" bitsize="64"/> - <reg name="x16" bitsize="64"/> - <reg name="x17" bitsize="64"/> - <reg name="x18" bitsize="64"/> - <reg name="x19" bitsize="64"/> - <reg name="x20" bitsize="64"/> - <reg name="x21" bitsize="64"/> - <reg name="x22" bitsize="64"/> - <reg name="x23" bitsize="64"/> - <reg name="x24" bitsize="64"/> - <reg name="x25" bitsize="64"/> - <reg name="x26" bitsize="64"/> - <reg name="x27" bitsize="64"/> - <reg name="x28" bitsize="64"/> - <reg name="x29" bitsize="64"/> - <reg name="x30" bitsize="64"/> - <reg name="sp" bitsize="64" type="data_ptr"/> - - <reg name="pc" bitsize="64" type="code_ptr"/> - - <flags id="pstate_flags" size="4"> - <field name="SP" start="0" end="0"/> - <field name="" start="1" end="1"/> - <field name="EL" start="2" end="3"/> - <field name="nRW" start="4" end="4"/> - <field name="" start="5" end="5"/> - <field name="F" start="6" end="6"/> - <field name="I" start="7" end="7"/> - <field name="A" start="8" end="8"/> - <field name="D" start="9" end="9"/> - - <field name="IL" start="20" end="20"/> - <field name="SS" start="21" end="21"/> - - <field name="V" start="28" end="28"/> - <field name="C" start="29" end="29"/> - <field name="Z" start="30" end="30"/> - <field name="N" start="31" end="31"/> - </flags> - <reg name="pstate" bitsize="32" type="pstate_flags"/> - </feature> - <feature name="org.gnu.gdb.aarch64.fpu"> - </feature> -</target> -)"; - -int gdbserver_socket = -1; -bool defer_start = false; - -u8 command_buffer[GDB_BUFFER_SIZE]; -u32 command_length; - -u32 latest_signal = 0; -bool memory_break = false; - -Kernel::Thread* current_thread = nullptr; -u32 current_core = 0; - -// Binding to a port within the reserved ports range (0-1023) requires root permissions, -// so default to a port outside of that range. -u16 gdbstub_port = 24689; - -bool halt_loop = true; -bool step_loop = false; -bool send_trap = false; - -// If set to false, the server will never be started and no -// gdbstub-related functions will be executed. -std::atomic<bool> server_enabled(false); - -#ifdef _WIN32 -WSADATA InitData; -#endif - -struct Breakpoint { - bool active; - VAddr addr; - u64 len; - std::array<u8, 4> inst; -}; - -using BreakpointMap = std::map<VAddr, Breakpoint>; -BreakpointMap breakpoints_execute; -BreakpointMap breakpoints_read; -BreakpointMap breakpoints_write; - -struct Module { - std::string name; - VAddr beg; - VAddr end; -}; - -std::vector<Module> modules; -} // Anonymous namespace - -void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext) { - Module module; - if (add_elf_ext) { - Common::SplitPath(name, nullptr, &module.name, nullptr); - module.name += ".elf"; - } else { - module.name = std::move(name); - } - module.beg = beg; - module.end = end; - modules.push_back(std::move(module)); -} - -static Kernel::Thread* FindThreadById(s64 id) { - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (auto& thread : threads) { - if (thread->GetThreadID() == static_cast<u64>(id)) { - current_core = thread->GetProcessorID(); - return thread.get(); - } - } - return nullptr; -} - -static u64 RegRead(std::size_t id, Kernel::Thread* thread = nullptr) { - if (!thread) { - return 0; - } - - const auto& thread_context = thread->GetContext64(); - - if (id < SP_REGISTER) { - return thread_context.cpu_registers[id]; - } else if (id == SP_REGISTER) { - return thread_context.sp; - } else if (id == PC_REGISTER) { - return thread_context.pc; - } else if (id == PSTATE_REGISTER) { - return thread_context.pstate; - } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) { - return thread_context.vector_registers[id - UC_ARM64_REG_Q0][0]; - } else { - return 0; - } -} - -static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr) { - if (!thread) { - return; - } - - auto& thread_context = thread->GetContext64(); - - if (id < SP_REGISTER) { - thread_context.cpu_registers[id] = val; - } else if (id == SP_REGISTER) { - thread_context.sp = val; - } else if (id == PC_REGISTER) { - thread_context.pc = val; - } else if (id == PSTATE_REGISTER) { - thread_context.pstate = static_cast<u32>(val); - } else if (id > PSTATE_REGISTER && id < FPCR_REGISTER) { - thread_context.vector_registers[id - (PSTATE_REGISTER + 1)][0] = val; - } -} - -static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) { - if (!thread) { - return u128{0}; - } - - auto& thread_context = thread->GetContext64(); - - if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - return thread_context.vector_registers[id - UC_ARM64_REG_Q0]; - } else if (id == FPCR_REGISTER) { - return u128{thread_context.fpcr, 0}; - } else { - return u128{0}; - } -} - -static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr) { - if (!thread) { - return; - } - - auto& thread_context = thread->GetContext64(); - - if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val; - } else if (id == FPCR_REGISTER) { - thread_context.fpcr = static_cast<u32>(val[0]); - } -} - -/** - * Turns hex string character into the equivalent byte. - * - * @param hex Input hex character to be turned into byte. - */ -static u8 HexCharToValue(u8 hex) { - if (hex >= '0' && hex <= '9') { - return static_cast<u8>(hex - '0'); - } else if (hex >= 'a' && hex <= 'f') { - return static_cast<u8>(hex - 'a' + 0xA); - } else if (hex >= 'A' && hex <= 'F') { - return static_cast<u8>(hex - 'A' + 0xA); - } - - LOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex); - return 0; -} - -/** - * Turn nibble of byte into hex string character. - * - * @param n Nibble to be turned into hex character. - */ -static u8 NibbleToHex(u8 n) { - n &= 0xF; - if (n < 0xA) { - return static_cast<u8>('0' + n); - } else { - return static_cast<u8>('a' + n - 0xA); - } -} - -/** - * Converts input hex string characters into an array of equivalent of u8 bytes. - * - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static u32 HexToInt(const u8* src, std::size_t len) { - u32 output = 0; - while (len-- > 0) { - output = (output << 4) | HexCharToValue(src[0]); - src++; - } - return output; -} - -/** - * Converts input hex string characters into an array of equivalent of u8 bytes. - * - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static u64 HexToLong(const u8* src, std::size_t len) { - u64 output = 0; - while (len-- > 0) { - output = (output << 4) | HexCharToValue(src[0]); - src++; - } - return output; -} - -/** - * Converts input array of u8 bytes into their equivalent hex string characters. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param src Pointer to array of u8 bytes. - * @param len Length of src array. - */ -static void MemToGdbHex(u8* dest, const u8* src, std::size_t len) { - while (len-- > 0) { - const u8 tmp = *src++; - *dest++ = NibbleToHex(static_cast<u8>(tmp >> 4)); - *dest++ = NibbleToHex(tmp); - } -} - -/** - * Converts input gdb-formatted hex string characters into an array of equivalent of u8 bytes. - * - * @param dest Pointer to buffer to store u8 bytes. - * @param src Pointer to array of output hex string characters. - * @param len Length of src array. - */ -static void GdbHexToMem(u8* dest, const u8* src, std::size_t len) { - while (len-- > 0) { - *dest++ = static_cast<u8>((HexCharToValue(src[0]) << 4) | HexCharToValue(src[1])); - src += 2; - } -} - -/** - * Convert a u32 into a gdb-formatted hex string. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param v Value to convert. - */ -static void IntToGdbHex(u8* dest, u32 v) { - for (int i = 0; i < 8; i += 2) { - dest[i + 1] = NibbleToHex(static_cast<u8>(v >> (4 * i))); - dest[i] = NibbleToHex(static_cast<u8>(v >> (4 * (i + 1)))); - } -} - -/** - * Convert a u64 into a gdb-formatted hex string. - * - * @param dest Pointer to buffer to store output hex string characters. - * @param v Value to convert. - */ -static void LongToGdbHex(u8* dest, u64 v) { - for (int i = 0; i < 16; i += 2) { - dest[i + 1] = NibbleToHex(static_cast<u8>(v >> (4 * i))); - dest[i] = NibbleToHex(static_cast<u8>(v >> (4 * (i + 1)))); - } -} - -/** - * Convert a gdb-formatted hex string into a u32. - * - * @param src Pointer to hex string. - */ -static u32 GdbHexToInt(const u8* src) { - u32 output = 0; - - for (int i = 0; i < 8; i += 2) { - output = (output << 4) | HexCharToValue(src[7 - i - 1]); - output = (output << 4) | HexCharToValue(src[7 - i]); - } - - return output; -} - -/** - * Convert a gdb-formatted hex string into a u64. - * - * @param src Pointer to hex string. - */ -static u64 GdbHexToLong(const u8* src) { - u64 output = 0; - - for (int i = 0; i < 16; i += 2) { - output = (output << 4) | HexCharToValue(src[15 - i - 1]); - output = (output << 4) | HexCharToValue(src[15 - i]); - } - - return output; -} - -/** - * Convert a gdb-formatted hex string into a u128. - * - * @param src Pointer to hex string. - */ -static u128 GdbHexToU128(const u8* src) { - u128 output; - - for (int i = 0; i < 16; i += 2) { - output[0] = (output[0] << 4) | HexCharToValue(src[15 - i - 1]); - output[0] = (output[0] << 4) | HexCharToValue(src[15 - i]); - } - - for (int i = 0; i < 16; i += 2) { - output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i - 1]); - output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i]); - } - - return output; -} - -/// Read a byte from the gdb client. -static u8 ReadByte() { - u8 c; - std::size_t received_size = recv(gdbserver_socket, reinterpret_cast<char*>(&c), 1, MSG_WAITALL); - if (received_size != 1) { - LOG_ERROR(Debug_GDBStub, "recv failed: {}", received_size); - Shutdown(); - } - - return c; -} - -/// Calculate the checksum of the current command buffer. -static u8 CalculateChecksum(const u8* buffer, std::size_t length) { - return static_cast<u8>(std::accumulate(buffer, buffer + length, u8{0}, - [](u8 lhs, u8 rhs) { return u8(lhs + rhs); })); -} - -/** - * Get the map of breakpoints for a given breakpoint type. - * - * @param type Type of breakpoint map. - */ -static BreakpointMap& GetBreakpointMap(BreakpointType type) { - switch (type) { - case BreakpointType::Execute: - return breakpoints_execute; - case BreakpointType::Read: - return breakpoints_read; - case BreakpointType::Write: - return breakpoints_write; - default: - return breakpoints_read; - } -} - -/** - * Remove the breakpoint from the given address of the specified type. - * - * @param type Type of breakpoint. - * @param addr Address of breakpoint. - */ -static void RemoveBreakpoint(BreakpointType type, VAddr addr) { - BreakpointMap& p = GetBreakpointMap(type); - - const auto bp = p.find(addr); - if (bp == p.end()) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", - bp->second.len, bp->second.addr, static_cast<int>(type)); - - if (type == BreakpointType::Execute) { - auto& system = Core::System::GetInstance(); - system.Memory().WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); - system.InvalidateCpuInstructionCaches(); - } - p.erase(addr); -} - -BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, BreakpointType type) { - const BreakpointMap& p = GetBreakpointMap(type); - const auto next_breakpoint = p.lower_bound(addr); - BreakpointAddress breakpoint; - - if (next_breakpoint != p.end()) { - breakpoint.address = next_breakpoint->first; - breakpoint.type = type; - } else { - breakpoint.address = 0; - breakpoint.type = BreakpointType::None; - } - - return breakpoint; -} - -bool CheckBreakpoint(VAddr addr, BreakpointType type) { - if (!IsConnected()) { - return false; - } - - const BreakpointMap& p = GetBreakpointMap(type); - const auto bp = p.find(addr); - - if (bp == p.end()) { - return false; - } - - u64 len = bp->second.len; - - // IDA Pro defaults to 4-byte breakpoints for all non-hardware breakpoints - // no matter if it's a 4-byte or 2-byte instruction. When you execute a - // Thumb instruction with a 4-byte breakpoint set, it will set a breakpoint on - // two instructions instead of the single instruction you placed the breakpoint - // on. So, as a way to make sure that execution breakpoints are only breaking - // on the instruction that was specified, set the length of an execution - // breakpoint to 1. This should be fine since the CPU should never begin executing - // an instruction anywhere except the beginning of the instruction. - if (type == BreakpointType::Execute) { - len = 1; - } - - if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { - LOG_DEBUG(Debug_GDBStub, - "Found breakpoint type {} @ {:016X}, range: {:016X}" - " - {:016X} ({:X} bytes)", - static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len); - return true; - } - - return false; -} - -/** - * Send packet to gdb client. - * - * @param packet Packet to be sent to client. - */ -static void SendPacket(const char packet) { - std::size_t sent_size = send(gdbserver_socket, &packet, 1, 0); - if (sent_size != 1) { - LOG_ERROR(Debug_GDBStub, "send failed"); - } -} - -/** - * Send reply to gdb client. - * - * @param reply Reply to be sent to client. - */ -static void SendReply(const char* reply) { - if (!IsConnected()) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "Reply: {}", reply); - - memset(command_buffer, 0, sizeof(command_buffer)); - - command_length = static_cast<u32>(strlen(reply)); - if (command_length + 4 > sizeof(command_buffer)) { - LOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply"); - return; - } - - memcpy(command_buffer + 1, reply, command_length); - - const u8 checksum = CalculateChecksum(command_buffer, command_length + 1); - command_buffer[0] = GDB_STUB_START; - command_buffer[command_length + 1] = GDB_STUB_END; - command_buffer[command_length + 2] = NibbleToHex(static_cast<u8>(checksum >> 4)); - command_buffer[command_length + 3] = NibbleToHex(checksum); - - u8* ptr = command_buffer; - u32 left = command_length + 4; - while (left > 0) { - const auto sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0); - if (sent_size < 0) { - LOG_ERROR(Debug_GDBStub, "gdb: send failed"); - return Shutdown(); - } - - left -= static_cast<u32>(sent_size); - ptr += sent_size; - } -} - -/// Handle query command from gdb client. -static void HandleQuery() { - LOG_DEBUG(Debug_GDBStub, "gdb: query '{}'", command_buffer + 1); - - const char* query = reinterpret_cast<const char*>(command_buffer + 1); - - if (strcmp(query, "TStatus") == 0) { - SendReply("T0"); - } else if (strncmp(query, "Supported", strlen("Supported")) == 0) { - // PacketSize needs to be large enough for target xml - std::string buffer = "PacketSize=2000;qXfer:features:read+;qXfer:threads:read+"; - if (!modules.empty()) { - buffer += ";qXfer:libraries:read+"; - } - SendReply(buffer.c_str()); - } else if (strncmp(query, "Xfer:features:read:target.xml:", - strlen("Xfer:features:read:target.xml:")) == 0) { - SendReply(target_xml); - } else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) { - const VAddr base_address = - Core::System::GetInstance().CurrentProcess()->PageTable().GetCodeRegionStart(); - std::string buffer = fmt::format("TextSeg={:0x}", base_address); - SendReply(buffer.c_str()); - } else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) { - std::string val = "m"; - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (const auto& thread : threads) { - val += fmt::format("{:x},", thread->GetThreadID()); - } - val.pop_back(); - SendReply(val.c_str()); - } else if (strncmp(query, "sThreadInfo", strlen("sThreadInfo")) == 0) { - SendReply("l"); - } else if (strncmp(query, "Xfer:threads:read", strlen("Xfer:threads:read")) == 0) { - std::string buffer; - buffer += "l<?xml version=\"1.0\"?>"; - buffer += "<threads>"; - const auto& threads = Core::System::GetInstance().GlobalScheduler().GetThreadList(); - for (const auto& thread : threads) { - buffer += - fmt::format(R"*(<thread id="{:x}" core="{:d}" name="Thread {:x}"></thread>)*", - thread->GetThreadID(), thread->GetProcessorID(), thread->GetThreadID()); - } - buffer += "</threads>"; - SendReply(buffer.c_str()); - } else if (strncmp(query, "Xfer:libraries:read", strlen("Xfer:libraries:read")) == 0) { - std::string buffer; - buffer += "l<?xml version=\"1.0\"?>"; - buffer += "<library-list>"; - for (const auto& module : modules) { - buffer += - fmt::format(R"*("<library name = "{}"><segment address = "0x{:x}"/></library>)*", - module.name, module.beg); - } - buffer += "</library-list>"; - SendReply(buffer.c_str()); - } else { - SendReply(""); - } -} - -/// Handle set thread command from gdb client. -static void HandleSetThread() { - int thread_id = -1; - if (command_buffer[2] != '-') { - thread_id = static_cast<int>(HexToInt(command_buffer + 2, command_length - 2)); - } - if (thread_id >= 1) { - current_thread = FindThreadById(thread_id); - } - if (!current_thread) { - thread_id = 1; - current_thread = FindThreadById(thread_id); - } - if (current_thread) { - SendReply("OK"); - return; - } - SendReply("E01"); -} - -/// Handle thread alive command from gdb client. -static void HandleThreadAlive() { - int thread_id = static_cast<int>(HexToInt(command_buffer + 1, command_length - 1)); - if (thread_id == 0) { - thread_id = 1; - } - if (FindThreadById(thread_id)) { - SendReply("OK"); - return; - } - SendReply("E01"); -} - -/** - * Send signal packet to client. - * - * @param signal Signal to be sent to client. - */ -static void SendSignal(Kernel::Thread* thread, u32 signal, bool full = true) { - if (gdbserver_socket == -1) { - return; - } - - latest_signal = signal; - - if (!thread) { - full = false; - } - - std::string buffer; - if (full) { - buffer = fmt::format("T{:02x}{:02x}:{:016x};{:02x}:{:016x};{:02x}:{:016x}", latest_signal, - PC_REGISTER, Common::swap64(RegRead(PC_REGISTER, thread)), SP_REGISTER, - Common::swap64(RegRead(SP_REGISTER, thread)), LR_REGISTER, - Common::swap64(RegRead(LR_REGISTER, thread))); - } else { - buffer = fmt::format("T{:02x}", latest_signal); - } - - if (thread) { - buffer += fmt::format(";thread:{:x};", thread->GetThreadID()); - } - - SendReply(buffer.c_str()); -} - -/// Read command from gdb client. -static void ReadCommand() { - command_length = 0; - memset(command_buffer, 0, sizeof(command_buffer)); - - u8 c = ReadByte(); - if (c == '+') { - // ignore ack - return; - } else if (c == 0x03) { - LOG_INFO(Debug_GDBStub, "gdb: found break command"); - halt_loop = true; - SendSignal(current_thread, SIGTRAP); - return; - } else if (c != GDB_STUB_START) { - LOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c); - return; - } - - while ((c = ReadByte()) != GDB_STUB_END) { - if (command_length >= sizeof(command_buffer)) { - LOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow"); - SendPacket(GDB_STUB_NACK); - return; - } - command_buffer[command_length++] = c; - } - - auto checksum_received = static_cast<u32>(HexCharToValue(ReadByte()) << 4); - checksum_received |= static_cast<u32>(HexCharToValue(ReadByte())); - - const u32 checksum_calculated = CalculateChecksum(command_buffer, command_length); - - if (checksum_received != checksum_calculated) { - LOG_ERROR(Debug_GDBStub, - "gdb: invalid checksum: calculated {:02X} and read {:02X} for ${}# (length: {})", - checksum_calculated, checksum_received, command_buffer, command_length); - - command_length = 0; - - SendPacket(GDB_STUB_NACK); - return; - } - - SendPacket(GDB_STUB_ACK); -} - -/// Check if there is data to be read from the gdb client. -static bool IsDataAvailable() { - if (!IsConnected()) { - return false; - } - - fd_set fd_socket; - - FD_ZERO(&fd_socket); - FD_SET(static_cast<u32>(gdbserver_socket), &fd_socket); - - struct timeval t; - t.tv_sec = 0; - t.tv_usec = 0; - - if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) { - LOG_ERROR(Debug_GDBStub, "select failed"); - return false; - } - - return FD_ISSET(gdbserver_socket, &fd_socket) != 0; -} - -/// Send requested register to gdb client. -static void ReadRegister() { - static u8 reply[64]; - memset(reply, 0, sizeof(reply)); - - u32 id = HexCharToValue(command_buffer[1]); - if (command_buffer[2] != '\0') { - id <<= 4; - id |= HexCharToValue(command_buffer[2]); - } - - if (id <= SP_REGISTER) { - LongToGdbHex(reply, RegRead(id, current_thread)); - } else if (id == PC_REGISTER) { - LongToGdbHex(reply, RegRead(id, current_thread)); - } else if (id == PSTATE_REGISTER) { - IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread))); - } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - u128 r = FpuRead(id, current_thread); - LongToGdbHex(reply, r[0]); - LongToGdbHex(reply + 16, r[1]); - } else if (id == FPCR_REGISTER) { - u128 r = FpuRead(id, current_thread); - IntToGdbHex(reply, static_cast<u32>(r[0])); - } else if (id == FPCR_REGISTER + 1) { - u128 r = FpuRead(id, current_thread); - IntToGdbHex(reply, static_cast<u32>(r[0] >> 32)); - } - - SendReply(reinterpret_cast<char*>(reply)); -} - -/// Send all registers to the gdb client. -static void ReadRegisters() { - static u8 buffer[GDB_BUFFER_SIZE - 4]; - memset(buffer, 0, sizeof(buffer)); - - u8* bufptr = buffer; - - for (u32 reg = 0; reg <= SP_REGISTER; reg++) { - LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread)); - } - - bufptr += 32 * 16; - - LongToGdbHex(bufptr, RegRead(PC_REGISTER, current_thread)); - - bufptr += 16; - - IntToGdbHex(bufptr, static_cast<u32>(RegRead(PSTATE_REGISTER, current_thread))); - - bufptr += 8; - - u128 r; - - for (u32 reg = UC_ARM64_REG_Q0; reg < FPCR_REGISTER; reg++) { - r = FpuRead(reg, current_thread); - LongToGdbHex(bufptr + reg * 32, r[0]); - LongToGdbHex(bufptr + reg * 32 + 16, r[1]); - } - - bufptr += 32 * 32; - - r = FpuRead(FPCR_REGISTER, current_thread); - IntToGdbHex(bufptr, static_cast<u32>(r[0])); - - bufptr += 8; - - SendReply(reinterpret_cast<char*>(buffer)); -} - -/// Modify data of register specified by gdb client. -static void WriteRegister() { - const u8* buffer_ptr = command_buffer + 3; - - u32 id = HexCharToValue(command_buffer[1]); - if (command_buffer[2] != '=') { - ++buffer_ptr; - id <<= 4; - id |= HexCharToValue(command_buffer[2]); - } - - if (id <= SP_REGISTER) { - RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); - } else if (id == PC_REGISTER) { - RegWrite(id, GdbHexToLong(buffer_ptr), current_thread); - } else if (id == PSTATE_REGISTER) { - RegWrite(id, GdbHexToInt(buffer_ptr), current_thread); - } else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) { - FpuWrite(id, GdbHexToU128(buffer_ptr), current_thread); - } else if (id == FPCR_REGISTER) { - } else if (id == FPCR_REGISTER + 1) { - } - - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - - SendReply("OK"); -} - -/// Modify all registers with data received from the client. -static void WriteRegisters() { - const u8* buffer_ptr = command_buffer + 1; - - if (command_buffer[0] != 'G') - return SendReply("E01"); - - for (u32 i = 0, reg = 0; reg <= FPCR_REGISTER; i++, reg++) { - if (reg <= SP_REGISTER) { - RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == PC_REGISTER) { - RegWrite(PC_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == PSTATE_REGISTER) { - RegWrite(PSTATE_REGISTER, GdbHexToInt(buffer_ptr + i * 16), current_thread); - } else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) { - RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == FPCR_REGISTER) { - RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } else if (reg == FPCR_REGISTER + 1) { - RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread); - } - } - - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - - SendReply("OK"); -} - -/// Read location in memory specified by gdb client. -static void ReadMemory() { - static u8 reply[GDB_BUFFER_SIZE - 4]; - - auto start_offset = command_buffer + 1; - const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - const u64 len = - HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); - - LOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len); - - if (len * 2 > sizeof(reply)) { - SendReply("E01"); - } - - auto& memory = Core::System::GetInstance().Memory(); - if (!memory.IsValidVirtualAddress(addr)) { - return SendReply("E00"); - } - - std::vector<u8> data(len); - memory.ReadBlock(addr, data.data(), len); - - MemToGdbHex(reply, data.data(), len); - reply[len * 2] = '\0'; - SendReply(reinterpret_cast<char*>(reply)); -} - -/// Modify location in memory with data received from the gdb client. -static void WriteMemory() { - auto start_offset = command_buffer + 1; - const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - const auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); - const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); - - auto& system = Core::System::GetInstance(); - auto& memory = system.Memory(); - if (!memory.IsValidVirtualAddress(addr)) { - return SendReply("E00"); - } - - std::vector<u8> data(len); - GdbHexToMem(data.data(), len_pos + 1, len); - memory.WriteBlock(addr, data.data(), len); - system.InvalidateCpuInstructionCaches(); - SendReply("OK"); -} - -void Break(bool is_memory_break) { - send_trap = true; - - memory_break = is_memory_break; -} - -/// Tell the CPU that it should perform a single step. -static void Step() { - if (command_length > 1) { - RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread); - // Update ARM context, skipping scheduler - no running threads at this point - Core::System::GetInstance() - .ArmInterface(current_core) - .LoadContext(current_thread->GetContext64()); - } - step_loop = true; - halt_loop = true; - send_trap = true; - Core::System::GetInstance().InvalidateCpuInstructionCaches(); -} - -/// Tell the CPU if we hit a memory breakpoint. -bool IsMemoryBreak() { - if (!IsConnected()) { - return false; - } - - return memory_break; -} - -/// Tell the CPU to continue executing. -static void Continue() { - memory_break = false; - step_loop = false; - halt_loop = false; - Core::System::GetInstance().InvalidateCpuInstructionCaches(); -} - -/** - * Commit breakpoint to list of breakpoints. - * - * @param type Type of breakpoint. - * @param addr Address of breakpoint. - * @param len Length of breakpoint. - */ -static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { - BreakpointMap& p = GetBreakpointMap(type); - - Breakpoint breakpoint; - breakpoint.active = true; - breakpoint.addr = addr; - breakpoint.len = len; - - auto& system = Core::System::GetInstance(); - auto& memory = system.Memory(); - memory.ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); - - static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4}; - if (type == BreakpointType::Execute) { - memory.WriteBlock(addr, btrap.data(), btrap.size()); - system.InvalidateCpuInstructionCaches(); - } - p.insert({addr, breakpoint}); - - LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", - static_cast<int>(type), breakpoint.len, breakpoint.addr); - - return true; -} - -/// Handle add breakpoint command from gdb client. -static void AddBreakpoint() { - BreakpointType type; - - u8 type_id = HexCharToValue(command_buffer[1]); - switch (type_id) { - case 0: - case 1: - type = BreakpointType::Execute; - break; - case 2: - type = BreakpointType::Write; - break; - case 3: - type = BreakpointType::Read; - break; - case 4: - type = BreakpointType::Access; - break; - default: - return SendReply("E01"); - } - - auto start_offset = command_buffer + 3; - auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); - - start_offset = addr_pos + 1; - u64 len = - HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); - - if (type == BreakpointType::Access) { - // Access is made up of Read and Write types, so add both breakpoints - type = BreakpointType::Read; - - if (!CommitBreakpoint(type, addr, len)) { - return SendReply("E02"); - } - - type = BreakpointType::Write; - } - - if (!CommitBreakpoint(type, addr, len)) { - return SendReply("E02"); - } - - SendReply("OK"); -} - -/// Handle remove breakpoint command from gdb client. -static void RemoveBreakpoint() { - BreakpointType type; - - u8 type_id = HexCharToValue(command_buffer[1]); - switch (type_id) { - case 0: - case 1: - type = BreakpointType::Execute; - break; - case 2: - type = BreakpointType::Write; - break; - case 3: - type = BreakpointType::Read; - break; - case 4: - type = BreakpointType::Access; - break; - default: - return SendReply("E01"); - } - - auto start_offset = command_buffer + 3; - auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); - VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); - - if (type == BreakpointType::Access) { - // Access is made up of Read and Write types, so add both breakpoints - type = BreakpointType::Read; - RemoveBreakpoint(type, addr); - - type = BreakpointType::Write; - } - - RemoveBreakpoint(type, addr); - SendReply("OK"); -} - -void HandlePacket() { - if (!IsConnected()) { - if (defer_start) { - ToggleServer(true); - } - return; - } - - if (!IsDataAvailable()) { - return; - } - - ReadCommand(); - if (command_length == 0) { - return; - } - - LOG_DEBUG(Debug_GDBStub, "Packet: {}", command_buffer); - - switch (command_buffer[0]) { - case 'q': - HandleQuery(); - break; - case 'H': - HandleSetThread(); - break; - case '?': - SendSignal(current_thread, latest_signal); - break; - case 'k': - Shutdown(); - LOG_INFO(Debug_GDBStub, "killed by gdb"); - return; - case 'g': - ReadRegisters(); - break; - case 'G': - WriteRegisters(); - break; - case 'p': - ReadRegister(); - break; - case 'P': - WriteRegister(); - break; - case 'm': - ReadMemory(); - break; - case 'M': - WriteMemory(); - break; - case 's': - Step(); - return; - case 'C': - case 'c': - Continue(); - return; - case 'z': - RemoveBreakpoint(); - break; - case 'Z': - AddBreakpoint(); - break; - case 'T': - HandleThreadAlive(); - break; - default: - SendReply(""); - break; - } -} - -void SetServerPort(u16 port) { - gdbstub_port = port; -} - -void ToggleServer(bool status) { - if (status) { - server_enabled = status; - - // Start server - if (!IsConnected() && Core::System::GetInstance().IsPoweredOn()) { - Init(); - } - } else { - // Stop server - if (IsConnected()) { - Shutdown(); - } - - server_enabled = status; - } -} - -void DeferStart() { - defer_start = true; -} - -static void Init(u16 port) { - if (!server_enabled) { - // Set the halt loop to false in case the user enabled the gdbstub mid-execution. - // This way the CPU can still execute normally. - halt_loop = false; - step_loop = false; - return; - } - - // Setup initial gdbstub status - halt_loop = true; - step_loop = false; - - breakpoints_execute.clear(); - breakpoints_read.clear(); - breakpoints_write.clear(); - - modules.clear(); - - // Start gdb server - LOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port); - - sockaddr_in saddr_server = {}; - saddr_server.sin_family = AF_INET; - saddr_server.sin_port = htons(port); - saddr_server.sin_addr.s_addr = INADDR_ANY; - -#ifdef _WIN32 - WSAStartup(MAKEWORD(2, 2), &InitData); -#endif - - int tmpsock = static_cast<int>(socket(PF_INET, SOCK_STREAM, 0)); - if (tmpsock == -1) { - LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); - } - - // Set socket to SO_REUSEADDR so it can always bind on the same port - int reuse_enabled = 1; - if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, - sizeof(reuse_enabled)) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); - } - - const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server); - socklen_t server_addrlen = sizeof(saddr_server); - if (bind(tmpsock, server_addr, server_addrlen) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket"); - } - - if (listen(tmpsock, 1) < 0) { - LOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket"); - } - - // Wait for gdb to connect - LOG_INFO(Debug_GDBStub, "Waiting for gdb to connect..."); - sockaddr_in saddr_client; - sockaddr* client_addr = reinterpret_cast<sockaddr*>(&saddr_client); - socklen_t client_addrlen = sizeof(saddr_client); - gdbserver_socket = static_cast<int>(accept(tmpsock, client_addr, &client_addrlen)); - if (gdbserver_socket < 0) { - // In the case that we couldn't start the server for whatever reason, just start CPU - // execution like normal. - halt_loop = false; - step_loop = false; - - LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); - } else { - LOG_INFO(Debug_GDBStub, "Client connected."); - saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); - } - - // Clean up temporary socket if it's still alive at this point. - if (tmpsock != -1) { - shutdown(tmpsock, SHUT_RDWR); - } -} - -void Init() { - Init(gdbstub_port); -} - -void Shutdown() { - if (!server_enabled) { - return; - } - defer_start = false; - - LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); - if (gdbserver_socket != -1) { - shutdown(gdbserver_socket, SHUT_RDWR); - gdbserver_socket = -1; - } - -#ifdef _WIN32 - WSACleanup(); -#endif - - LOG_INFO(Debug_GDBStub, "GDB stopped."); -} - -bool IsServerEnabled() { - return server_enabled; -} - -bool IsConnected() { - return IsServerEnabled() && gdbserver_socket != -1; -} - -bool GetCpuHaltFlag() { - return halt_loop; -} - -bool GetCpuStepFlag() { - return step_loop; -} - -void SetCpuStepFlag(bool is_step) { - step_loop = is_step; -} - -void SendTrap(Kernel::Thread* thread, int trap) { - if (!send_trap) { - return; - } - - current_thread = thread; - SendSignal(thread, trap); - - halt_loop = true; - send_trap = false; -} -}; // namespace GDBStub diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h deleted file mode 100644 index 8fe3c320b..000000000 --- a/src/core/gdbstub/gdbstub.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// Originally written by Sven Peter <sven@fail0verflow.com> for anergistic. - -#pragma once - -#include <string> -#include "common/common_types.h" -#include "core/hle/kernel/thread.h" - -namespace GDBStub { - -/// Breakpoint Method -enum class BreakpointType { - None, ///< None - Execute, ///< Execution Breakpoint - Read, ///< Read Breakpoint - Write, ///< Write Breakpoint - Access ///< Access (R/W) Breakpoint -}; - -struct BreakpointAddress { - VAddr address; - BreakpointType type; -}; - -/** - * Set the port the gdbstub should use to listen for connections. - * - * @param port Port to listen for connection - */ -void SetServerPort(u16 port); - -/** - * Starts or stops the server if possible. - * - * @param status Set the server to enabled or disabled. - */ -void ToggleServer(bool status); - -/// Start the gdbstub server. -void Init(); - -/** - * Defer initialization of the gdbstub to the first packet processing functions. - * This avoids a case where the gdbstub thread is frozen after initialization - * and fails to respond in time to packets. - */ -void DeferStart(); - -/// Stop gdbstub server. -void Shutdown(); - -/// Checks if the gdbstub server is enabled. -bool IsServerEnabled(); - -/// Returns true if there is an active socket connection. -bool IsConnected(); - -/// Register module. -void RegisterModule(std::string name, VAddr beg, VAddr end, bool add_elf_ext = true); - -/** - * Signal to the gdbstub server that it should halt CPU execution. - * - * @param is_memory_break If true, the break resulted from a memory breakpoint. - */ -void Break(bool is_memory_break = false); - -/// Determine if there was a memory breakpoint. -bool IsMemoryBreak(); - -/// Read and handle packet from gdb client. -void HandlePacket(); - -/** - * Get the nearest breakpoint of the specified type at the given address. - * - * @param addr Address to search from. - * @param type Type of breakpoint. - */ -BreakpointAddress GetNextBreakpointFromAddress(VAddr addr, GDBStub::BreakpointType type); - -/** - * Check if a breakpoint of the specified type exists at the given address. - * - * @param addr Address of breakpoint. - * @param type Type of breakpoint. - */ -bool CheckBreakpoint(VAddr addr, GDBStub::BreakpointType type); - -/// If set to true, the CPU will halt at the beginning of the next CPU loop. -bool GetCpuHaltFlag(); - -/// If set to true and the CPU is halted, the CPU will step one instruction. -bool GetCpuStepFlag(); - -/** - * When set to true, the CPU will step one instruction when the CPU is halted next. - * - * @param is_step - */ -void SetCpuStepFlag(bool is_step); - -/** - * Send trap signal from thread back to the gdbstub server. - * - * @param thread Sending thread. - * @param trap Trap no. - */ -void SendTrap(Kernel::Thread* thread, int trap); -} // namespace GDBStub diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bafd1ced7..e3b770d66 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -681,7 +681,7 @@ static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { } /// Used to output a message on a debug hardware unit - does nothing on a retail unit -static void OutputDebugString([[maybe_unused]] Core::System& system, VAddr address, u64 len) { +static void OutputDebugString(Core::System& system, VAddr address, u64 len) { if (len == 0) { return; } diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index ded52ea0b..6981f8ee7 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -47,8 +47,8 @@ static constexpr u32 SanitizeJPEGSize(std::size_t size) { class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { public: - explicit IManagerForSystemService(Common::UUID user_id) - : ServiceFramework("IManagerForSystemService") { + explicit IManagerForSystemService(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IManagerForSystemService"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CheckAvailability"}, @@ -83,8 +83,8 @@ public: // 3.0.0+ class IFloatingRegistrationRequest final : public ServiceFramework<IFloatingRegistrationRequest> { public: - explicit IFloatingRegistrationRequest(Common::UUID user_id) - : ServiceFramework("IFloatingRegistrationRequest") { + explicit IFloatingRegistrationRequest(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IFloatingRegistrationRequest"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSessionId"}, @@ -108,7 +108,8 @@ public: class IAdministrator final : public ServiceFramework<IAdministrator> { public: - explicit IAdministrator(Common::UUID user_id) : ServiceFramework("IAdministrator") { + explicit IAdministrator(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IAdministrator"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CheckAvailability"}, @@ -165,8 +166,8 @@ public: class IAuthorizationRequest final : public ServiceFramework<IAuthorizationRequest> { public: - explicit IAuthorizationRequest(Common::UUID user_id) - : ServiceFramework("IAuthorizationRequest") { + explicit IAuthorizationRequest(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IAuthorizationRequest"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSessionId"}, @@ -184,7 +185,8 @@ public: class IOAuthProcedure final : public ServiceFramework<IOAuthProcedure> { public: - explicit IOAuthProcedure(Common::UUID user_id) : ServiceFramework("IOAuthProcedure") { + explicit IOAuthProcedure(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IOAuthProcedure"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "PrepareAsync"}, @@ -202,8 +204,8 @@ public: // 3.0.0+ class IOAuthProcedureForExternalNsa final : public ServiceFramework<IOAuthProcedureForExternalNsa> { public: - explicit IOAuthProcedureForExternalNsa(Common::UUID user_id) - : ServiceFramework("IOAuthProcedureForExternalNsa") { + explicit IOAuthProcedureForExternalNsa(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IOAuthProcedureForExternalNsa"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "PrepareAsync"}, @@ -225,8 +227,8 @@ public: class IOAuthProcedureForNintendoAccountLinkage final : public ServiceFramework<IOAuthProcedureForNintendoAccountLinkage> { public: - explicit IOAuthProcedureForNintendoAccountLinkage(Common::UUID user_id) - : ServiceFramework("IOAuthProcedureForNintendoAccountLinkage") { + explicit IOAuthProcedureForNintendoAccountLinkage(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IOAuthProcedureForNintendoAccountLinkage"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "PrepareAsync"}, @@ -246,7 +248,8 @@ public: class INotifier final : public ServiceFramework<INotifier> { public: - explicit INotifier(Common::UUID user_id) : ServiceFramework("INotifier") { + explicit INotifier(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "INotifier"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSystemEvent"}, @@ -259,9 +262,9 @@ public: class IProfileCommon : public ServiceFramework<IProfileCommon> { public: - explicit IProfileCommon(const char* name, bool editor_commands, Common::UUID user_id, - ProfileManager& profile_manager) - : ServiceFramework(name), profile_manager(profile_manager), user_id(user_id) { + explicit IProfileCommon(Core::System& system_, const char* name, bool editor_commands, + Common::UUID user_id_, ProfileManager& profile_manager_) + : ServiceFramework{system_, name}, profile_manager{profile_manager_}, user_id{user_id_} { static const FunctionInfo functions[] = { {0, &IProfileCommon::Get, "Get"}, {1, &IProfileCommon::GetBase, "GetBase"}, @@ -427,19 +430,21 @@ protected: class IProfile final : public IProfileCommon { public: - IProfile(Common::UUID user_id, ProfileManager& profile_manager) - : IProfileCommon("IProfile", false, user_id, profile_manager) {} + explicit IProfile(Core::System& system_, Common::UUID user_id_, + ProfileManager& profile_manager_) + : IProfileCommon{system_, "IProfile", false, user_id_, profile_manager_} {} }; class IProfileEditor final : public IProfileCommon { public: - IProfileEditor(Common::UUID user_id, ProfileManager& profile_manager) - : IProfileCommon("IProfileEditor", true, user_id, profile_manager) {} + explicit IProfileEditor(Core::System& system_, Common::UUID user_id_, + ProfileManager& profile_manager_) + : IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {} }; class IAsyncContext final : public ServiceFramework<IAsyncContext> { public: - explicit IAsyncContext(Common::UUID user_id) : ServiceFramework("IAsyncContext") { + explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSystemEvent"}, @@ -455,7 +460,8 @@ public: class ISessionObject final : public ServiceFramework<ISessionObject> { public: - explicit ISessionObject(Common::UUID user_id) : ServiceFramework("ISessionObject") { + explicit ISessionObject(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "ISessionObject"} { // clang-format off static const FunctionInfo functions[] = { {999, nullptr, "Dummy"}, @@ -468,7 +474,8 @@ public: class IGuestLoginRequest final : public ServiceFramework<IGuestLoginRequest> { public: - explicit IGuestLoginRequest(Common::UUID) : ServiceFramework("IGuestLoginRequest") { + explicit IGuestLoginRequest(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IGuestLoginRequest"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSessionId"}, @@ -487,8 +494,8 @@ public: class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { public: - explicit IManagerForApplication(Common::UUID user_id) - : ServiceFramework("IManagerForApplication"), user_id(user_id) { + explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_) + : ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} { // clang-format off static const FunctionInfo functions[] = { {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, @@ -534,8 +541,8 @@ private: class IAsyncNetworkServiceLicenseKindContext final : public ServiceFramework<IAsyncNetworkServiceLicenseKindContext> { public: - explicit IAsyncNetworkServiceLicenseKindContext(Common::UUID user_id) - : ServiceFramework("IAsyncNetworkServiceLicenseKindContext") { + explicit IAsyncNetworkServiceLicenseKindContext(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IAsyncNetworkServiceLicenseKindContext"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetSystemEvent"}, @@ -554,8 +561,8 @@ public: class IOAuthProcedureForUserRegistration final : public ServiceFramework<IOAuthProcedureForUserRegistration> { public: - explicit IOAuthProcedureForUserRegistration(Common::UUID user_id) - : ServiceFramework("IOAuthProcedureForUserRegistration") { + explicit IOAuthProcedureForUserRegistration(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IOAuthProcedureForUserRegistration"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "PrepareAsync"}, @@ -578,7 +585,7 @@ public: class DAUTH_O final : public ServiceFramework<DAUTH_O> { public: - explicit DAUTH_O(Common::UUID) : ServiceFramework("dauth:o") { + explicit DAUTH_O(Core::System& system_, Common::UUID) : ServiceFramework{system_, "dauth:o"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, // [5.0.0-5.1.0] GeneratePostData @@ -597,7 +604,8 @@ public: // 6.0.0+ class IAsyncResult final : public ServiceFramework<IAsyncResult> { public: - explicit IAsyncResult(Common::UUID user_id) : ServiceFramework("IAsyncResult") { + explicit IAsyncResult(Core::System& system_, Common::UUID) + : ServiceFramework{system_, "IAsyncResult"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetResult"}, @@ -656,7 +664,7 @@ void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IProfile>(user_id, *profile_manager); + rb.PushIpcInterface<IProfile>(system, user_id, *profile_manager); } void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx) { @@ -731,7 +739,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IManagerForApplication>(profile_manager->GetLastOpenedUser()); + rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser()); } void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { @@ -742,8 +750,10 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx bool is_locked = false; if (res != Loader::ResultStatus::Success) { - FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; - auto nacp_unique = pm.GetControlMetadata().first; + const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(), + system.GetFileSystemController(), + system.GetContentProvider()}; + const auto nacp_unique = pm.GetControlMetadata().first; if (nacp_unique != nullptr) { is_locked = nacp_unique->GetUserAccountSwitchLock(); @@ -767,7 +777,7 @@ void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IProfileEditor>(user_id, *profile_manager); + rb.PushIpcInterface<IProfileEditor>(system, user_id, *profile_manager); } void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) { @@ -789,7 +799,7 @@ void Module::Interface::LoadOpenContext(Kernel::HLERequestContext& ctx) { // TODO: Find the differences between this and GetBaasAccountManagerForApplication IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IManagerForApplication>(profile_manager->GetLastOpenedUser()); + rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser()); } void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) { @@ -825,11 +835,11 @@ void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContex rb.PushRaw<u128>(profile_manager->GetUser(0)->uuid); } -Module::Interface::Interface(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager, Core::System& system, - const char* name) - : ServiceFramework(name), module(std::move(module)), - profile_manager(std::move(profile_manager)), system(system) {} +Module::Interface::Interface(std::shared_ptr<Module> module_, + std::shared_ptr<ProfileManager> profile_manager_, + Core::System& system_, const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)}, profile_manager{std::move( + profile_manager_)} {} Module::Interface::~Interface() = default; diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index c611efd89..ab8edc049 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -15,8 +15,8 @@ class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager, Core::System& system, + explicit Interface(std::shared_ptr<Module> module_, + std::shared_ptr<ProfileManager> profile_manager_, Core::System& system_, const char* name); ~Interface() override; @@ -60,7 +60,6 @@ public: protected: std::shared_ptr<Module> module; std::shared_ptr<ProfileManager> profile_manager; - Core::System& system; }; }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index eb097738a..38d877f6e 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -64,7 +64,7 @@ struct LaunchParameterAccountPreselectedUser { static_assert(sizeof(LaunchParameterAccountPreselectedUser) == 0x88); IWindowController::IWindowController(Core::System& system_) - : ServiceFramework("IWindowController"), system{system_} { + : ServiceFramework{system_, "IWindowController"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateWindow"}, @@ -99,7 +99,8 @@ void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) rb.Push(RESULT_SUCCESS); } -IAudioController::IAudioController() : ServiceFramework("IAudioController") { +IAudioController::IAudioController(Core::System& system_) + : ServiceFramework{system_, "IAudioController"} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioController::SetExpectedMasterVolume, "SetExpectedMasterVolume"}, @@ -180,7 +181,8 @@ void IAudioController::SetTransparentAudioRate(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") { +IDisplayController::IDisplayController(Core::System& system_) + : ServiceFramework{system_, "IDisplayController"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetLastForegroundCaptureImage"}, @@ -219,7 +221,8 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController" IDisplayController::~IDisplayController() = default; -IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { +IDebugFunctions::IDebugFunctions(Core::System& system_) + : ServiceFramework{system_, "IDebugFunctions"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, @@ -246,9 +249,8 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { IDebugFunctions::~IDebugFunctions() = default; -ISelfController::ISelfController(Core::System& system, - std::shared_ptr<NVFlinger::NVFlinger> nvflinger) - : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) { +ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_) + : ServiceFramework{system_, "ISelfController"}, nvflinger{nvflinger_} { // clang-format off static const FunctionInfo functions[] = { {0, &ISelfController::Exit, "Exit"}, @@ -458,8 +460,8 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) // TODO(Subv): Find out how AM determines the display to use, for now just // create the layer in the Default display. - const auto display_id = nvflinger->OpenDisplay("Default"); - const auto layer_id = nvflinger->CreateLayer(*display_id); + const auto display_id = nvflinger.OpenDisplay("Default"); + const auto layer_id = nvflinger.CreateLayer(*display_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -476,8 +478,8 @@ void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestConte // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse // side effects. // TODO: Support multiple layers - const auto display_id = nvflinger->OpenDisplay("Default"); - const auto layer_id = nvflinger->CreateLayer(*display_id); + const auto display_id = nvflinger.OpenDisplay("Default"); + const auto layer_id = nvflinger.CreateLayer(*display_id); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -606,9 +608,9 @@ void AppletMessageQueue::RequestExit() { PushMessage(AppletMessage::ExitRequested); } -ICommonStateGetter::ICommonStateGetter(Core::System& system, - std::shared_ptr<AppletMessageQueue> msg_queue) - : ServiceFramework("ICommonStateGetter"), system(system), msg_queue(std::move(msg_queue)) { +ICommonStateGetter::ICommonStateGetter(Core::System& system_, + std::shared_ptr<AppletMessageQueue> msg_queue_) + : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, @@ -796,8 +798,9 @@ private: std::vector<u8> buffer; }; -IStorage::IStorage(std::vector<u8>&& buffer) - : ServiceFramework("IStorage"), impl{std::make_shared<StorageDataImpl>(std::move(buffer))} { +IStorage::IStorage(Core::System& system_, std::vector<u8>&& buffer) + : ServiceFramework{system_, "IStorage"}, impl{std::make_shared<StorageDataImpl>( + std::move(buffer))} { Register(); } @@ -820,7 +823,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IStorageAccessor>(*this); + rb.PushIpcInterface<IStorageAccessor>(system, *this); } void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { @@ -842,8 +845,8 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { public: - explicit ILibraryAppletAccessor(std::shared_ptr<Applets::Applet> applet) - : ServiceFramework("ILibraryAppletAccessor"), applet(std::move(applet)) { + explicit ILibraryAppletAccessor(Core::System& system_, std::shared_ptr<Applets::Applet> applet_) + : ServiceFramework{system_, "ILibraryAppletAccessor"}, applet{std::move(applet_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletAccessor::GetAppletStateChangedEvent, "GetAppletStateChangedEvent"}, @@ -998,8 +1001,8 @@ private: std::shared_ptr<Applets::Applet> applet; }; -IStorageAccessor::IStorageAccessor(IStorage& storage) - : ServiceFramework("IStorageAccessor"), backing(storage) { +IStorageAccessor::IStorageAccessor(Core::System& system_, IStorage& backing_) + : ServiceFramework{system_, "IStorageAccessor"}, backing{backing_} { // clang-format off static const FunctionInfo functions[] = { {0, &IStorageAccessor::GetSize, "GetSize"}, @@ -1070,7 +1073,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { } ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_) - : ServiceFramework("ILibraryAppletCreator"), system{system_} { + : ServiceFramework{system_, "ILibraryAppletCreator"} { static const FunctionInfo functions[] = { {0, &ILibraryAppletCreator::CreateLibraryApplet, "CreateLibraryApplet"}, {1, nullptr, "TerminateAllLibraryApplets"}, @@ -1106,7 +1109,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<AM::ILibraryAppletAccessor>(applet); + rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); } void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { @@ -1118,7 +1121,7 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<AM::IStorage>(std::move(buffer)); + rb.PushIpcInterface<IStorage>(system, std::move(buffer)); } void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) { @@ -1145,11 +1148,11 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IStorage>(std::move(memory)); + rb.PushIpcInterface<IStorage>(system, std::move(memory)); } IApplicationFunctions::IApplicationFunctions(Core::System& system_) - : ServiceFramework("IApplicationFunctions"), system{system_} { + : ServiceFramework{system_, "IApplicationFunctions"} { // clang-format off static const FunctionInfo functions[] = { {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, @@ -1189,9 +1192,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"}, {110, &IApplicationFunctions::QueryApplicationPlayStatistics, "QueryApplicationPlayStatistics"}, {111, &IApplicationFunctions::QueryApplicationPlayStatisticsByUid, "QueryApplicationPlayStatisticsByUid"}, - {120, nullptr, "ExecuteProgram"}, - {121, nullptr, "ClearUserChannel"}, - {122, nullptr, "UnpopToUserChannel"}, + {120, &IApplicationFunctions::ExecuteProgram, "ExecuteProgram"}, + {121, &IApplicationFunctions::ClearUserChannel, "ClearUserChannel"}, + {122, &IApplicationFunctions::UnpopToUserChannel, "UnpopToUserChannel"}, {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, @@ -1301,7 +1304,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { if (data.has_value()) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IStorage>(std::move(*data)); + rb.PushIpcInterface<IStorage>(system, std::move(*data)); launch_popped_application_specific = true; return; } @@ -1324,7 +1327,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); std::memcpy(buffer.data(), ¶ms, buffer.size()); - rb.PushIpcInterface<IStorage>(std::move(buffer)); + rb.PushIpcInterface<IStorage>(system, std::move(buffer)); launch_popped_account_preselect = true; return; } @@ -1381,13 +1384,16 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { const auto res = [this] { const auto title_id = system.CurrentProcess()->GetTitleID(); - FileSys::PatchManager pm{title_id}; + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; auto res = pm.GetControlMetadata(); if (res.first != nullptr) { return res; } - FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), + system.GetFileSystemController(), + system.GetContentProvider()}; return pm_update.GetControlMetadata(); }(); @@ -1415,13 +1421,16 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { const auto res = [this] { const auto title_id = system.CurrentProcess()->GetTitleID(); - FileSys::PatchManager pm{title_id}; + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; auto res = pm.GetControlMetadata(); if (res.first != nullptr) { return res; } - FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; + const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), + system.GetFileSystemController(), + system.GetContentProvider()}; return pm_update.GetControlMetadata(); }(); @@ -1556,6 +1565,34 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque rb.Push<u32>(0); } +void IApplicationFunctions::ExecuteProgram(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::RequestParser rp{ctx}; + [[maybe_unused]] const auto unk_1 = rp.Pop<u32>(); + [[maybe_unused]] const auto unk_2 = rp.Pop<u32>(); + const auto program_index = rp.Pop<u64>(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + system.ExecuteProgram(program_index); +} + +void IApplicationFunctions::ClearUserChannel(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void IApplicationFunctions::UnpopToUserChannel(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_AM, "(STUBBED) called"); @@ -1580,22 +1617,22 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); } -void InstallInterfaces(SM::ServiceManager& service_manager, - std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) { +void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, + Core::System& system) { auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); // Needed on game boot message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); std::make_shared<AppletAE>(nvflinger, message_queue, system)->InstallAsService(service_manager); std::make_shared<AppletOE>(nvflinger, message_queue, system)->InstallAsService(service_manager); - std::make_shared<IdleSys>()->InstallAsService(service_manager); - std::make_shared<OMM>()->InstallAsService(service_manager); - std::make_shared<SPSM>()->InstallAsService(service_manager); - std::make_shared<TCAP>()->InstallAsService(service_manager); + std::make_shared<IdleSys>(system)->InstallAsService(service_manager); + std::make_shared<OMM>(system)->InstallAsService(service_manager); + std::make_shared<SPSM>(system)->InstallAsService(service_manager); + std::make_shared<TCAP>(system)->InstallAsService(service_manager); } -IHomeMenuFunctions::IHomeMenuFunctions(Kernel::KernelCore& kernel) - : ServiceFramework("IHomeMenuFunctions"), kernel(kernel) { +IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_) + : ServiceFramework{system_, "IHomeMenuFunctions"} { // clang-format off static const FunctionInfo functions[] = { {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, @@ -1614,7 +1651,7 @@ IHomeMenuFunctions::IHomeMenuFunctions(Kernel::KernelCore& kernel) RegisterHandlers(functions); pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair( - kernel, "IHomeMenuFunctions:PopFromGeneralChannelEvent"); + system.Kernel(), "IHomeMenuFunctions:PopFromGeneralChannelEvent"); } IHomeMenuFunctions::~IHomeMenuFunctions() = default; @@ -1634,7 +1671,8 @@ void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext rb.PushCopyObjects(pop_from_general_channel_event.readable); } -IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") { +IGlobalStateController::IGlobalStateController(Core::System& system_) + : ServiceFramework{system_, "IGlobalStateController"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestToEnterSleep"}, @@ -1657,7 +1695,8 @@ IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStat IGlobalStateController::~IGlobalStateController() = default; -IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") { +IApplicationCreator::IApplicationCreator(Core::System& system_) + : ServiceFramework{system_, "IApplicationCreator"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateApplication"}, @@ -1672,8 +1711,8 @@ IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreat IApplicationCreator::~IApplicationCreator() = default; -IProcessWindingController::IProcessWindingController() - : ServiceFramework("IProcessWindingController") { +IProcessWindingController::IProcessWindingController(Core::System& system_) + : ServiceFramework{system_, "IProcessWindingController"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetLaunchReason"}, diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index bcc06affe..b1da0d081 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -77,13 +77,11 @@ public: private: void GetAppletResourceUserId(Kernel::HLERequestContext& ctx); void AcquireForegroundRights(Kernel::HLERequestContext& ctx); - - Core::System& system; }; class IAudioController final : public ServiceFramework<IAudioController> { public: - IAudioController(); + explicit IAudioController(Core::System& system_); ~IAudioController() override; private: @@ -109,20 +107,19 @@ private: class IDisplayController final : public ServiceFramework<IDisplayController> { public: - IDisplayController(); + explicit IDisplayController(Core::System& system_); ~IDisplayController() override; }; class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { public: - IDebugFunctions(); + explicit IDebugFunctions(Core::System& system_); ~IDebugFunctions() override; }; class ISelfController final : public ServiceFramework<ISelfController> { public: - explicit ISelfController(Core::System& system_, - std::shared_ptr<NVFlinger::NVFlinger> nvflinger_); + explicit ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_); ~ISelfController() override; private: @@ -155,8 +152,7 @@ private: Disable = 2, }; - Core::System& system; - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + NVFlinger::NVFlinger& nvflinger; Kernel::EventPair launchable_event; Kernel::EventPair accumulated_suspended_tick_changed_event; @@ -168,8 +164,8 @@ private: class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { public: - explicit ICommonStateGetter(Core::System& system, - std::shared_ptr<AppletMessageQueue> msg_queue); + explicit ICommonStateGetter(Core::System& system_, + std::shared_ptr<AppletMessageQueue> msg_queue_); ~ICommonStateGetter() override; private: @@ -197,7 +193,6 @@ private: void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); void SetCpuBoostMode(Kernel::HLERequestContext& ctx); - Core::System& system; std::shared_ptr<AppletMessageQueue> msg_queue; bool vr_mode_state{}; }; @@ -212,7 +207,7 @@ public: class IStorage final : public ServiceFramework<IStorage> { public: - explicit IStorage(std::vector<u8>&& buffer); + explicit IStorage(Core::System& system_, std::vector<u8>&& buffer); ~IStorage() override; std::vector<u8>& GetData() { @@ -236,7 +231,7 @@ private: class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { public: - explicit IStorageAccessor(IStorage& backing); + explicit IStorageAccessor(Core::System& system_, IStorage& backing_); ~IStorageAccessor() override; private: @@ -256,8 +251,6 @@ private: void CreateLibraryApplet(Kernel::HLERequestContext& ctx); void CreateStorage(Kernel::HLERequestContext& ctx); void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx); - - Core::System& system; }; class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { @@ -288,6 +281,9 @@ private: void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx); void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx); void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx); + void ExecuteProgram(Kernel::HLERequestContext& ctx); + void ClearUserChannel(Kernel::HLERequestContext& ctx); + void UnpopToUserChannel(Kernel::HLERequestContext& ctx); void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx); void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); @@ -297,12 +293,11 @@ private: s32 previous_program_index{-1}; Kernel::EventPair gpu_error_detected_event; Kernel::EventPair friend_invitation_storage_channel_event; - Core::System& system; }; class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { public: - explicit IHomeMenuFunctions(Kernel::KernelCore& kernel); + explicit IHomeMenuFunctions(Core::System& system_); ~IHomeMenuFunctions() override; private: @@ -310,29 +305,28 @@ private: void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); Kernel::EventPair pop_from_general_channel_event; - Kernel::KernelCore& kernel; }; class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { public: - IGlobalStateController(); + explicit IGlobalStateController(Core::System& system_); ~IGlobalStateController() override; }; class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { public: - IApplicationCreator(); + explicit IApplicationCreator(Core::System& system_); ~IApplicationCreator() override; }; class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { public: - IProcessWindingController(); + explicit IProcessWindingController(Core::System& system_); ~IProcessWindingController() override; }; /// Registers all AM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, - std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system); +void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, + Core::System& system); } // namespace Service::AM diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index be23ca747..5421e0da0 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -13,11 +13,11 @@ namespace Service::AM { class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { public: - explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, - Core::System& system) - : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)), - msg_queue(std::move(msg_queue)), system(system) { + explicit ILibraryAppletProxy(NVFlinger::NVFlinger& nvflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, + Core::System& system_) + : ServiceFramework{system_, "ILibraryAppletProxy"}, nvflinger{nvflinger_}, + msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -66,7 +66,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IAudioController>(); + rb.PushIpcInterface<IAudioController>(system); } void GetDisplayController(Kernel::HLERequestContext& ctx) { @@ -74,7 +74,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDisplayController>(); + rb.PushIpcInterface<IDisplayController>(system); } void GetProcessWindingController(Kernel::HLERequestContext& ctx) { @@ -82,7 +82,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IProcessWindingController>(); + rb.PushIpcInterface<IProcessWindingController>(system); } void GetDebugFunctions(Kernel::HLERequestContext& ctx) { @@ -90,7 +90,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDebugFunctions>(); + rb.PushIpcInterface<IDebugFunctions>(system); } void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { @@ -109,17 +109,17 @@ private: rb.PushIpcInterface<IApplicationFunctions>(system); } - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + NVFlinger::NVFlinger& nvflinger; std::shared_ptr<AppletMessageQueue> msg_queue; - Core::System& system; }; class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { public: - explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) - : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)), - msg_queue(std::move(msg_queue)), system(system) { + explicit ISystemAppletProxy(NVFlinger::NVFlinger& nvflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, + Core::System& system_) + : ServiceFramework{system_, "ISystemAppletProxy"}, nvflinger{nvflinger_}, + msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -170,7 +170,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IAudioController>(); + rb.PushIpcInterface<IAudioController>(system); } void GetDisplayController(Kernel::HLERequestContext& ctx) { @@ -178,7 +178,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDisplayController>(); + rb.PushIpcInterface<IDisplayController>(system); } void GetDebugFunctions(Kernel::HLERequestContext& ctx) { @@ -186,7 +186,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDebugFunctions>(); + rb.PushIpcInterface<IDebugFunctions>(system); } void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { @@ -202,7 +202,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IHomeMenuFunctions>(system.Kernel()); + rb.PushIpcInterface<IHomeMenuFunctions>(system); } void GetGlobalStateController(Kernel::HLERequestContext& ctx) { @@ -210,7 +210,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IGlobalStateController>(); + rb.PushIpcInterface<IGlobalStateController>(system); } void GetApplicationCreator(Kernel::HLERequestContext& ctx) { @@ -218,11 +218,11 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IApplicationCreator>(); + rb.PushIpcInterface<IApplicationCreator>(system); } - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + + NVFlinger::NVFlinger& nvflinger; std::shared_ptr<AppletMessageQueue> msg_queue; - Core::System& system; }; void AppletAE::OpenSystemAppletProxy(Kernel::HLERequestContext& ctx) { @@ -249,10 +249,10 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system); } -AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) - : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)), - msg_queue(std::move(msg_queue)), system(system) { +AppletAE::AppletAE(NVFlinger::NVFlinger& nvflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, + Core::System& system_) + : ServiceFramework{system_, "appletAE"}, nvflinger{nvflinger_}, msg_queue{ + std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"}, diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h index 2e3e45915..adb207349 100644 --- a/src/core/hle/service/am/applet_ae.h +++ b/src/core/hle/service/am/applet_ae.h @@ -23,8 +23,8 @@ class AppletMessageQueue; class AppletAE final : public ServiceFramework<AppletAE> { public: - explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); + explicit AppletAE(NVFlinger::NVFlinger& nvflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); ~AppletAE() override; const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; @@ -34,9 +34,8 @@ private: void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx); void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx); - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + NVFlinger::NVFlinger& nvflinger; std::shared_ptr<AppletMessageQueue> msg_queue; - Core::System& system; }; } // namespace AM diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index a2ffaa440..f9eba8f52 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -12,10 +12,11 @@ namespace Service::AM { class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { public: - explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) - : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)), - msg_queue(std::move(msg_queue)), system(system) { + explicit IApplicationProxy(NVFlinger::NVFlinger& nvflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, + Core::System& system_) + : ServiceFramework{system_, "IApplicationProxy"}, nvflinger{nvflinger_}, + msg_queue{std::move(msg_queue_)} { // clang-format off static const FunctionInfo functions[] = { {0, &IApplicationProxy::GetCommonStateGetter, "GetCommonStateGetter"}, @@ -39,7 +40,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IAudioController>(); + rb.PushIpcInterface<IAudioController>(system); } void GetDisplayController(Kernel::HLERequestContext& ctx) { @@ -47,7 +48,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDisplayController>(); + rb.PushIpcInterface<IDisplayController>(system); } void GetDebugFunctions(Kernel::HLERequestContext& ctx) { @@ -55,7 +56,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDebugFunctions>(); + rb.PushIpcInterface<IDebugFunctions>(system); } void GetWindowController(Kernel::HLERequestContext& ctx) { @@ -98,9 +99,8 @@ private: rb.PushIpcInterface<IApplicationFunctions>(system); } - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + NVFlinger::NVFlinger& nvflinger; std::shared_ptr<AppletMessageQueue> msg_queue; - Core::System& system; }; void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { @@ -111,10 +111,10 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system); } -AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system) - : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)), - msg_queue(std::move(msg_queue)), system(system) { +AppletOE::AppletOE(NVFlinger::NVFlinger& nvflinger_, std::shared_ptr<AppletMessageQueue> msg_queue_, + Core::System& system_) + : ServiceFramework{system_, "appletOE"}, nvflinger{nvflinger_}, msg_queue{ + std::move(msg_queue_)} { static const FunctionInfo functions[] = { {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"}, }; diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h index 758da792d..6c1aa255a 100644 --- a/src/core/hle/service/am/applet_oe.h +++ b/src/core/hle/service/am/applet_oe.h @@ -23,8 +23,8 @@ class AppletMessageQueue; class AppletOE final : public ServiceFramework<AppletOE> { public: - explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger, - std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system); + explicit AppletOE(NVFlinger::NVFlinger& nvflinger_, + std::shared_ptr<AppletMessageQueue> msg_queue_, Core::System& system_); ~AppletOE() override; const std::shared_ptr<AppletMessageQueue>& GetMessageQueue() const; @@ -32,9 +32,8 @@ public: private: void OpenApplicationProxy(Kernel::HLERequestContext& ctx); - std::shared_ptr<NVFlinger::NVFlinger> nvflinger; + NVFlinger::NVFlinger& nvflinger; std::shared_ptr<AppletMessageQueue> msg_queue; - Core::System& system; }; } // namespace AM diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp index 3ca63f020..e8ea4248b 100644 --- a/src/core/hle/service/am/applets/controller.cpp +++ b/src/core/hle/service/am/applets/controller.cpp @@ -46,7 +46,7 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters( } Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_) {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Controller::~Controller() = default; @@ -245,7 +245,7 @@ void Controller::ConfigurationComplete() { complete = true; out_data = std::vector<u8>(sizeof(ControllerSupportResultInfo)); std::memcpy(out_data.data(), &result_info, out_data.size()); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(out_data))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data))); broker.SignalStateChanged(); } diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h index a7a1f2b65..d4c9da7b1 100644 --- a/src/core/hle/service/am/applets/controller.h +++ b/src/core/hle/service/am/applets/controller.h @@ -120,6 +120,7 @@ public: private: const Core::Frontend::ControllerApplet& frontend; + Core::System& system; ControllerAppletVersion controller_applet_version; ControllerSupportArgPrivate controller_private_arg; diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index f12fd7f89..dcd4b2a35 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -87,7 +87,7 @@ ResultCode Decode64BitError(u64 error) { } // Anonymous namespace Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Error::~Error() = default; @@ -186,7 +186,7 @@ void Error::Execute() { void Error::DisplayCompleted() { complete = true; - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{})); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{})); broker.SignalStateChanged(); } diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 104501ac5..bdb6fd464 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -38,7 +38,7 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) } Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_) {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} Auth::~Auth() = default; @@ -135,8 +135,8 @@ void Auth::Execute() { } } -void Auth::AuthFinished(bool successful) { - this->successful = successful; +void Auth::AuthFinished(bool is_successful) { + this->successful = is_successful; struct Return { ResultCode result_code; @@ -148,12 +148,12 @@ void Auth::AuthFinished(bool successful) { std::vector<u8> out(sizeof(Return)); std::memcpy(out.data(), &return_, sizeof(Return)); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(out))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out))); broker.SignalStateChanged(); } PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} PhotoViewer::~PhotoViewer() = default; @@ -198,12 +198,12 @@ void PhotoViewer::Execute() { } void PhotoViewer::ViewFinished() { - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{})); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{})); broker.SignalStateChanged(); } StubApplet::StubApplet(Core::System& system_, AppletId id_) - : Applet{system_.Kernel()}, id(id_), system{system_} {} + : Applet{system_.Kernel()}, id{id_}, system{system_} {} StubApplet::~StubApplet() = default; @@ -234,8 +234,9 @@ void StubApplet::ExecuteInteractive() { LOG_WARNING(Service_AM, "called (STUBBED)"); LogCurrentStorage(broker, "ExecuteInteractive"); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); - broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); + broker.PushInteractiveDataFromApplet( + std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); broker.SignalStateChanged(); } @@ -243,8 +244,9 @@ void StubApplet::Execute() { LOG_WARNING(Service_AM, "called (STUBBED)"); LogCurrentStorage(broker, "Execute"); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); - broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); + broker.PushInteractiveDataFromApplet( + std::make_shared<IStorage>(system, std::vector<u8>(0x1000))); broker.SignalStateChanged(); } diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index cfa2df369..ba76ae3d3 100644 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h @@ -29,10 +29,11 @@ public: void ExecuteInteractive() override; void Execute() override; - void AuthFinished(bool successful = true); + void AuthFinished(bool is_successful = true); private: Core::Frontend::ParentalControlsApplet& frontend; + Core::System& system; bool complete = false; bool successful = false; diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp index 70cc23552..77fba16c7 100644 --- a/src/core/hle/service/am/applets/profile_select.cpp +++ b/src/core/hle/service/am/applets/profile_select.cpp @@ -17,7 +17,7 @@ constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; ProfileSelect::ProfileSelect(Core::System& system_, const Core::Frontend::ProfileSelectApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_) {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} ProfileSelect::~ProfileSelect() = default; @@ -50,7 +50,7 @@ void ProfileSelect::ExecuteInteractive() { void ProfileSelect::Execute() { if (complete) { - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); return; } @@ -71,7 +71,7 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { final_data = std::vector<u8>(sizeof(UserSelectionOutput)); std::memcpy(final_data.data(), &output, final_data.size()); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); broker.SignalStateChanged(); } diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index 16364ead7..648d33a24 100644 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h @@ -53,6 +53,7 @@ private: bool complete = false; ResultCode status = RESULT_SUCCESS; std::vector<u8> final_data; + Core::System& system; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index bdeb0737a..3022438b1 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp @@ -53,7 +53,7 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, const Core::Frontend::SoftwareKeyboardApplet& frontend_) - : Applet{system_.Kernel()}, frontend(frontend_) {} + : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {} SoftwareKeyboard::~SoftwareKeyboard() = default; @@ -122,7 +122,7 @@ void SoftwareKeyboard::ExecuteInteractive() { switch (request) { case Request::Calc: { - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{1})); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1})); broker.SignalStateChanged(); break; } @@ -135,7 +135,7 @@ void SoftwareKeyboard::ExecuteInteractive() { void SoftwareKeyboard::Execute() { if (complete) { - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data))); broker.SignalStateChanged(); return; } @@ -179,15 +179,17 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { final_data = output_main; if (complete) { - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(output_main))); + broker.PushNormalDataFromApplet( + std::make_shared<IStorage>(system, std::move(output_main))); broker.SignalStateChanged(); } else { - broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::move(output_sub))); + broker.PushInteractiveDataFromApplet( + std::make_shared<IStorage>(system, std::move(output_sub))); } } else { output_main[0] = 1; complete = true; - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(output_main))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main))); broker.SignalStateChanged(); } } diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index 5a3824b5a..1d260fef8 100644 --- a/src/core/hle/service/am/applets/software_keyboard.h +++ b/src/core/hle/service/am/applets/software_keyboard.h @@ -80,6 +80,7 @@ private: bool complete = false; bool is_inline = false; std::vector<u8> final_data; + Core::System& system; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index efe595c4f..c3b6b706a 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp @@ -290,7 +290,7 @@ void WebBrowser::Finalize() { std::vector<u8> data(sizeof(WebCommonReturnValue)); std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue)); - broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(data))); + broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(data))); broker.SignalStateChanged(); if (!temporary_dir.empty() && Common::FS::IsDirectory(temporary_dir)) { diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp index d256d57c8..6196773d5 100644 --- a/src/core/hle/service/am/idle.cpp +++ b/src/core/hle/service/am/idle.cpp @@ -6,7 +6,7 @@ namespace Service::AM { -IdleSys::IdleSys() : ServiceFramework{"idle:sys"} { +IdleSys::IdleSys(Core::System& system_) : ServiceFramework{system_, "idle:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetAutoPowerDownEvent"}, diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h index c44e856b1..e290c30b1 100644 --- a/src/core/hle/service/am/idle.h +++ b/src/core/hle/service/am/idle.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::AM { class IdleSys final : public ServiceFramework<IdleSys> { public: - explicit IdleSys(); + explicit IdleSys(Core::System& system_); ~IdleSys() override; }; diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp index 37389ccda..55de67e1d 100644 --- a/src/core/hle/service/am/omm.cpp +++ b/src/core/hle/service/am/omm.cpp @@ -6,7 +6,7 @@ namespace Service::AM { -OMM::OMM() : ServiceFramework{"omm"} { +OMM::OMM(Core::System& system_) : ServiceFramework{system_, "omm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetOperationMode"}, diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h index 59dc91b72..3766150fe 100644 --- a/src/core/hle/service/am/omm.h +++ b/src/core/hle/service/am/omm.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::AM { class OMM final : public ServiceFramework<OMM> { public: - explicit OMM(); + explicit OMM(Core::System& system_); ~OMM() override; }; diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp index f27729ce7..95218d9ee 100644 --- a/src/core/hle/service/am/spsm.cpp +++ b/src/core/hle/service/am/spsm.cpp @@ -6,7 +6,7 @@ namespace Service::AM { -SPSM::SPSM() : ServiceFramework{"spsm"} { +SPSM::SPSM(Core::System& system_) : ServiceFramework{system_, "spsm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetState"}, diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h index 3a0b979fa..04bbf9e68 100644 --- a/src/core/hle/service/am/spsm.h +++ b/src/core/hle/service/am/spsm.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::AM { class SPSM final : public ServiceFramework<SPSM> { public: - explicit SPSM(); + explicit SPSM(Core::System& system_); ~SPSM() override; }; diff --git a/src/core/hle/service/am/tcap.cpp b/src/core/hle/service/am/tcap.cpp index a75cbdda8..4d0971c03 100644 --- a/src/core/hle/service/am/tcap.cpp +++ b/src/core/hle/service/am/tcap.cpp @@ -6,7 +6,7 @@ namespace Service::AM { -TCAP::TCAP() : ServiceFramework{"tcap"} { +TCAP::TCAP(Core::System& system_) : ServiceFramework{system_, "tcap"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetContinuousHighSkinTemperatureEvent"}, diff --git a/src/core/hle/service/am/tcap.h b/src/core/hle/service/am/tcap.h index 2021b55d1..e9578f16e 100644 --- a/src/core/hle/service/am/tcap.h +++ b/src/core/hle/service/am/tcap.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::AM { class TCAP final : public ServiceFramework<TCAP> { public: - explicit TCAP(); + explicit TCAP(Core::System& system_); ~TCAP() override; }; diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index e58b2c518..6abac3f78 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -48,8 +48,8 @@ static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { return add_on_content; } -AOC_U::AOC_U(Core::System& system) - : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs(system)), system(system) { +AOC_U::AOC_U(Core::System& system_) + : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CountAddOnContentByApplicationId"}, @@ -164,7 +164,8 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); const auto title_id = system.CurrentProcess()->GetTitleID(); - FileSys::PatchManager pm{title_id}; + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; const auto res = pm.GetControlMetadata(); if (res.first == nullptr) { diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h index 848b2f416..7628f4568 100644 --- a/src/core/hle/service/aoc/aoc_u.h +++ b/src/core/hle/service/aoc/aoc_u.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class WritableEvent; } @@ -26,7 +30,6 @@ private: std::vector<u64> add_on_content; Kernel::EventPair aoc_change_event; - Core::System& system; }; /// Registers all AOC services with the specified service manager. diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index e2d8f0027..97d6619dd 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp @@ -14,13 +14,14 @@ Module::~Module() = default; void InstallInterfaces(Core::System& system) { auto module_ = std::make_shared<Module>(); - std::make_shared<APM>(module_, system.GetAPMController(), "apm") + std::make_shared<APM>(system, module_, system.GetAPMController(), "apm") ->InstallAsService(system.ServiceManager()); - std::make_shared<APM>(module_, system.GetAPMController(), "apm:p") + std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:p") ->InstallAsService(system.ServiceManager()); - std::make_shared<APM>(module_, system.GetAPMController(), "apm:am") + std::make_shared<APM>(system, module_, system.GetAPMController(), "apm:am") + ->InstallAsService(system.ServiceManager()); + std::make_shared<APM_Sys>(system, system.GetAPMController()) ->InstallAsService(system.ServiceManager()); - std::make_shared<APM_Sys>(system.GetAPMController())->InstallAsService(system.ServiceManager()); } } // namespace Service::APM diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h index cf4c2bb11..691fe6c16 100644 --- a/src/core/hle/service/apm/apm.h +++ b/src/core/hle/service/apm/apm.h @@ -4,7 +4,9 @@ #pragma once -#include "core/hle/service/service.h" +namespace Core { +class System; +} namespace Service::APM { diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp index 06f0f8edd..89442e21e 100644 --- a/src/core/hle/service/apm/interface.cpp +++ b/src/core/hle/service/apm/interface.cpp @@ -12,7 +12,8 @@ namespace Service::APM { class ISession final : public ServiceFramework<ISession> { public: - ISession(Controller& controller) : ServiceFramework("ISession"), controller(controller) { + explicit ISession(Core::System& system_, Controller& controller_) + : ServiceFramework{system_, "ISession"}, controller{controller_} { static const FunctionInfo functions[] = { {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, @@ -50,8 +51,9 @@ private: Controller& controller; }; -APM::APM(std::shared_ptr<Module> apm, Controller& controller, const char* name) - : ServiceFramework(name), apm(std::move(apm)), controller(controller) { +APM::APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& controller_, + const char* name) + : ServiceFramework{system_, name}, apm(std::move(apm_)), controller{controller_} { static const FunctionInfo functions[] = { {0, &APM::OpenSession, "OpenSession"}, {1, &APM::GetPerformanceMode, "GetPerformanceMode"}, @@ -67,7 +69,7 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISession>(controller); + rb.PushIpcInterface<ISession>(system, controller); } void APM::GetPerformanceMode(Kernel::HLERequestContext& ctx) { @@ -77,7 +79,8 @@ void APM::GetPerformanceMode(Kernel::HLERequestContext& ctx) { rb.PushEnum(controller.GetCurrentPerformanceMode()); } -APM_Sys::APM_Sys(Controller& controller) : ServiceFramework{"apm:sys"}, controller(controller) { +APM_Sys::APM_Sys(Core::System& system_, Controller& controller_) + : ServiceFramework{system_, "apm:sys"}, controller{controller_} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestPerformanceMode"}, @@ -101,7 +104,7 @@ void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISession>(controller); + rb.PushIpcInterface<ISession>(system, controller); } void APM_Sys::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h index de1b89437..7d57c4978 100644 --- a/src/core/hle/service/apm/interface.h +++ b/src/core/hle/service/apm/interface.h @@ -13,7 +13,8 @@ class Module; class APM final : public ServiceFramework<APM> { public: - explicit APM(std::shared_ptr<Module> apm, Controller& controller, const char* name); + explicit APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& controller_, + const char* name); ~APM() override; private: @@ -26,7 +27,7 @@ private: class APM_Sys final : public ServiceFramework<APM_Sys> { public: - explicit APM_Sys(Controller& controller); + explicit APM_Sys(Core::System& system_, Controller& controller); ~APM_Sys() override; void SetCpuBoostMode(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 6ddb547fb..84890be72 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -8,7 +8,7 @@ namespace Service::Audio { -AudCtl::AudCtl() : ServiceFramework{"audctl"} { +AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetTargetVolume"}, diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index c7fafc02e..15f6c77a0 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudCtl final : public ServiceFramework<AudCtl> { public: - explicit AudCtl(); + explicit AudCtl(Core::System& system_); ~AudCtl() override; private: diff --git a/src/core/hle/service/audio/auddbg.cpp b/src/core/hle/service/audio/auddbg.cpp index 8fff3e4b4..6264e4bda 100644 --- a/src/core/hle/service/audio/auddbg.cpp +++ b/src/core/hle/service/audio/auddbg.cpp @@ -6,7 +6,7 @@ namespace Service::Audio { -AudDbg::AudDbg(const char* name) : ServiceFramework{name} { +AudDbg::AudDbg(Core::System& system_, const char* name) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestSuspendForDebug"}, diff --git a/src/core/hle/service/audio/auddbg.h b/src/core/hle/service/audio/auddbg.h index 6689f4759..d1653eedd 100644 --- a/src/core/hle/service/audio/auddbg.h +++ b/src/core/hle/service/audio/auddbg.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudDbg final : public ServiceFramework<AudDbg> { public: - explicit AudDbg(const char* name); + explicit AudDbg(Core::System& system_, const char* name); ~AudDbg() override; }; diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp index ddd12f35e..79c3aa920 100644 --- a/src/core/hle/service/audio/audin_a.cpp +++ b/src/core/hle/service/audio/audin_a.cpp @@ -6,7 +6,7 @@ namespace Service::Audio { -AudInA::AudInA() : ServiceFramework{"audin:a"} { +AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestSuspendAudioIns"}, diff --git a/src/core/hle/service/audio/audin_a.h b/src/core/hle/service/audio/audin_a.h index e7623bc29..15120a4b6 100644 --- a/src/core/hle/service/audio/audin_a.h +++ b/src/core/hle/service/audio/audin_a.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudInA final : public ServiceFramework<AudInA> { public: - explicit AudInA(); + explicit AudInA(Core::System& system_); ~AudInA() override; }; diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 3e2299426..26a6deddf 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -11,7 +11,7 @@ namespace Service::Audio { class IAudioIn final : public ServiceFramework<IAudioIn> { public: - IAudioIn() : ServiceFramework("IAudioIn") { + explicit IAudioIn(Core::System& system_) : ServiceFramework{system_, "IAudioIn"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetAudioInState"}, @@ -36,7 +36,7 @@ public: } }; -AudInU::AudInU() : ServiceFramework("audin:u") { +AudInU::AudInU(Core::System& system_) : ServiceFramework{system_, "audin:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &AudInU::ListAudioIns, "ListAudioIns"}, @@ -96,7 +96,7 @@ void AudInU::OpenInOutImpl(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 6, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushRaw<AudInOutParams>(params); - rb.PushIpcInterface<IAudioIn>(); + rb.PushIpcInterface<IAudioIn>(system); } void AudInU::OpenAudioIn(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h index a599f4a64..0d75ae5ac 100644 --- a/src/core/hle/service/audio/audin_u.h +++ b/src/core/hle/service/audio/audin_u.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -14,7 +18,7 @@ namespace Service::Audio { class AudInU final : public ServiceFramework<AudInU> { public: - explicit AudInU(); + explicit AudInU(Core::System& system_); ~AudInU() override; private: diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp index 1781bec83..b3f24f9bb 100644 --- a/src/core/hle/service/audio/audio.cpp +++ b/src/core/hle/service/audio/audio.cpp @@ -20,22 +20,22 @@ namespace Service::Audio { void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<AudCtl>()->InstallAsService(service_manager); - std::make_shared<AudOutA>()->InstallAsService(service_manager); + std::make_shared<AudCtl>(system)->InstallAsService(service_manager); + std::make_shared<AudOutA>(system)->InstallAsService(service_manager); std::make_shared<AudOutU>(system)->InstallAsService(service_manager); - std::make_shared<AudInA>()->InstallAsService(service_manager); - std::make_shared<AudInU>()->InstallAsService(service_manager); - std::make_shared<AudRecA>()->InstallAsService(service_manager); - std::make_shared<AudRecU>()->InstallAsService(service_manager); - std::make_shared<AudRenA>()->InstallAsService(service_manager); + std::make_shared<AudInA>(system)->InstallAsService(service_manager); + std::make_shared<AudInU>(system)->InstallAsService(service_manager); + std::make_shared<AudRecA>(system)->InstallAsService(service_manager); + std::make_shared<AudRecU>(system)->InstallAsService(service_manager); + std::make_shared<AudRenA>(system)->InstallAsService(service_manager); std::make_shared<AudRenU>(system)->InstallAsService(service_manager); - std::make_shared<CodecCtl>()->InstallAsService(service_manager); - std::make_shared<HwOpus>()->InstallAsService(service_manager); + std::make_shared<CodecCtl>(system)->InstallAsService(service_manager); + std::make_shared<HwOpus>(system)->InstallAsService(service_manager); - std::make_shared<AudDbg>("audin:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>("audout:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>("audrec:d")->InstallAsService(service_manager); - std::make_shared<AudDbg>("audren:d")->InstallAsService(service_manager); + std::make_shared<AudDbg>(system, "audin:d")->InstallAsService(service_manager); + std::make_shared<AudDbg>(system, "audout:d")->InstallAsService(service_manager); + std::make_shared<AudDbg>(system, "audrec:d")->InstallAsService(service_manager); + std::make_shared<AudDbg>(system, "audren:d")->InstallAsService(service_manager); } } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp index 85febbca3..19825fd5d 100644 --- a/src/core/hle/service/audio/audout_a.cpp +++ b/src/core/hle/service/audio/audout_a.cpp @@ -6,7 +6,7 @@ namespace Service::Audio { -AudOutA::AudOutA() : ServiceFramework{"audout:a"} { +AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestSuspendAudioOuts"}, diff --git a/src/core/hle/service/audio/audout_a.h b/src/core/hle/service/audio/audout_a.h index d65b66e8e..2043dfb77 100644 --- a/src/core/hle/service/audio/audout_a.h +++ b/src/core/hle/service/audio/audout_a.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudOutA final : public ServiceFramework<AudOutA> { public: - explicit AudOutA(); + explicit AudOutA(Core::System& system_); ~AudOutA() override; }; diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 9b4910e53..145f47ee2 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -40,11 +40,11 @@ enum class AudioState : u32 { class IAudioOut final : public ServiceFramework<IAudioOut> { public: - IAudioOut(Core::System& system, AudoutParams audio_params, AudioCore::AudioOut& audio_core, - std::string&& device_name, std::string&& unique_name) - : ServiceFramework("IAudioOut"), audio_core(audio_core), - device_name(std::move(device_name)), - audio_params(audio_params), main_memory{system.Memory()} { + IAudioOut(Core::System& system_, AudoutParams audio_params_, AudioCore::AudioOut& audio_core_, + std::string&& device_name_, std::string&& unique_name) + : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_}, + device_name{std::move(device_name_)}, audio_params{audio_params_}, main_memory{ + system.Memory()} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, @@ -213,7 +213,7 @@ private: Core::Memory::Memory& main_memory; }; -AudOutU::AudOutU(Core::System& system_) : ServiceFramework("audout:u"), system{system_} { +AudOutU::AudOutU(Core::System& system_) : ServiceFramework{system_, "audout:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &AudOutU::ListAudioOutsImpl, "ListAudioOuts"}, diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h index c9f532ccd..f7ae2f2bf 100644 --- a/src/core/hle/service/audio/audout_u.h +++ b/src/core/hle/service/audio/audout_u.h @@ -34,8 +34,6 @@ private: std::vector<std::shared_ptr<IAudioOut>> audio_out_interfaces; std::unique_ptr<AudioCore::AudioOut> audio_core; - - Core::System& system; }; } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp index ce1bfb48d..c5ab7cad4 100644 --- a/src/core/hle/service/audio/audrec_a.cpp +++ b/src/core/hle/service/audio/audrec_a.cpp @@ -6,7 +6,7 @@ namespace Service::Audio { -AudRecA::AudRecA() : ServiceFramework{"audrec:a"} { +AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestSuspendFinalOutputRecorders"}, diff --git a/src/core/hle/service/audio/audrec_a.h b/src/core/hle/service/audio/audrec_a.h index 384d24c69..2cce90b1d 100644 --- a/src/core/hle/service/audio/audrec_a.h +++ b/src/core/hle/service/audio/audrec_a.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudRecA final : public ServiceFramework<AudRecA> { public: - explicit AudRecA(); + explicit AudRecA(Core::System& system_); ~AudRecA() override; }; diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp index 1a5aed9ed..eb5c63c62 100644 --- a/src/core/hle/service/audio/audrec_u.cpp +++ b/src/core/hle/service/audio/audrec_u.cpp @@ -8,7 +8,8 @@ namespace Service::Audio { class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { public: - IFinalOutputRecorder() : ServiceFramework("IFinalOutputRecorder") { + explicit IFinalOutputRecorder(Core::System& system_) + : ServiceFramework{system_, "IFinalOutputRecorder"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetFinalOutputRecorderState"}, @@ -29,7 +30,7 @@ public: } }; -AudRecU::AudRecU() : ServiceFramework("audrec:u") { +AudRecU::AudRecU(Core::System& system_) : ServiceFramework{system_, "audrec:u"} { static const FunctionInfo functions[] = { {0, nullptr, "OpenFinalOutputRecorder"}, }; diff --git a/src/core/hle/service/audio/audrec_u.h b/src/core/hle/service/audio/audrec_u.h index ca3d638e8..f79d49e5c 100644 --- a/src/core/hle/service/audio/audrec_u.h +++ b/src/core/hle/service/audio/audrec_u.h @@ -6,15 +6,15 @@ #include "core/hle/service/service.h" -namespace Kernel { -class HLERequestContext; +namespace Core { +class System; } namespace Service::Audio { class AudRecU final : public ServiceFramework<AudRecU> { public: - explicit AudRecU(); + explicit AudRecU(Core::System& system_); ~AudRecU() override; }; diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp index edb66d985..5e9f866f0 100644 --- a/src/core/hle/service/audio/audren_a.cpp +++ b/src/core/hle/service/audio/audren_a.cpp @@ -6,7 +6,7 @@ namespace Service::Audio { -AudRenA::AudRenA() : ServiceFramework{"audren:a"} { +AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestSuspendAudioRenderers"}, diff --git a/src/core/hle/service/audio/audren_a.h b/src/core/hle/service/audio/audren_a.h index 81fef0ffe..5d0a626ad 100644 --- a/src/core/hle/service/audio/audren_a.h +++ b/src/core/hle/service/audio/audren_a.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class AudRenA final : public ServiceFramework<AudRenA> { public: - explicit AudRenA(); + explicit AudRenA(Core::System& system_); ~AudRenA() override; }; diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index a2d3ded7b..6e7b7316c 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -28,7 +28,7 @@ class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { public: explicit IAudioRenderer(Core::System& system, AudioCommon::AudioRendererParameter audren_params, const std::size_t instance_number) - : ServiceFramework("IAudioRenderer") { + : ServiceFramework{system, "IAudioRenderer"} { // clang-format off static const FunctionInfo functions[] = { {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, @@ -167,8 +167,8 @@ private: class IAudioDevice final : public ServiceFramework<IAudioDevice> { public: - explicit IAudioDevice(Core::System& system, u32_le revision_num) - : ServiceFramework("IAudioDevice"), revision{revision_num} { + explicit IAudioDevice(Core::System& system_, u32_le revision_num) + : ServiceFramework{system_, "IAudioDevice"}, revision{revision_num} { static const FunctionInfo functions[] = { {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, @@ -325,7 +325,7 @@ private: }; // namespace Audio -AudRenU::AudRenU(Core::System& system_) : ServiceFramework("audren:u"), system{system_} { +AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 4e0ccc792..d693dc406 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -31,7 +31,6 @@ private: void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); std::size_t audren_instance_count = 0; - Core::System& system; }; // Describes a particular audio feature that may be supported in a particular revision. diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp index c6864146d..94afec1b6 100644 --- a/src/core/hle/service/audio/codecctl.cpp +++ b/src/core/hle/service/audio/codecctl.cpp @@ -2,14 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/logging/log.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/audio/codecctl.h" namespace Service::Audio { -CodecCtl::CodecCtl() : ServiceFramework("codecctl") { +CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { static const FunctionInfo functions[] = { {0, nullptr, "InitializeCodecController"}, {1, nullptr, "FinalizeCodecController"}, diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h index 2fe75b6e2..58e53259e 100644 --- a/src/core/hle/service/audio/codecctl.h +++ b/src/core/hle/service/audio/codecctl.h @@ -6,15 +6,15 @@ #include "core/hle/service/service.h" -namespace Kernel { -class HLERequestContext; +namespace Core { +class System; } namespace Service::Audio { class CodecCtl final : public ServiceFramework<CodecCtl> { public: - explicit CodecCtl(); + explicit CodecCtl(Core::System& system_); ~CodecCtl() override; }; diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index f1d81602c..ea3414fd2 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp @@ -160,8 +160,9 @@ private: class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { public: - explicit IHardwareOpusDecoderManager(OpusDecoderState decoder_state) - : ServiceFramework("IHardwareOpusDecoderManager"), decoder_state{std::move(decoder_state)} { + explicit IHardwareOpusDecoderManager(Core::System& system_, OpusDecoderState decoder_state) + : ServiceFramework{system_, "IHardwareOpusDecoderManager"}, decoder_state{ + std::move(decoder_state)} { // clang-format off static const FunctionInfo functions[] = { {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"}, @@ -287,10 +288,10 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<IHardwareOpusDecoderManager>( - OpusDecoderState{std::move(decoder), sample_rate, channel_count}); + system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); } -HwOpus::HwOpus() : ServiceFramework("hwopus") { +HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { static const FunctionInfo functions[] = { {0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"}, {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h index 602ede8ba..4f921f18e 100644 --- a/src/core/hle/service/audio/hwopus.h +++ b/src/core/hle/service/audio/hwopus.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Audio { class HwOpus final : public ServiceFramework<HwOpus> { public: - explicit HwOpus(); + explicit HwOpus(Core::System& system_); ~HwOpus() override; private: diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 68deb0600..b8696a395 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp @@ -88,9 +88,11 @@ struct DeliveryCacheDirectoryEntry { class IDeliveryCacheProgressService final : public ServiceFramework<IDeliveryCacheProgressService> { public: - IDeliveryCacheProgressService(std::shared_ptr<Kernel::ReadableEvent> event, - const DeliveryCacheProgressImpl& impl) - : ServiceFramework{"IDeliveryCacheProgressService"}, event(std::move(event)), impl(impl) { + explicit IDeliveryCacheProgressService(Core::System& system_, + std::shared_ptr<Kernel::ReadableEvent> event_, + const DeliveryCacheProgressImpl& impl_) + : ServiceFramework{system_, "IDeliveryCacheProgressService"}, event{std::move(event_)}, + impl{impl_} { // clang-format off static const FunctionInfo functions[] = { {0, &IDeliveryCacheProgressService::GetEvent, "GetEvent"}, @@ -126,7 +128,7 @@ private: class IBcatService final : public ServiceFramework<IBcatService> { public: explicit IBcatService(Core::System& system_, Backend& backend_) - : ServiceFramework("IBcatService"), system{system_}, backend{backend_}, + : ServiceFramework{system_, "IBcatService"}, backend{backend_}, progress{{ ProgressServiceBackend{system_.Kernel(), "Normal"}, ProgressServiceBackend{system_.Kernel(), "Directory"}, @@ -171,7 +173,7 @@ private: std::shared_ptr<IDeliveryCacheProgressService> CreateProgressService(SyncType type) { auto& backend{progress.at(static_cast<std::size_t>(type))}; - return std::make_shared<IDeliveryCacheProgressService>(backend.GetEvent(), + return std::make_shared<IDeliveryCacheProgressService>(system, backend.GetEvent(), backend.GetImpl()); } @@ -261,7 +263,6 @@ private: rb.Push(RESULT_SUCCESS); } - Core::System& system; Backend& backend; std::array<ProgressServiceBackend, static_cast<std::size_t>(SyncType::Count)> progress; @@ -277,8 +278,8 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) { class IDeliveryCacheFileService final : public ServiceFramework<IDeliveryCacheFileService> { public: - IDeliveryCacheFileService(FileSys::VirtualDir root_) - : ServiceFramework{"IDeliveryCacheFileService"}, root(std::move(root_)) { + explicit IDeliveryCacheFileService(Core::System& system_, FileSys::VirtualDir root_) + : ServiceFramework{system_, "IDeliveryCacheFileService"}, root(std::move(root_)) { // clang-format off static const FunctionInfo functions[] = { {0, &IDeliveryCacheFileService::Open, "Open"}, @@ -394,8 +395,8 @@ private: class IDeliveryCacheDirectoryService final : public ServiceFramework<IDeliveryCacheDirectoryService> { public: - IDeliveryCacheDirectoryService(FileSys::VirtualDir root_) - : ServiceFramework{"IDeliveryCacheDirectoryService"}, root(std::move(root_)) { + explicit IDeliveryCacheDirectoryService(Core::System& system_, FileSys::VirtualDir root_) + : ServiceFramework{system_, "IDeliveryCacheDirectoryService"}, root(std::move(root_)) { // clang-format off static const FunctionInfo functions[] = { {0, &IDeliveryCacheDirectoryService::Open, "Open"}, @@ -492,8 +493,8 @@ private: class IDeliveryCacheStorageService final : public ServiceFramework<IDeliveryCacheStorageService> { public: - IDeliveryCacheStorageService(FileSys::VirtualDir root_) - : ServiceFramework{"IDeliveryCacheStorageService"}, root(std::move(root_)) { + explicit IDeliveryCacheStorageService(Core::System& system_, FileSys::VirtualDir root_) + : ServiceFramework{system_, "IDeliveryCacheStorageService"}, root(std::move(root_)) { // clang-format off static const FunctionInfo functions[] = { {0, &IDeliveryCacheStorageService::CreateFileService, "CreateFileService"}, @@ -518,7 +519,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDeliveryCacheFileService>(root); + rb.PushIpcInterface<IDeliveryCacheFileService>(system, root); } void CreateDirectoryService(Kernel::HLERequestContext& ctx) { @@ -526,7 +527,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDeliveryCacheDirectoryService>(root); + rb.PushIpcInterface<IDeliveryCacheDirectoryService>(system, root); } void EnumerateDeliveryCacheDirectory(Kernel::HLERequestContext& ctx) { @@ -551,10 +552,10 @@ private: void Module::Interface::CreateDeliveryCacheStorageService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_BCAT, "called"); + const auto title_id = system.CurrentProcess()->GetTitleID(); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDeliveryCacheStorageService>( - fsc.GetBCATDirectory(system.CurrentProcess()->GetTitleID())); + rb.PushIpcInterface<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id)); } void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId( @@ -566,7 +567,7 @@ void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId( IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDeliveryCacheStorageService>(fsc.GetBCATDirectory(title_id)); + rb.PushIpcInterface<IDeliveryCacheStorageService>(system, fsc.GetBCATDirectory(title_id)); } std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System& system, @@ -582,10 +583,9 @@ std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, FileSystem::FileSystemController& fsc_, const char* name) - : ServiceFramework(name), fsc{fsc_}, module{std::move(module_)}, + : ServiceFramework{system_, name}, fsc{fsc_}, module{std::move(module_)}, backend{CreateBackendFromSettings(system_, - [&fsc_](u64 tid) { return fsc_.GetBCATDirectory(tid); })}, - system{system_} {} + [&fsc_](u64 tid) { return fsc_.GetBCATDirectory(tid); })} {} Module::Interface::~Interface() = default; diff --git a/src/core/hle/service/bcat/module.h b/src/core/hle/service/bcat/module.h index e4ba23ba0..738731c06 100644 --- a/src/core/hle/service/bcat/module.h +++ b/src/core/hle/service/bcat/module.h @@ -37,9 +37,6 @@ public: std::shared_ptr<Module> module; std::unique_ptr<Backend> backend; - - private: - Core::System& system; }; }; diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp index fac6b2f9c..e4630320e 100644 --- a/src/core/hle/service/bpc/bpc.cpp +++ b/src/core/hle/service/bpc/bpc.cpp @@ -12,7 +12,7 @@ namespace Service::BPC { class BPC final : public ServiceFramework<BPC> { public: - explicit BPC() : ServiceFramework{"bpc"} { + explicit BPC(Core::System& system_) : ServiceFramework{system_, "bpc"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ShutdownSystem"}, @@ -40,7 +40,7 @@ public: class BPC_R final : public ServiceFramework<BPC_R> { public: - explicit BPC_R() : ServiceFramework{"bpc:r"} { + explicit BPC_R(Core::System& system_) : ServiceFramework{system_, "bpc:r"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetRtcTime"}, @@ -55,9 +55,9 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<BPC>()->InstallAsService(sm); - std::make_shared<BPC_R>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<BPC>(system)->InstallAsService(sm); + std::make_shared<BPC_R>(system)->InstallAsService(sm); } } // namespace Service::BPC diff --git a/src/core/hle/service/bpc/bpc.h b/src/core/hle/service/bpc/bpc.h index eaa37be8d..6ec25aa9b 100644 --- a/src/core/hle/service/bpc/bpc.h +++ b/src/core/hle/service/bpc/bpc.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::BPC { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::BPC diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index d4f0dd1ab..2de86f1f1 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp @@ -17,7 +17,7 @@ namespace Service::BtDrv { class Bt final : public ServiceFramework<Bt> { public: - explicit Bt(Core::System& system) : ServiceFramework{"bt"} { + explicit Bt(Core::System& system_) : ServiceFramework{system_, "bt"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LeClientReadCharacteristic"}, @@ -52,7 +52,7 @@ private: class BtDrv final : public ServiceFramework<BtDrv> { public: - explicit BtDrv() : ServiceFramework{"btdrv"} { + explicit BtDrv(Core::System& system_) : ServiceFramework{system_, "btdrv"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "InitializeBluetoothDriver"}, @@ -166,7 +166,7 @@ public: }; void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<BtDrv>()->InstallAsService(sm); + std::make_shared<BtDrv>(system)->InstallAsService(sm); std::make_shared<Bt>(system)->InstallAsService(sm); } diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index c8f8ddbd5..38b55300e 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -18,7 +18,7 @@ namespace Service::BTM { class IBtmUserCore final : public ServiceFramework<IBtmUserCore> { public: - explicit IBtmUserCore(Core::System& system) : ServiceFramework{"IBtmUserCore"} { + explicit IBtmUserCore(Core::System& system_) : ServiceFramework{system_, "IBtmUserCore"} { // clang-format off static const FunctionInfo functions[] = { {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"}, @@ -107,7 +107,7 @@ private: class BTM_USR final : public ServiceFramework<BTM_USR> { public: - explicit BTM_USR(Core::System& system) : ServiceFramework{"btm:u"}, system(system) { + explicit BTM_USR(Core::System& system_) : ServiceFramework{system_, "btm:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &BTM_USR::GetCore, "GetCore"}, @@ -124,13 +124,11 @@ private: rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<IBtmUserCore>(system); } - - Core::System& system; }; class BTM final : public ServiceFramework<BTM> { public: - explicit BTM() : ServiceFramework{"btm"} { + explicit BTM(Core::System& system_) : ServiceFramework{system_, "btm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetState"}, @@ -207,7 +205,7 @@ public: class BTM_DBG final : public ServiceFramework<BTM_DBG> { public: - explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { + explicit BTM_DBG(Core::System& system_) : ServiceFramework{system_, "btm:dbg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "AcquireDiscoveryEvent"}, @@ -232,7 +230,7 @@ public: class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { public: - explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} { + explicit IBtmSystemCore(Core::System& system_) : ServiceFramework{system_, "IBtmSystemCore"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "StartGamepadPairing"}, @@ -254,7 +252,7 @@ public: class BTM_SYS final : public ServiceFramework<BTM_SYS> { public: - explicit BTM_SYS() : ServiceFramework{"btm:sys"} { + explicit BTM_SYS(Core::System& system_) : ServiceFramework{system_, "btm:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, &BTM_SYS::GetCore, "GetCore"}, @@ -270,14 +268,14 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IBtmSystemCore>(); + rb.PushIpcInterface<IBtmSystemCore>(system); } }; void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<BTM>()->InstallAsService(sm); - std::make_shared<BTM_DBG>()->InstallAsService(sm); - std::make_shared<BTM_SYS>()->InstallAsService(sm); + std::make_shared<BTM>(system)->InstallAsService(sm); + std::make_shared<BTM_DBG>(system)->InstallAsService(sm); + std::make_shared<BTM_SYS>(system)->InstallAsService(sm); std::make_shared<BTM_USR>(system)->InstallAsService(sm); } diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp index ba5749b84..5b7fe8e9b 100644 --- a/src/core/hle/service/caps/caps.cpp +++ b/src/core/hle/service/caps/caps.cpp @@ -13,13 +13,13 @@ namespace Service::Capture { -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<CAPS_A>()->InstallAsService(sm); - std::make_shared<CAPS_C>()->InstallAsService(sm); - std::make_shared<CAPS_U>()->InstallAsService(sm); - std::make_shared<CAPS_SC>()->InstallAsService(sm); - std::make_shared<CAPS_SS>()->InstallAsService(sm); - std::make_shared<CAPS_SU>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<CAPS_A>(system)->InstallAsService(sm); + std::make_shared<CAPS_C>(system)->InstallAsService(sm); + std::make_shared<CAPS_U>(system)->InstallAsService(sm); + std::make_shared<CAPS_SC>(system)->InstallAsService(sm); + std::make_shared<CAPS_SS>(system)->InstallAsService(sm); + std::make_shared<CAPS_SU>(system)->InstallAsService(sm); } } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h index b8c67b6e2..3c4290c88 100644 --- a/src/core/hle/service/caps/caps.h +++ b/src/core/hle/service/caps/caps.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -87,6 +91,6 @@ static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30, "ApplicationAlbumFileEntry has incorrect size."); /// Registers all Capture services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index a0a3b2ae3..1fe4f0e14 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp @@ -8,7 +8,8 @@ namespace Service::Capture { class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> { public: - explicit IAlbumAccessorSession() : ServiceFramework{"IAlbumAccessorSession"} { + explicit IAlbumAccessorSession(Core::System& system_) + : ServiceFramework{system_, "IAlbumAccessorSession"} { // clang-format off static const FunctionInfo functions[] = { {2001, nullptr, "OpenAlbumMovieReadStream"}, @@ -26,7 +27,7 @@ public: } }; -CAPS_A::CAPS_A() : ServiceFramework("caps:a") { +CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetAlbumFileCount"}, diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h index cb93aad5b..389cc6dbe 100644 --- a/src/core/hle/service/caps/caps_a.h +++ b/src/core/hle/service/caps/caps_a.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -14,7 +18,7 @@ namespace Service::Capture { class CAPS_A final : public ServiceFramework<CAPS_A> { public: - explicit CAPS_A(); + explicit CAPS_A(Core::System& system_); ~CAPS_A() override; }; diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp index a0ee116fa..45c1c9d30 100644 --- a/src/core/hle/service/caps/caps_c.cpp +++ b/src/core/hle/service/caps/caps_c.cpp @@ -10,7 +10,8 @@ namespace Service::Capture { class IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> { public: - explicit IAlbumControlSession() : ServiceFramework{"IAlbumControlSession"} { + explicit IAlbumControlSession(Core::System& system_) + : ServiceFramework{system_, "IAlbumControlSession"} { // clang-format off static const FunctionInfo functions[] = { {2001, nullptr, "OpenAlbumMovieReadStream"}, @@ -44,7 +45,7 @@ public: } }; -CAPS_C::CAPS_C() : ServiceFramework("caps:c") { +CAPS_C::CAPS_C(Core::System& system_) : ServiceFramework{system_, "caps:c"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "CaptureRawImage"}, diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h index b110301d4..c6d1dfdce 100644 --- a/src/core/hle/service/caps/caps_c.h +++ b/src/core/hle/service/caps/caps_c.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -14,7 +18,7 @@ namespace Service::Capture { class CAPS_C final : public ServiceFramework<CAPS_C> { public: - explicit CAPS_C(); + explicit CAPS_C(Core::System& system_); ~CAPS_C() override; private: diff --git a/src/core/hle/service/caps/caps_sc.cpp b/src/core/hle/service/caps/caps_sc.cpp index 822ee96c8..d91e18e80 100644 --- a/src/core/hle/service/caps/caps_sc.cpp +++ b/src/core/hle/service/caps/caps_sc.cpp @@ -6,7 +6,7 @@ namespace Service::Capture { -CAPS_SC::CAPS_SC() : ServiceFramework("caps:sc") { +CAPS_SC::CAPS_SC(Core::System& system_) : ServiceFramework{system_, "caps:sc"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "CaptureRawImage"}, diff --git a/src/core/hle/service/caps/caps_sc.h b/src/core/hle/service/caps/caps_sc.h index ac3e929ca..e79a33ee5 100644 --- a/src/core/hle/service/caps/caps_sc.h +++ b/src/core/hle/service/caps/caps_sc.h @@ -6,15 +6,15 @@ #include "core/hle/service/service.h" -namespace Kernel { -class HLERequestContext; +namespace Core { +class System; } namespace Service::Capture { class CAPS_SC final : public ServiceFramework<CAPS_SC> { public: - explicit CAPS_SC(); + explicit CAPS_SC(Core::System& system_); ~CAPS_SC() override; }; diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp index 24dc716e7..2b5314691 100644 --- a/src/core/hle/service/caps/caps_ss.cpp +++ b/src/core/hle/service/caps/caps_ss.cpp @@ -6,7 +6,7 @@ namespace Service::Capture { -CAPS_SS::CAPS_SS() : ServiceFramework("caps:ss") { +CAPS_SS::CAPS_SS(Core::System& system_) : ServiceFramework{system_, "caps:ss"} { // clang-format off static const FunctionInfo functions[] = { {201, nullptr, "SaveScreenShot"}, diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h index 450686e4f..1816f7885 100644 --- a/src/core/hle/service/caps/caps_ss.h +++ b/src/core/hle/service/caps/caps_ss.h @@ -6,15 +6,15 @@ #include "core/hle/service/service.h" -namespace Kernel { -class HLERequestContext; +namespace Core { +class System; } namespace Service::Capture { class CAPS_SS final : public ServiceFramework<CAPS_SS> { public: - explicit CAPS_SS(); + explicit CAPS_SS(Core::System& system_); ~CAPS_SS() override; }; diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp index e386470f7..eae39eb7b 100644 --- a/src/core/hle/service/caps/caps_su.cpp +++ b/src/core/hle/service/caps/caps_su.cpp @@ -8,7 +8,7 @@ namespace Service::Capture { -CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") { +CAPS_SU::CAPS_SU(Core::System& system_) : ServiceFramework{system_, "caps:su"} { // clang-format off static const FunctionInfo functions[] = { {32, &CAPS_SU::SetShimLibraryVersion, "SetShimLibraryVersion"}, diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h index 62c9603a9..b366fdb13 100644 --- a/src/core/hle/service/caps/caps_su.h +++ b/src/core/hle/service/caps/caps_su.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -14,7 +18,7 @@ namespace Service::Capture { class CAPS_SU final : public ServiceFramework<CAPS_SU> { public: - explicit CAPS_SU(); + explicit CAPS_SU(Core::System& system_); ~CAPS_SU() override; private: diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp index f9479bdb3..842316a2e 100644 --- a/src/core/hle/service/caps/caps_u.cpp +++ b/src/core/hle/service/caps/caps_u.cpp @@ -12,8 +12,8 @@ namespace Service::Capture { class IAlbumAccessorApplicationSession final : public ServiceFramework<IAlbumAccessorApplicationSession> { public: - explicit IAlbumAccessorApplicationSession() - : ServiceFramework{"IAlbumAccessorApplicationSession"} { + explicit IAlbumAccessorApplicationSession(Core::System& system_) + : ServiceFramework{system_, "IAlbumAccessorApplicationSession"} { // clang-format off static const FunctionInfo functions[] = { {2001, nullptr, "OpenAlbumMovieReadStream"}, @@ -28,7 +28,7 @@ public: } }; -CAPS_U::CAPS_U() : ServiceFramework("caps:u") { +CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} { // clang-format off static const FunctionInfo functions[] = { {32, &CAPS_U::SetShimLibraryVersion, "SetShimLibraryVersion"}, diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h index 4b80f3156..e7e0d8775 100644 --- a/src/core/hle/service/caps/caps_u.h +++ b/src/core/hle/service/caps/caps_u.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -14,7 +18,7 @@ namespace Service::Capture { class CAPS_U final : public ServiceFramework<CAPS_U> { public: - explicit CAPS_U(); + explicit CAPS_U(Core::System& system_); ~CAPS_U() override; private: diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 4ec8c3093..4924c61c3 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp @@ -12,7 +12,7 @@ namespace Service::ERPT { class ErrorReportContext final : public ServiceFramework<ErrorReportContext> { public: - explicit ErrorReportContext() : ServiceFramework{"erpt:c"} { + explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SubmitContext"}, @@ -35,7 +35,7 @@ public: class ErrorReportSession final : public ServiceFramework<ErrorReportSession> { public: - explicit ErrorReportSession() : ServiceFramework{"erpt:r"} { + explicit ErrorReportSession(Core::System& system_) : ServiceFramework{system_, "erpt:r"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenReport"}, @@ -48,9 +48,9 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<ErrorReportContext>()->InstallAsService(sm); - std::make_shared<ErrorReportSession>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<ErrorReportContext>(system)->InstallAsService(sm); + std::make_shared<ErrorReportSession>(system)->InstallAsService(sm); } } // namespace Service::ERPT diff --git a/src/core/hle/service/erpt/erpt.h b/src/core/hle/service/erpt/erpt.h index de439ab6d..8cd5c081f 100644 --- a/src/core/hle/service/erpt/erpt.h +++ b/src/core/hle/service/erpt/erpt.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -11,6 +15,6 @@ class ServiceManager; namespace Service::ERPT { /// Registers all ERPT services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::ERPT diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index c2737a365..26d1e3306 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp @@ -14,7 +14,7 @@ constexpr ResultCode ERROR_INVALID_RIGHTS_ID{ErrorModule::ETicket, 3}; class ETicket final : public ServiceFramework<ETicket> { public: - explicit ETicket() : ServiceFramework{"es"} { + explicit ETicket(Core::System& system_) : ServiceFramework{system_, "es"} { // clang-format off static const FunctionInfo functions[] = { {1, &ETicket::ImportTicket, "ImportTicket"}, @@ -305,8 +305,8 @@ private: Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); }; -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<ETicket>()->InstallAsService(service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<ETicket>(system)->InstallAsService(service_manager); } } // namespace Service::ES diff --git a/src/core/hle/service/es/es.h b/src/core/hle/service/es/es.h index afe70465b..2a7b27d12 100644 --- a/src/core/hle/service/es/es.h +++ b/src/core/hle/service/es/es.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -11,6 +15,6 @@ class ServiceManager; namespace Service::ES { /// Registers all ES services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::ES diff --git a/src/core/hle/service/eupld/eupld.cpp b/src/core/hle/service/eupld/eupld.cpp index 0d6d244f4..2d650b1b7 100644 --- a/src/core/hle/service/eupld/eupld.cpp +++ b/src/core/hle/service/eupld/eupld.cpp @@ -12,7 +12,7 @@ namespace Service::EUPLD { class ErrorUploadContext final : public ServiceFramework<ErrorUploadContext> { public: - explicit ErrorUploadContext() : ServiceFramework{"eupld:c"} { + explicit ErrorUploadContext(Core::System& system_) : ServiceFramework{system_, "eupld:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetUrl"}, @@ -29,7 +29,7 @@ public: class ErrorUploadRequest final : public ServiceFramework<ErrorUploadRequest> { public: - explicit ErrorUploadRequest() : ServiceFramework{"eupld:r"} { + explicit ErrorUploadRequest(Core::System& system_) : ServiceFramework{system_, "eupld:r"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -45,9 +45,9 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<ErrorUploadContext>()->InstallAsService(sm); - std::make_shared<ErrorUploadRequest>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<ErrorUploadContext>(system)->InstallAsService(sm); + std::make_shared<ErrorUploadRequest>(system)->InstallAsService(sm); } } // namespace Service::EUPLD diff --git a/src/core/hle/service/eupld/eupld.h b/src/core/hle/service/eupld/eupld.h index 6eef2c15f..539993a9d 100644 --- a/src/core/hle/service/eupld/eupld.h +++ b/src/core/hle/service/eupld/eupld.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -11,6 +15,6 @@ class ServiceManager; namespace Service::EUPLD { /// Registers all EUPLD services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::EUPLD diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 2546d7595..9b7672a91 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -20,8 +20,9 @@ namespace Service::Fatal { -Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) - : ServiceFramework(name), module(std::move(module)), system(system) {} +Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)} {} Module::Interface::~Interface() = default; diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h index bd9339dfc..2095bf89f 100644 --- a/src/core/hle/service/fatal/fatal.h +++ b/src/core/hle/service/fatal/fatal.h @@ -16,7 +16,8 @@ class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name); + explicit Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name); ~Interface() override; void ThrowFatal(Kernel::HLERequestContext& ctx); @@ -25,7 +26,6 @@ public: protected: std::shared_ptr<Module> module; - Core::System& system; }; }; diff --git a/src/core/hle/service/fatal/fatal_p.cpp b/src/core/hle/service/fatal/fatal_p.cpp index 066ccf6b0..8672b85dc 100644 --- a/src/core/hle/service/fatal/fatal_p.cpp +++ b/src/core/hle/service/fatal/fatal_p.cpp @@ -6,8 +6,8 @@ namespace Service::Fatal { -Fatal_P::Fatal_P(std::shared_ptr<Module> module, Core::System& system) - : Module::Interface(std::move(module), system, "fatal:p") {} +Fatal_P::Fatal_P(std::shared_ptr<Module> module_, Core::System& system_) + : Interface(std::move(module_), system_, "fatal:p") {} Fatal_P::~Fatal_P() = default; diff --git a/src/core/hle/service/fatal/fatal_p.h b/src/core/hle/service/fatal/fatal_p.h index c6d953cb5..ffa5b7b98 100644 --- a/src/core/hle/service/fatal/fatal_p.h +++ b/src/core/hle/service/fatal/fatal_p.h @@ -10,7 +10,7 @@ namespace Service::Fatal { class Fatal_P final : public Module::Interface { public: - explicit Fatal_P(std::shared_ptr<Module> module, Core::System& system); + explicit Fatal_P(std::shared_ptr<Module> module_, Core::System& system_); ~Fatal_P() override; }; diff --git a/src/core/hle/service/fatal/fatal_u.cpp b/src/core/hle/service/fatal/fatal_u.cpp index 8d72ed485..82993938a 100644 --- a/src/core/hle/service/fatal/fatal_u.cpp +++ b/src/core/hle/service/fatal/fatal_u.cpp @@ -6,8 +6,8 @@ namespace Service::Fatal { -Fatal_U::Fatal_U(std::shared_ptr<Module> module, Core::System& system) - : Module::Interface(std::move(module), system, "fatal:u") { +Fatal_U::Fatal_U(std::shared_ptr<Module> module_, Core::System& system_) + : Interface(std::move(module_), system_, "fatal:u") { static const FunctionInfo functions[] = { {0, &Fatal_U::ThrowFatal, "ThrowFatal"}, {1, &Fatal_U::ThrowFatalWithPolicy, "ThrowFatalWithPolicy"}, diff --git a/src/core/hle/service/fatal/fatal_u.h b/src/core/hle/service/fatal/fatal_u.h index 34c5c7f95..0b58c9112 100644 --- a/src/core/hle/service/fatal/fatal_u.h +++ b/src/core/hle/service/fatal/fatal_u.h @@ -10,7 +10,7 @@ namespace Service::Fatal { class Fatal_U final : public Module::Interface { public: - explicit Fatal_U(std::shared_ptr<Module> module, Core::System& system); + explicit Fatal_U(std::shared_ptr<Module> module_, Core::System& system_); ~Fatal_U() override; }; diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp index e461274c1..9dc1bc52e 100644 --- a/src/core/hle/service/fgm/fgm.cpp +++ b/src/core/hle/service/fgm/fgm.cpp @@ -14,7 +14,7 @@ namespace Service::FGM { class IRequest final : public ServiceFramework<IRequest> { public: - explicit IRequest() : ServiceFramework{"IRequest"} { + explicit IRequest(Core::System& system_) : ServiceFramework{system_, "IRequest"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -30,7 +30,7 @@ public: class FGM final : public ServiceFramework<FGM> { public: - explicit FGM(const char* name) : ServiceFramework{name} { + explicit FGM(Core::System& system_, const char* name) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {0, &FGM::Initialize, "Initialize"}, @@ -46,13 +46,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IRequest>(); + rb.PushIpcInterface<IRequest>(system); } }; class FGM_DBG final : public ServiceFramework<FGM_DBG> { public: - explicit FGM_DBG() : ServiceFramework{"fgm:dbg"} { + explicit FGM_DBG(Core::System& system_) : ServiceFramework{system_, "fgm:dbg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -65,11 +65,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<FGM>("fgm")->InstallAsService(sm); - std::make_shared<FGM>("fgm:0")->InstallAsService(sm); - std::make_shared<FGM>("fgm:9")->InstallAsService(sm); - std::make_shared<FGM_DBG>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<FGM>(system, "fgm")->InstallAsService(sm); + std::make_shared<FGM>(system, "fgm:0")->InstallAsService(sm); + std::make_shared<FGM>(system, "fgm:9")->InstallAsService(sm); + std::make_shared<FGM_DBG>(system)->InstallAsService(sm); } } // namespace Service::FGM diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h index e59691264..75978f2ed 100644 --- a/src/core/hle/service/fgm/fgm.h +++ b/src/core/hle/service/fgm/fgm.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::FGM { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::FGM diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 3cdef4888..ca93062cf 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -455,7 +455,9 @@ FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataTy const auto res = system.GetAppLoader().ReadControlData(nacp); if (res != Loader::ResultStatus::Success) { - FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; + const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(), + system.GetFileSystemController(), + system.GetContentProvider()}; const auto metadata = pm.GetControlMetadata(); const auto& nacp_unique = metadata.first; @@ -715,7 +717,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove } if (save_data_factory == nullptr) { - save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); + save_data_factory = + std::make_unique<FileSys::SaveDataFactory>(system, std::move(nand_directory)); } if (sdmc_factory == nullptr) { @@ -726,10 +729,9 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove } void InstallInterfaces(Core::System& system) { - std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager()); - std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager()); - std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter()) - ->InstallAsService(system.ServiceManager()); + std::make_shared<FSP_LDR>(system)->InstallAsService(system.ServiceManager()); + std::make_shared<FSP_PR>(system)->InstallAsService(system.ServiceManager()); + std::make_shared<FSP_SRV>(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp_ldr.cpp index fb487d5bc..1f6c17ba5 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.cpp +++ b/src/core/hle/service/filesystem/fsp_ldr.cpp @@ -7,7 +7,7 @@ namespace Service::FileSystem { -FSP_LDR::FSP_LDR() : ServiceFramework{"fsp:ldr"} { +FSP_LDR::FSP_LDR(Core::System& system_) : ServiceFramework{system_, "fsp:ldr"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenCodeFileSystem"}, diff --git a/src/core/hle/service/filesystem/fsp_ldr.h b/src/core/hle/service/filesystem/fsp_ldr.h index 8210b7729..d6432a0e1 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.h +++ b/src/core/hle/service/filesystem/fsp_ldr.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::FileSystem { class FSP_LDR final : public ServiceFramework<FSP_LDR> { public: - explicit FSP_LDR(); + explicit FSP_LDR(Core::System& system_); ~FSP_LDR() override; }; diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp_pr.cpp index 378201610..00e4d1662 100644 --- a/src/core/hle/service/filesystem/fsp_pr.cpp +++ b/src/core/hle/service/filesystem/fsp_pr.cpp @@ -7,7 +7,7 @@ namespace Service::FileSystem { -FSP_PR::FSP_PR() : ServiceFramework{"fsp:pr"} { +FSP_PR::FSP_PR(Core::System& system_) : ServiceFramework{system_, "fsp:pr"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RegisterProgram"}, diff --git a/src/core/hle/service/filesystem/fsp_pr.h b/src/core/hle/service/filesystem/fsp_pr.h index 556ae5ce9..9e622518c 100644 --- a/src/core/hle/service/filesystem/fsp_pr.h +++ b/src/core/hle/service/filesystem/fsp_pr.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::FileSystem { class FSP_PR final : public ServiceFramework<FSP_PR> { public: - explicit FSP_PR(); + explicit FSP_PR(Core::System& system_); ~FSP_PR() override; }; diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 649128be4..b3480494c 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -14,6 +14,7 @@ #include "common/hex_util.h" #include "common/logging/log.h" #include "common/string_util.h" +#include "core/core.h" #include "core/file_sys/directory.h" #include "core/file_sys/errors.h" #include "core/file_sys/mode.h" @@ -56,8 +57,8 @@ enum class FileSystemType : u8 { class IStorage final : public ServiceFramework<IStorage> { public: - explicit IStorage(FileSys::VirtualFile backend_) - : ServiceFramework("IStorage"), backend(std::move(backend_)) { + explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) + : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, @@ -114,8 +115,8 @@ private: class IFile final : public ServiceFramework<IFile> { public: - explicit IFile(FileSys::VirtualFile backend_) - : ServiceFramework("IFile"), backend(std::move(backend_)) { + explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) + : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, @@ -246,8 +247,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec class IDirectory final : public ServiceFramework<IDirectory> { public: - explicit IDirectory(FileSys::VirtualDir backend_) - : ServiceFramework("IDirectory"), backend(std::move(backend_)) { + explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_) + : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { static const FunctionInfo functions[] = { {0, &IDirectory::Read, "Read"}, {1, &IDirectory::GetEntryCount, "GetEntryCount"}, @@ -302,8 +303,9 @@ private: class IFileSystem final : public ServiceFramework<IFileSystem> { public: - explicit IFileSystem(FileSys::VirtualDir backend, SizeGetter size) - : ServiceFramework("IFileSystem"), backend(std::move(backend)), size(std::move(size)) { + explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) + : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( + size_)} { static const FunctionInfo functions[] = { {0, &IFileSystem::CreateFile, "CreateFile"}, {1, &IFileSystem::DeleteFile, "DeleteFile"}, @@ -420,7 +422,7 @@ public: return; } - auto file = std::make_shared<IFile>(result.Unwrap()); + auto file = std::make_shared<IFile>(system, result.Unwrap()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -445,7 +447,7 @@ public: return; } - auto directory = std::make_shared<IDirectory>(result.Unwrap()); + auto directory = std::make_shared<IDirectory>(system, result.Unwrap()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -500,8 +502,9 @@ private: class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { public: - explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space, FileSystemController& fsc) - : ServiceFramework("ISaveDataInfoReader"), fsc(fsc) { + explicit ISaveDataInfoReader(Core::System& system_, FileSys::SaveDataSpaceId space, + FileSystemController& fsc_) + : ServiceFramework{system_, "ISaveDataInfoReader"}, fsc{fsc_} { static const FunctionInfo functions[] = { {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, }; @@ -650,8 +653,9 @@ private: u64 next_entry_index = 0; }; -FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) - : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) { +FSP_SRV::FSP_SRV(Core::System& system_) + : ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()}, + content_provider{system.GetContentProvider()}, reporter{system.GetReporter()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenFileSystem"}, @@ -801,8 +805,9 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) { void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - auto filesystem = std::make_shared<IFileSystem>( - fsc.OpenSDMC().Unwrap(), SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); + auto filesystem = + std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(), + SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -862,8 +867,8 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { UNREACHABLE(); } - auto filesystem = - std::make_shared<IFileSystem>(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id)); + auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()), + SizeGetter::FromStorageId(fsc, id)); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -882,7 +887,8 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISaveDataInfoReader>(std::make_shared<ISaveDataInfoReader>(space, fsc)); + rb.PushIpcInterface<ISaveDataInfoReader>( + std::make_shared<ISaveDataInfoReader>(system, space, fsc)); } void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(Kernel::HLERequestContext& ctx) { @@ -931,7 +937,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { return; } - auto storage = std::make_shared<IStorage>(std::move(romfs.Unwrap())); + auto storage = std::make_shared<IStorage>(system, std::move(romfs.Unwrap())); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -955,7 +961,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { if (archive != nullptr) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::make_shared<IStorage>(archive)); + rb.PushIpcInterface(std::make_shared<IStorage>(system, archive)); return; } @@ -968,10 +974,10 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { return; } - FileSys::PatchManager pm{title_id}; + const FileSys::PatchManager pm{title_id, fsc, content_provider}; auto storage = std::make_shared<IStorage>( - pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); + system, pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -1033,7 +1039,8 @@ void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) { class IMultiCommitManager final : public ServiceFramework<IMultiCommitManager> { public: - explicit IMultiCommitManager() : ServiceFramework("IMultiCommitManager") { + explicit IMultiCommitManager(Core::System& system_) + : ServiceFramework{system_, "IMultiCommitManager"} { static const FunctionInfo functions[] = { {1, &IMultiCommitManager::Add, "Add"}, {2, &IMultiCommitManager::Commit, "Commit"}, @@ -1064,7 +1071,7 @@ void FSP_SRV::OpenMultiCommitManager(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IMultiCommitManager>(std::make_shared<IMultiCommitManager>()); + rb.PushIpcInterface<IMultiCommitManager>(std::make_shared<IMultiCommitManager>(system)); } } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 4964e874e..472286d6e 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -12,8 +12,9 @@ class Reporter; } namespace FileSys { +class ContentProvider; class FileSystemBackend; -} +} // namespace FileSys namespace Service::FileSystem { @@ -32,7 +33,7 @@ enum class LogMode : u32 { class FSP_SRV final : public ServiceFramework<FSP_SRV> { public: - explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter); + explicit FSP_SRV(Core::System& system_); ~FSP_SRV() override; private: @@ -55,6 +56,7 @@ private: void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); FileSystemController& fsc; + const FileSys::ContentProvider& content_provider; FileSys::VirtualFile romfs; u64 current_process_id = 0; diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index ebb323da2..40a289594 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -17,7 +17,7 @@ namespace Service::Friend { class IFriendService final : public ServiceFramework<IFriendService> { public: - IFriendService() : ServiceFramework("IFriendService") { + explicit IFriendService(Core::System& system_) : ServiceFramework{system_, "IFriendService"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetCompletionEvent"}, @@ -171,8 +171,8 @@ private: class INotificationService final : public ServiceFramework<INotificationService> { public: - INotificationService(Common::UUID uuid, Core::System& system) - : ServiceFramework("INotificationService"), uuid(uuid) { + explicit INotificationService(Common::UUID uuid_, Core::System& system_) + : ServiceFramework{system_, "INotificationService"}, uuid{uuid_} { // clang-format off static const FunctionInfo functions[] = { {0, &INotificationService::GetEvent, "GetEvent"}, @@ -267,7 +267,7 @@ private: void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IFriendService>(); + rb.PushIpcInterface<IFriendService>(system); LOG_DEBUG(Service_ACC, "called"); } @@ -282,8 +282,9 @@ void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx rb.PushIpcInterface<INotificationService>(uuid, system); } -Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) - : ServiceFramework(name), module(std::move(module)), system(system) {} +Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)} {} Module::Interface::~Interface() = default; diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h index 24f3fc969..8be3321db 100644 --- a/src/core/hle/service/friend/friend.h +++ b/src/core/hle/service/friend/friend.h @@ -16,7 +16,8 @@ class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name); + explicit Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name); ~Interface() override; void CreateFriendService(Kernel::HLERequestContext& ctx); @@ -24,7 +25,6 @@ public: protected: std::shared_ptr<Module> module; - Core::System& system; }; }; diff --git a/src/core/hle/service/friend/interface.cpp b/src/core/hle/service/friend/interface.cpp index 58155f652..7368ccec2 100644 --- a/src/core/hle/service/friend/interface.cpp +++ b/src/core/hle/service/friend/interface.cpp @@ -6,8 +6,8 @@ namespace Service::Friend { -Friend::Friend(std::shared_ptr<Module> module, Core::System& system, const char* name) - : Interface(std::move(module), system, name) { +Friend::Friend(std::shared_ptr<Module> module_, Core::System& system_, const char* name) + : Interface(std::move(module_), system_, name) { static const FunctionInfo functions[] = { {0, &Friend::CreateFriendService, "CreateFriendService"}, {1, &Friend::CreateNotificationService, "CreateNotificationService"}, diff --git a/src/core/hle/service/friend/interface.h b/src/core/hle/service/friend/interface.h index 465a35770..43d914b32 100644 --- a/src/core/hle/service/friend/interface.h +++ b/src/core/hle/service/friend/interface.h @@ -10,7 +10,7 @@ namespace Service::Friend { class Friend final : public Module::Interface { public: - explicit Friend(std::shared_ptr<Module> module, Core::System& system, const char* name); + explicit Friend(std::shared_ptr<Module> module_, Core::System& system_, const char* name); ~Friend() override; }; diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index c6252ff89..fc77e7286 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -33,8 +33,8 @@ std::optional<u64> GetTitleIDForProcessID(const Core::System& system, u64 proces } } // Anonymous namespace -ARP_R::ARP_R(const Core::System& system, const ARPManager& manager) - : ServiceFramework{"arp:r"}, system(system), manager(manager) { +ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_) + : ServiceFramework{system_, "arp:r"}, manager{manager_} { // clang-format off static const FunctionInfo functions[] = { {0, &ARP_R::GetApplicationLaunchProperty, "GetApplicationLaunchProperty"}, @@ -152,8 +152,9 @@ class IRegistrar final : public ServiceFramework<IRegistrar> { public: explicit IRegistrar( + Core::System& system_, std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issuer) - : ServiceFramework{"IRegistrar"}, issue_process_id(std::move(issuer)) { + : ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} { // clang-format off static const FunctionInfo functions[] = { {0, &IRegistrar::Issue, "Issue"}, @@ -237,8 +238,8 @@ private: std::vector<u8> control; }; -ARP_W::ARP_W(const Core::System& system, ARPManager& manager) - : ServiceFramework{"arp:w"}, system(system), manager(manager) { +ARP_W::ARP_W(Core::System& system_, ARPManager& manager_) + : ServiceFramework{system_, "arp:w"}, manager{manager_} { // clang-format off static const FunctionInfo functions[] = { {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, @@ -255,7 +256,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_ARP, "called"); registrar = std::make_shared<IRegistrar>( - [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) { + system, [this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) { const auto res = GetTitleIDForProcessID(system, process_id); if (!res.has_value()) { return ERR_NOT_REGISTERED; diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h index d5f8a7e7a..34b412e26 100644 --- a/src/core/hle/service/glue/arp.h +++ b/src/core/hle/service/glue/arp.h @@ -13,7 +13,7 @@ class IRegistrar; class ARP_R final : public ServiceFramework<ARP_R> { public: - explicit ARP_R(const Core::System& system, const ARPManager& manager); + explicit ARP_R(Core::System& system_, const ARPManager& manager_); ~ARP_R() override; private: @@ -22,20 +22,18 @@ private: void GetApplicationControlProperty(Kernel::HLERequestContext& ctx); void GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestContext& ctx); - const Core::System& system; const ARPManager& manager; }; class ARP_W final : public ServiceFramework<ARP_W> { public: - explicit ARP_W(const Core::System& system, ARPManager& manager); + explicit ARP_W(Core::System& system_, ARPManager& manager_); ~ARP_W() override; private: void AcquireRegistrar(Kernel::HLERequestContext& ctx); void DeleteProperties(Kernel::HLERequestContext& ctx); - const Core::System& system; ARPManager& manager; std::shared_ptr<IRegistrar> registrar; }; diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp index cd89d088f..a478b68e1 100644 --- a/src/core/hle/service/glue/bgtc.cpp +++ b/src/core/hle/service/glue/bgtc.cpp @@ -6,7 +6,7 @@ namespace Service::Glue { -BGTC_T::BGTC_T() : ServiceFramework{"bgtc:t"} { +BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "NotifyTaskStarting"}, @@ -31,7 +31,7 @@ BGTC_T::BGTC_T() : ServiceFramework{"bgtc:t"} { BGTC_T::~BGTC_T() = default; -BGTC_SC::BGTC_SC() : ServiceFramework{"bgtc:sc"} { +BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "GetState"}, diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h index 81844f03e..906116ba6 100644 --- a/src/core/hle/service/glue/bgtc.h +++ b/src/core/hle/service/glue/bgtc.h @@ -6,17 +6,21 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Glue { class BGTC_T final : public ServiceFramework<BGTC_T> { public: - BGTC_T(); + explicit BGTC_T(Core::System& system_); ~BGTC_T() override; }; class BGTC_SC final : public ServiceFramework<BGTC_SC> { public: - BGTC_SC(); + explicit BGTC_SC(Core::System& system_); ~BGTC_SC() override; }; diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp index c728e815c..4eafbe5fa 100644 --- a/src/core/hle/service/glue/glue.cpp +++ b/src/core/hle/service/glue/glue.cpp @@ -18,8 +18,8 @@ void InstallInterfaces(Core::System& system) { ->InstallAsService(system.ServiceManager()); // BackGround Task Controller - std::make_shared<BGTC_T>()->InstallAsService(system.ServiceManager()); - std::make_shared<BGTC_SC>()->InstallAsService(system.ServiceManager()); + std::make_shared<BGTC_T>(system)->InstallAsService(system.ServiceManager()); + std::make_shared<BGTC_SC>(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::Glue diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp index 401e0b208..a502ab47f 100644 --- a/src/core/hle/service/grc/grc.cpp +++ b/src/core/hle/service/grc/grc.cpp @@ -12,7 +12,7 @@ namespace Service::GRC { class GRC final : public ServiceFramework<GRC> { public: - explicit GRC() : ServiceFramework{"grc:c"} { + explicit GRC(Core::System& system) : ServiceFramework{system, "grc:c"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "OpenContinuousRecorder"}, @@ -27,8 +27,8 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<GRC>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<GRC>(system)->InstallAsService(sm); } } // namespace Service::GRC diff --git a/src/core/hle/service/grc/grc.h b/src/core/hle/service/grc/grc.h index e0d29e70d..9069fe756 100644 --- a/src/core/hle/service/grc/grc.h +++ b/src/core/hle/service/grc/grc.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::GRC { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::GRC diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e2539ded8..66c4fe60a 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -677,6 +677,14 @@ Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActi return handheld_activation_mode; } +void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) { + communication_mode = communication_mode_; +} + +Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const { + return communication_mode; +} + void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) { const std::size_t npad_index = NPadIdToIndex(npad_id); ASSERT(npad_index < shared_memory_entries.size()); diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 160dcbbe3..96f319294 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -86,6 +86,13 @@ public: None = 2, }; + enum class NpadCommunicationMode : u64 { + Unknown0 = 0, + Unknown1 = 1, + Unknown2 = 2, + Unknown3 = 3, + }; + struct DeviceHandle { NpadType npad_type{}; u8 npad_id{}; @@ -146,6 +153,9 @@ public: void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode); NpadHandheldActivationMode GetNpadHandheldActivationMode() const; + void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); + NpadCommunicationMode GetNpadCommunicationMode() const; + void SetNpadMode(u32 npad_id, NpadAssignments assignment_mode); bool VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index, @@ -424,6 +434,8 @@ private: std::vector<u32> supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual}; + // NpadCommunicationMode is unknown, default value is 1 + NpadCommunicationMode communication_mode{NpadCommunicationMode::Unknown1}; // Each controller should have their own styleset changed event std::array<Kernel::EventPair, 10> styleset_changed_events; std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 902516b29..b3c7234e1 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -44,8 +44,8 @@ constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // constexpr auto motion_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.666Hz) constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; -IAppletResource::IAppletResource(Core::System& system) - : ServiceFramework("IAppletResource"), system(system) { +IAppletResource::IAppletResource(Core::System& system_) + : ServiceFramework{system_, "IAppletResource"} { static const FunctionInfo functions[] = { {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, }; @@ -139,8 +139,10 @@ void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanose class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { public: - explicit IActiveVibrationDeviceList(std::shared_ptr<IAppletResource> applet_resource_) - : ServiceFramework("IActiveVibrationDeviceList"), applet_resource(applet_resource_) { + explicit IActiveVibrationDeviceList(Core::System& system_, + std::shared_ptr<IAppletResource> applet_resource_) + : ServiceFramework{system_, "IActiveVibrationDeviceList"}, + applet_resource(applet_resource_) { // clang-format off static const FunctionInfo functions[] = { {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, @@ -155,8 +157,10 @@ private: IPC::RequestParser rp{ctx}; const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; - applet_resource->GetController<Controller_NPad>(HidController::NPad) - .InitializeVibrationDevice(vibration_device_handle); + if (applet_resource != nullptr) { + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .InitializeVibrationDevice(vibration_device_handle); + } LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", vibration_device_handle.npad_type, vibration_device_handle.npad_id, @@ -177,7 +181,7 @@ std::shared_ptr<IAppletResource> Hid::GetAppletResource() { return applet_resource; } -Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { +Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} { // clang-format off static const FunctionInfo functions[] = { {0, &Hid::CreateAppletResource, "CreateAppletResource"}, @@ -306,8 +310,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { {527, nullptr, "EnablePalmaBoostMode"}, {528, nullptr, "GetPalmaBluetoothAddress"}, {529, nullptr, "SetDisallowedPalmaConnection"}, - {1000, nullptr, "SetNpadCommunicationMode"}, - {1001, nullptr, "GetNpadCommunicationMode"}, + {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"}, + {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, {1002, nullptr, "SetTouchScreenConfiguration"}, {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, {2000, nullptr, "ActivateDigitizer"}, @@ -1068,7 +1072,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IActiveVibrationDeviceList>(applet_resource); + rb.PushIpcInterface<IActiveVibrationDeviceList>(system, applet_resource); } void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { @@ -1296,9 +1300,37 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void Hid::SetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + const auto communication_mode{rp.PopEnum<Controller_NPad::NpadCommunicationMode>()}; + + applet_resource->GetController<Controller_NPad>(HidController::NPad) + .SetNpadCommunicationMode(communication_mode); + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, communication_mode={}", + applet_resource_user_id, communication_mode); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", + applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(applet_resource->GetController<Controller_NPad>(HidController::NPad) + .GetNpadCommunicationMode()); +} + class HidDbg final : public ServiceFramework<HidDbg> { public: - explicit HidDbg() : ServiceFramework{"hid:dbg"} { + explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "DeactivateDebugPad"}, @@ -1425,7 +1457,7 @@ public: class HidSys final : public ServiceFramework<HidSys> { public: - explicit HidSys() : ServiceFramework{"hid:sys"} { + explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} { // clang-format off static const FunctionInfo functions[] = { {31, nullptr, "SendKeyboardLockKeyEvent"}, @@ -1559,7 +1591,7 @@ public: class HidTmp final : public ServiceFramework<HidTmp> { public: - explicit HidTmp() : ServiceFramework{"hid:tmp"} { + explicit HidTmp(Core::System& system_) : ServiceFramework{system_, "hid:tmp"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"}, @@ -1572,7 +1604,7 @@ public: class HidBus final : public ServiceFramework<HidBus> { public: - explicit HidBus() : ServiceFramework{"hidbus"} { + explicit HidBus(Core::System& system_) : ServiceFramework{system_, "hidbus"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "GetBusHandle"}, @@ -1602,15 +1634,15 @@ void ReloadInputDevices() { void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { std::make_shared<Hid>(system)->InstallAsService(service_manager); - std::make_shared<HidBus>()->InstallAsService(service_manager); - std::make_shared<HidDbg>()->InstallAsService(service_manager); - std::make_shared<HidSys>()->InstallAsService(service_manager); - std::make_shared<HidTmp>()->InstallAsService(service_manager); + std::make_shared<HidBus>(system)->InstallAsService(service_manager); + std::make_shared<HidDbg>(system)->InstallAsService(service_manager); + std::make_shared<HidSys>(system)->InstallAsService(service_manager); + std::make_shared<HidTmp>(system)->InstallAsService(service_manager); std::make_shared<IRS>(system)->InstallAsService(service_manager); - std::make_shared<IRS_SYS>()->InstallAsService(service_manager); + std::make_shared<IRS_SYS>(system)->InstallAsService(service_manager); - std::make_shared<XCD_SYS>()->InstallAsService(service_manager); + std::make_shared<XCD_SYS>(system)->InstallAsService(service_manager); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index c8e4a4b55..b87bfdde1 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -41,7 +41,7 @@ enum class HidController : std::size_t { class IAppletResource final : public ServiceFramework<IAppletResource> { public: - explicit IAppletResource(Core::System& system); + explicit IAppletResource(Core::System& system_); ~IAppletResource() override; void ActivateController(HidController controller); @@ -71,7 +71,6 @@ private: std::shared_ptr<Core::Timing::EventType> pad_update_event; std::shared_ptr<Core::Timing::EventType> motion_update_event; - Core::System& system; std::array<std::unique_ptr<ControllerBase>, static_cast<size_t>(HidController::MaxControllers)> controllers{}; @@ -79,7 +78,7 @@ private: class Hid final : public ServiceFramework<Hid> { public: - explicit Hid(Core::System& system); + explicit Hid(Core::System& system_); ~Hid() override; std::shared_ptr<IAppletResource> GetAppletResource(); @@ -146,6 +145,8 @@ private: void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); + void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); enum class VibrationDeviceType : u32 { LinearResonantActuator = 1, @@ -164,7 +165,6 @@ private: static_assert(sizeof(VibrationDeviceInfo) == 0x8, "VibrationDeviceInfo has incorrect size."); std::shared_ptr<IAppletResource> applet_resource; - Core::System& system; }; /// Reload input devices. Used when input configuration changed diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index e82fd031b..c8413099f 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -12,7 +12,7 @@ namespace Service::HID { -IRS::IRS(Core::System& system) : ServiceFramework{"irs"}, system(system) { +IRS::IRS(Core::System& system_) : ServiceFramework{system_, "irs"} { // clang-format off static const FunctionInfo functions[] = { {302, &IRS::ActivateIrsensor, "ActivateIrsensor"}, @@ -175,7 +175,7 @@ void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { IRS::~IRS() = default; -IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} { +IRS_SYS::IRS_SYS(Core::System& system_) : ServiceFramework{system_, "irs:sys"} { // clang-format off static const FunctionInfo functions[] = { {500, nullptr, "SetAppletResourceUserId"}, diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 8918ad6ca..be0c486ba 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h @@ -7,6 +7,10 @@ #include "core/hle/kernel/object.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class SharedMemory; } @@ -15,7 +19,7 @@ namespace Service::HID { class IRS final : public ServiceFramework<IRS> { public: - explicit IRS(Core::System& system); + explicit IRS(Core::System& system_); ~IRS() override; private: @@ -37,14 +41,14 @@ private: void RunIrLedProcessor(Kernel::HLERequestContext& ctx); void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); + std::shared_ptr<Kernel::SharedMemory> shared_mem; const u32 device_handle{0xABCD}; - Core::System& system; }; class IRS_SYS final : public ServiceFramework<IRS_SYS> { public: - explicit IRS_SYS(); + explicit IRS_SYS(Core::System& system); ~IRS_SYS() override; }; diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp index c8e9125f6..43a8840d0 100644 --- a/src/core/hle/service/hid/xcd.cpp +++ b/src/core/hle/service/hid/xcd.cpp @@ -6,7 +6,7 @@ namespace Service::HID { -XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} { +XCD_SYS::XCD_SYS(Core::System& system_) : ServiceFramework{system_, "xcd:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetDataFormat"}, diff --git a/src/core/hle/service/hid/xcd.h b/src/core/hle/service/hid/xcd.h index fd506d303..54932c228 100644 --- a/src/core/hle/service/hid/xcd.h +++ b/src/core/hle/service/hid/xcd.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::HID { class XCD_SYS final : public ServiceFramework<XCD_SYS> { public: - explicit XCD_SYS(); + explicit XCD_SYS(Core::System& system_); ~XCD_SYS() override; }; diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp index 17350b403..6ad3a2877 100644 --- a/src/core/hle/service/lbl/lbl.cpp +++ b/src/core/hle/service/lbl/lbl.cpp @@ -15,7 +15,7 @@ namespace Service::LBL { class LBL final : public ServiceFramework<LBL> { public: - explicit LBL() : ServiceFramework{"lbl"} { + explicit LBL(Core::System& system_) : ServiceFramework{system_, "lbl"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SaveCurrentSetting"}, @@ -84,8 +84,8 @@ private: bool vr_mode_enabled = false; }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<LBL>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<LBL>(system)->InstallAsService(sm); } } // namespace Service::LBL diff --git a/src/core/hle/service/lbl/lbl.h b/src/core/hle/service/lbl/lbl.h index bf6f400f8..9c2021026 100644 --- a/src/core/hle/service/lbl/lbl.h +++ b/src/core/hle/service/lbl/lbl.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::LBL { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::LBL diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp index 49972cd69..ee908f399 100644 --- a/src/core/hle/service/ldn/ldn.cpp +++ b/src/core/hle/service/ldn/ldn.cpp @@ -13,7 +13,7 @@ namespace Service::LDN { class IMonitorService final : public ServiceFramework<IMonitorService> { public: - explicit IMonitorService() : ServiceFramework{"IMonitorService"} { + explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetStateForMonitor"}, @@ -33,7 +33,7 @@ public: class LDNM final : public ServiceFramework<LDNM> { public: - explicit LDNM() : ServiceFramework{"ldn:m"} { + explicit LDNM(Core::System& system_) : ServiceFramework{system_, "ldn:m"} { // clang-format off static const FunctionInfo functions[] = { {0, &LDNM::CreateMonitorService, "CreateMonitorService"} @@ -48,15 +48,15 @@ public: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IMonitorService>(); + rb.PushIpcInterface<IMonitorService>(system); } }; class ISystemLocalCommunicationService final : public ServiceFramework<ISystemLocalCommunicationService> { public: - explicit ISystemLocalCommunicationService() - : ServiceFramework{"ISystemLocalCommunicationService"} { + explicit ISystemLocalCommunicationService(Core::System& system_) + : ServiceFramework{system_, "ISystemLocalCommunicationService"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetState"}, @@ -99,7 +99,8 @@ public: class IUserLocalCommunicationService final : public ServiceFramework<IUserLocalCommunicationService> { public: - explicit IUserLocalCommunicationService() : ServiceFramework{"IUserLocalCommunicationService"} { + explicit IUserLocalCommunicationService(Core::System& system_) + : ServiceFramework{system_, "IUserLocalCommunicationService"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetState"}, @@ -148,7 +149,7 @@ public: class LDNS final : public ServiceFramework<LDNS> { public: - explicit LDNS() : ServiceFramework{"ldn:s"} { + explicit LDNS(Core::System& system_) : ServiceFramework{system_, "ldn:s"} { // clang-format off static const FunctionInfo functions[] = { {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"}, @@ -163,13 +164,13 @@ public: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystemLocalCommunicationService>(); + rb.PushIpcInterface<ISystemLocalCommunicationService>(system); } }; class LDNU final : public ServiceFramework<LDNU> { public: - explicit LDNU() : ServiceFramework{"ldn:u"} { + explicit LDNU(Core::System& system_) : ServiceFramework{system_, "ldn:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"}, @@ -184,14 +185,14 @@ public: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IUserLocalCommunicationService>(); + rb.PushIpcInterface<IUserLocalCommunicationService>(system); } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<LDNM>()->InstallAsService(sm); - std::make_shared<LDNS>()->InstallAsService(sm); - std::make_shared<LDNU>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<LDNM>(system)->InstallAsService(sm); + std::make_shared<LDNS>(system)->InstallAsService(sm); + std::make_shared<LDNU>(system)->InstallAsService(sm); } } // namespace Service::LDN diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h index 6b2a3c2b2..3ccd9738b 100644 --- a/src/core/hle/service/ldn/ldn.h +++ b/src/core/hle/service/ldn/ldn.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -11,6 +15,6 @@ class ServiceManager; namespace Service::LDN { /// Registers all LDN services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::LDN diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 65c209725..fff68326b 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -115,7 +115,7 @@ static_assert(sizeof(NROInfo) == 0x60, "NROInfo has invalid size."); class DebugMonitor final : public ServiceFramework<DebugMonitor> { public: - explicit DebugMonitor() : ServiceFramework{"ldr:dmnt"} { + explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "AddProcessToDebugLaunchQueue"}, @@ -130,7 +130,7 @@ public: class ProcessManager final : public ServiceFramework<ProcessManager> { public: - explicit ProcessManager() : ServiceFramework{"ldr:pm"} { + explicit ProcessManager(Core::System& system_) : ServiceFramework{system_, "ldr:pm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateProcess"}, @@ -147,7 +147,7 @@ public: class Shell final : public ServiceFramework<Shell> { public: - explicit Shell() : ServiceFramework{"ldr:shel"} { + explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "AddProcessToLaunchQueue"}, @@ -161,7 +161,7 @@ public: class RelocatableObject final : public ServiceFramework<RelocatableObject> { public: - explicit RelocatableObject(Core::System& system) : ServiceFramework{"ldr:ro"}, system(system) { + explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { // clang-format off static const FunctionInfo functions[] = { {0, &RelocatableObject::LoadNro, "LoadNro"}, @@ -639,13 +639,12 @@ private: Common::Is4KBAligned(header.segment_headers[RO_INDEX].memory_size) && Common::Is4KBAligned(header.segment_headers[DATA_INDEX].memory_size); } - Core::System& system; }; void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<DebugMonitor>()->InstallAsService(sm); - std::make_shared<ProcessManager>()->InstallAsService(sm); - std::make_shared<Shell>()->InstallAsService(sm); + std::make_shared<DebugMonitor>(system)->InstallAsService(sm); + std::make_shared<ProcessManager>(system)->InstallAsService(sm); + std::make_shared<Shell>(system)->InstallAsService(sm); std::make_shared<RelocatableObject>(system)->InstallAsService(sm); } diff --git a/src/core/hle/service/ldr/ldr.h b/src/core/hle/service/ldr/ldr.h index 7ac8c0b65..104fc15c5 100644 --- a/src/core/hle/service/ldr/ldr.h +++ b/src/core/hle/service/ldr/ldr.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 49a42a9c9..f884b2735 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -18,8 +18,9 @@ namespace Service::LM { class ILogger final : public ServiceFramework<ILogger> { public: - explicit ILogger(Manager& manager_, Core::Memory::Memory& memory_) - : ServiceFramework("ILogger"), manager{manager_}, memory{memory_} { + explicit ILogger(Core::System& system_) + : ServiceFramework{system_, "ILogger"}, manager{system_.GetLogManager()}, + memory{system_.Memory()} { static const FunctionInfo functions[] = { {0, &ILogger::Log, "Log"}, {1, &ILogger::SetDestination, "SetDestination"}, @@ -81,8 +82,7 @@ private: class LM final : public ServiceFramework<LM> { public: - explicit LM(Manager& manager_, Core::Memory::Memory& memory_) - : ServiceFramework{"lm"}, manager{manager_}, memory{memory_} { + explicit LM(Core::System& system_) : ServiceFramework{system_, "lm"} { // clang-format off static const FunctionInfo functions[] = { {0, &LM::OpenLogger, "OpenLogger"}, @@ -98,16 +98,12 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ILogger>(manager, memory); + rb.PushIpcInterface<ILogger>(system); } - - Manager& manager; - Core::Memory::Memory& memory; }; void InstallInterfaces(Core::System& system) { - std::make_shared<LM>(system.GetLogManager(), system.Memory()) - ->InstallAsService(system.ServiceManager()); + std::make_shared<LM>(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::LM diff --git a/src/core/hle/service/mig/mig.cpp b/src/core/hle/service/mig/mig.cpp index 113a4665c..1599d941b 100644 --- a/src/core/hle/service/mig/mig.cpp +++ b/src/core/hle/service/mig/mig.cpp @@ -12,7 +12,7 @@ namespace Service::Migration { class MIG_USR final : public ServiceFramework<MIG_USR> { public: - explicit MIG_USR() : ServiceFramework{"mig:usr"} { + explicit MIG_USR(Core::System& system_) : ServiceFramework{system_, "mig:usr"} { // clang-format off static const FunctionInfo functions[] = { {10, nullptr, "TryGetLastMigrationInfo"}, @@ -33,8 +33,8 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<MIG_USR>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<MIG_USR>(system)->InstallAsService(sm); } } // namespace Service::Migration diff --git a/src/core/hle/service/mig/mig.h b/src/core/hle/service/mig/mig.h index 288c1c1b3..2b24cdf2c 100644 --- a/src/core/hle/service/mig/mig.h +++ b/src/core/hle/service/mig/mig.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::Migration { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::Migration diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index d7080b715..26be9e45b 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -18,7 +18,8 @@ constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1}; class IDatabaseService final : public ServiceFramework<IDatabaseService> { public: - explicit IDatabaseService() : ServiceFramework{"IDatabaseService"} { + explicit IDatabaseService(Core::System& system_) + : ServiceFramework{system_, "IDatabaseService"} { // clang-format off static const FunctionInfo functions[] = { {0, &IDatabaseService::IsUpdated, "IsUpdated"}, @@ -252,7 +253,8 @@ private: class MiiDBModule final : public ServiceFramework<MiiDBModule> { public: - explicit MiiDBModule(const char* name) : ServiceFramework{name} { + explicit MiiDBModule(Core::System& system_, const char* name) + : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, @@ -266,7 +268,7 @@ private: void GetDatabaseService(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IDatabaseService>(); + rb.PushIpcInterface<IDatabaseService>(system); LOG_DEBUG(Service_Mii, "called"); } @@ -274,7 +276,7 @@ private: class MiiImg final : public ServiceFramework<MiiImg> { public: - explicit MiiImg() : ServiceFramework{"miiimg"} { + explicit MiiImg(Core::System& system_) : ServiceFramework{system_, "miiimg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -298,11 +300,11 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<MiiDBModule>("mii:e")->InstallAsService(sm); - std::make_shared<MiiDBModule>("mii:u")->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<MiiDBModule>(system, "mii:e")->InstallAsService(sm); + std::make_shared<MiiDBModule>(system, "mii:u")->InstallAsService(sm); - std::make_shared<MiiImg>()->InstallAsService(sm); + std::make_shared<MiiImg>(system)->InstallAsService(sm); } } // namespace Service::Mii diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h index 7ce9be50e..9d3238e72 100644 --- a/src/core/hle/service/mii/mii.h +++ b/src/core/hle/service/mii/mii.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::Mii { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::Mii diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp index 25c24e537..b0cb07d24 100644 --- a/src/core/hle/service/mm/mm_u.cpp +++ b/src/core/hle/service/mm/mm_u.cpp @@ -6,12 +6,13 @@ #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_session.h" #include "core/hle/service/mm/mm_u.h" +#include "core/hle/service/sm/sm.h" namespace Service::MM { class MM_U final : public ServiceFramework<MM_U> { public: - explicit MM_U() : ServiceFramework{"mm:u"} { + explicit MM_U(Core::System& system_) : ServiceFramework{system_, "mm:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &MM_U::InitializeOld, "InitializeOld"}, @@ -104,8 +105,8 @@ private: u32 id{1}; }; -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<MM_U>()->InstallAsService(service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<MM_U>(system)->InstallAsService(service_manager); } } // namespace Service::MM diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h index 5439fa653..49b6a3355 100644 --- a/src/core/hle/service/mm/mm_u.h +++ b/src/core/hle/service/mm/mm_u.h @@ -4,11 +4,17 @@ #pragma once -#include "core/hle/service/service.h" +namespace Core { +class System; +} + +namespace Service::SM { +class ServiceManager; +} namespace Service::MM { /// Registers all MM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::MM diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp index e38dea1f4..b8d627ca8 100644 --- a/src/core/hle/service/ncm/ncm.cpp +++ b/src/core/hle/service/ncm/ncm.cpp @@ -14,8 +14,8 @@ namespace Service::NCM { class ILocationResolver final : public ServiceFramework<ILocationResolver> { public: - explicit ILocationResolver(FileSys::StorageId id) - : ServiceFramework{"ILocationResolver"}, storage(id) { + explicit ILocationResolver(Core::System& system_, FileSys::StorageId id) + : ServiceFramework{system_, "ILocationResolver"}, storage{id} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ResolveProgramPath"}, @@ -50,7 +50,8 @@ private: class IRegisteredLocationResolver final : public ServiceFramework<IRegisteredLocationResolver> { public: - explicit IRegisteredLocationResolver() : ServiceFramework{"IRegisteredLocationResolver"} { + explicit IRegisteredLocationResolver(Core::System& system_) + : ServiceFramework{system_, "IRegisteredLocationResolver"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ResolveProgramPath"}, @@ -72,7 +73,8 @@ public: class IAddOnContentLocationResolver final : public ServiceFramework<IAddOnContentLocationResolver> { public: - explicit IAddOnContentLocationResolver() : ServiceFramework{"IAddOnContentLocationResolver"} { + explicit IAddOnContentLocationResolver(Core::System& system_) + : ServiceFramework{system_, "IAddOnContentLocationResolver"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ResolveAddOnContentPath"}, @@ -89,7 +91,7 @@ public: class LR final : public ServiceFramework<LR> { public: - explicit LR() : ServiceFramework{"lr"} { + explicit LR(Core::System& system_) : ServiceFramework{system_, "lr"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenLocationResolver"}, @@ -105,7 +107,7 @@ public: class NCM final : public ServiceFramework<NCM> { public: - explicit NCM() : ServiceFramework{"ncm"} { + explicit NCM(Core::System& system_) : ServiceFramework{system_, "ncm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateContentStorage"}, @@ -130,9 +132,9 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<LR>()->InstallAsService(sm); - std::make_shared<NCM>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<LR>(system)->InstallAsService(sm); + std::make_shared<NCM>(system)->InstallAsService(sm); } } // namespace Service::NCM diff --git a/src/core/hle/service/ncm/ncm.h b/src/core/hle/service/ncm/ncm.h index 7bc8518a6..ee01eddc0 100644 --- a/src/core/hle/service/ncm/ncm.h +++ b/src/core/hle/service/ncm/ncm.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::NCM { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::NCM diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 780ea30fe..6ab35de47 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -16,7 +16,7 @@ namespace Service::NFC { class IAm final : public ServiceFramework<IAm> { public: - explicit IAm() : ServiceFramework{"NFC::IAm"} { + explicit IAm(Core::System& system_) : ServiceFramework{system_, "NFC::IAm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -31,7 +31,7 @@ public: class NFC_AM final : public ServiceFramework<NFC_AM> { public: - explicit NFC_AM() : ServiceFramework{"nfc:am"} { + explicit NFC_AM(Core::System& system_) : ServiceFramework{system_, "nfc:am"} { // clang-format off static const FunctionInfo functions[] = { {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"}, @@ -47,13 +47,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IAm>(); + rb.PushIpcInterface<IAm>(system); } }; class MFIUser final : public ServiceFramework<MFIUser> { public: - explicit MFIUser() : ServiceFramework{"NFC::MFIUser"} { + explicit MFIUser(Core::System& system_) : ServiceFramework{system_, "NFC::MFIUser"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -79,7 +79,7 @@ public: class NFC_MF_U final : public ServiceFramework<NFC_MF_U> { public: - explicit NFC_MF_U() : ServiceFramework{"nfc:mf:u"} { + explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { // clang-format off static const FunctionInfo functions[] = { {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"}, @@ -95,13 +95,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<MFIUser>(); + rb.PushIpcInterface<MFIUser>(system); } }; class IUser final : public ServiceFramework<IUser> { public: - explicit IUser() : ServiceFramework{"NFC::IUser"} { + explicit IUser(Core::System& system_) : ServiceFramework{system_, "NFC::IUser"} { // clang-format off static const FunctionInfo functions[] = { {0, &IUser::InitializeOld, "InitializeOld"}, @@ -171,7 +171,7 @@ private: class NFC_U final : public ServiceFramework<NFC_U> { public: - explicit NFC_U() : ServiceFramework{"nfc:user"} { + explicit NFC_U(Core::System& system_) : ServiceFramework{system_, "nfc:user"} { // clang-format off static const FunctionInfo functions[] = { {0, &NFC_U::CreateUserInterface, "CreateUserInterface"}, @@ -187,13 +187,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IUser>(); + rb.PushIpcInterface<IUser>(system); } }; class ISystem final : public ServiceFramework<ISystem> { public: - explicit ISystem() : ServiceFramework{"ISystem"} { + explicit ISystem(Core::System& system_) : ServiceFramework{system_, "ISystem"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -230,7 +230,7 @@ public: class NFC_SYS final : public ServiceFramework<NFC_SYS> { public: - explicit NFC_SYS() : ServiceFramework{"nfc:sys"} { + explicit NFC_SYS(Core::System& system_) : ServiceFramework{system_, "nfc:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"}, @@ -246,15 +246,15 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystem>(); + rb.PushIpcInterface<ISystem>(system); } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<NFC_AM>()->InstallAsService(sm); - std::make_shared<NFC_MF_U>()->InstallAsService(sm); - std::make_shared<NFC_U>()->InstallAsService(sm); - std::make_shared<NFC_SYS>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<NFC_AM>(system)->InstallAsService(sm); + std::make_shared<NFC_MF_U>(system)->InstallAsService(sm); + std::make_shared<NFC_U>(system)->InstallAsService(sm); + std::make_shared<NFC_SYS>(system)->InstallAsService(sm); } } // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h index 4d2d815f9..5a94b076d 100644 --- a/src/core/hle/service/nfc/nfc.h +++ b/src/core/hle/service/nfc/nfc.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::NFC { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::NFC diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index a0469ffbd..5557da72e 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -21,8 +21,9 @@ namespace ErrCodes { constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); } // namespace ErrCodes -Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) - : ServiceFramework(name), module(std::move(module)), system(system) { +Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)} { auto& kernel = system.Kernel(); nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected"); } @@ -31,8 +32,8 @@ Module::Interface::~Interface() = default; class IUser final : public ServiceFramework<IUser> { public: - IUser(Module::Interface& nfp_interface, Core::System& system) - : ServiceFramework("NFP::IUser"), nfp_interface(nfp_interface) { + explicit IUser(Module::Interface& nfp_interface_, Core::System& system_) + : ServiceFramework{system_, "NFP::IUser"}, nfp_interface{nfp_interface_} { static const FunctionInfo functions[] = { {0, &IUser::Initialize, "Initialize"}, {1, &IUser::Finalize, "Finalize"}, diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index 200013795..295de535b 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h @@ -16,7 +16,8 @@ class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name); + explicit Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name); ~Interface() override; struct ModelInfo { @@ -43,7 +44,6 @@ public: protected: std::shared_ptr<Module> module; - Core::System& system; }; }; diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp index 298184f17..10b0ef944 100644 --- a/src/core/hle/service/nfp/nfp_user.cpp +++ b/src/core/hle/service/nfp/nfp_user.cpp @@ -6,8 +6,8 @@ namespace Service::NFP { -NFP_User::NFP_User(std::shared_ptr<Module> module, Core::System& system) - : Module::Interface(std::move(module), system, "nfp:user") { +NFP_User::NFP_User(std::shared_ptr<Module> module_, Core::System& system_) + : Interface(std::move(module_), system_, "nfp:user") { static const FunctionInfo functions[] = { {0, &NFP_User::CreateUserInterface, "CreateUserInterface"}, }; diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h index 1686ebf20..7f3c124f6 100644 --- a/src/core/hle/service/nfp/nfp_user.h +++ b/src/core/hle/service/nfp/nfp_user.h @@ -10,7 +10,7 @@ namespace Service::NFP { class NFP_User final : public Module::Interface { public: - explicit NFP_User(std::shared_ptr<Module> module, Core::System& system); + explicit NFP_User(std::shared_ptr<Module> module_, Core::System& system_); ~NFP_User() override; }; diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index db7ec6d0e..ef5176bea 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -23,7 +23,7 @@ enum class RequestState : u32 { class IScanRequest final : public ServiceFramework<IScanRequest> { public: - explicit IScanRequest() : ServiceFramework("IScanRequest") { + explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Submit"}, @@ -40,7 +40,7 @@ public: class IRequest final : public ServiceFramework<IRequest> { public: - explicit IRequest(Core::System& system) : ServiceFramework("IRequest") { + explicit IRequest(Core::System& system_) : ServiceFramework{system_, "IRequest"} { static const FunctionInfo functions[] = { {0, &IRequest::GetRequestState, "GetRequestState"}, {1, &IRequest::GetResult, "GetResult"}, @@ -140,7 +140,7 @@ private: class INetworkProfile final : public ServiceFramework<INetworkProfile> { public: - explicit INetworkProfile() : ServiceFramework("INetworkProfile") { + explicit INetworkProfile(Core::System& system_) : ServiceFramework{system_, "INetworkProfile"} { static const FunctionInfo functions[] = { {0, nullptr, "Update"}, {1, nullptr, "PersistOld"}, @@ -152,7 +152,7 @@ public: class IGeneralService final : public ServiceFramework<IGeneralService> { public: - IGeneralService(Core::System& system); + explicit IGeneralService(Core::System& system_); private: void GetClientId(Kernel::HLERequestContext& ctx) { @@ -169,7 +169,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IScanRequest>(); + rb.PushIpcInterface<IScanRequest>(system); } void CreateRequest(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); @@ -207,7 +207,7 @@ private: IPC::ResponseBuilder rb{ctx, 6, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<INetworkProfile>(); + rb.PushIpcInterface<INetworkProfile>(system); rb.PushRaw<u128>(uuid); } void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) { @@ -239,11 +239,10 @@ private: rb.Push<u8>(1); } } - Core::System& system; }; -IGeneralService::IGeneralService(Core::System& system) - : ServiceFramework("IGeneralService"), system(system) { +IGeneralService::IGeneralService(Core::System& system_) + : ServiceFramework{system_, "IGeneralService"} { // clang-format off static const FunctionInfo functions[] = { {1, &IGeneralService::GetClientId, "GetClientId"}, @@ -296,8 +295,8 @@ IGeneralService::IGeneralService(Core::System& system) class NetworkInterface final : public ServiceFramework<NetworkInterface> { public: - explicit NetworkInterface(const char* name, Core::System& system) - : ServiceFramework{name}, system(system) { + explicit NetworkInterface(const char* name, Core::System& system_) + : ServiceFramework{system_, name} { static const FunctionInfo functions[] = { {4, &NetworkInterface::CreateGeneralServiceOld, "CreateGeneralServiceOld"}, {5, &NetworkInterface::CreateGeneralService, "CreateGeneralService"}, @@ -305,6 +304,7 @@ public: RegisterHandlers(functions); } +private: void CreateGeneralServiceOld(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NIFM, "called"); @@ -320,9 +320,6 @@ public: rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<IGeneralService>(system); } - -private: - Core::System& system; }; void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h index 6857e18f9..c3dd4f386 100644 --- a/src/core/hle/service/nifm/nifm.h +++ b/src/core/hle/service/nifm/nifm.h @@ -4,14 +4,14 @@ #pragma once -namespace Service::SM { -class ServiceManager; -} - namespace Core { class System; } +namespace Service::SM { +class ServiceManager; +} + namespace Service::NIFM { /// Registers all NIFM services with the specified service manager. diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 11aa74828..d33b26129 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -17,7 +17,8 @@ namespace Service::NIM { class IShopServiceAsync final : public ServiceFramework<IShopServiceAsync> { public: - IShopServiceAsync() : ServiceFramework("IShopServiceAsync") { + explicit IShopServiceAsync(Core::System& system_) + : ServiceFramework{system_, "IShopServiceAsync"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Cancel"}, @@ -35,7 +36,8 @@ public: class IShopServiceAccessor final : public ServiceFramework<IShopServiceAccessor> { public: - IShopServiceAccessor() : ServiceFramework("IShopServiceAccessor") { + explicit IShopServiceAccessor(Core::System& system_) + : ServiceFramework{system_, "IShopServiceAccessor"} { // clang-format off static const FunctionInfo functions[] = { {0, &IShopServiceAccessor::CreateAsyncInterface, "CreateAsyncInterface"}, @@ -50,13 +52,14 @@ private: LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IShopServiceAsync>(); + rb.PushIpcInterface<IShopServiceAsync>(system); } }; class IShopServiceAccessServer final : public ServiceFramework<IShopServiceAccessServer> { public: - IShopServiceAccessServer() : ServiceFramework("IShopServiceAccessServer") { + explicit IShopServiceAccessServer(Core::System& system_) + : ServiceFramework{system_, "IShopServiceAccessServer"} { // clang-format off static const FunctionInfo functions[] = { {0, &IShopServiceAccessServer::CreateAccessorInterface, "CreateAccessorInterface"}, @@ -71,13 +74,13 @@ private: LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IShopServiceAccessor>(); + rb.PushIpcInterface<IShopServiceAccessor>(system); } }; class NIM final : public ServiceFramework<NIM> { public: - explicit NIM() : ServiceFramework{"nim"} { + explicit NIM(Core::System& system_) : ServiceFramework{system_, "nim"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateSystemUpdateTask"}, @@ -207,7 +210,7 @@ public: class NIM_ECA final : public ServiceFramework<NIM_ECA> { public: - explicit NIM_ECA() : ServiceFramework{"nim:eca"} { + explicit NIM_ECA(Core::System& system_) : ServiceFramework{system_, "nim:eca"} { // clang-format off static const FunctionInfo functions[] = { {0, &NIM_ECA::CreateServerInterface, "CreateServerInterface"}, @@ -226,13 +229,13 @@ private: LOG_WARNING(Service_NIM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IShopServiceAccessServer>(); + rb.PushIpcInterface<IShopServiceAccessServer>(system); } }; class NIM_SHP final : public ServiceFramework<NIM_SHP> { public: - explicit NIM_SHP() : ServiceFramework{"nim:shp"} { + explicit NIM_SHP(Core::System& system_) : ServiceFramework{system_, "nim:shp"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestDeviceAuthenticationToken"}, @@ -272,8 +275,8 @@ public: class IEnsureNetworkClockAvailabilityService final : public ServiceFramework<IEnsureNetworkClockAvailabilityService> { public: - explicit IEnsureNetworkClockAvailabilityService(Core::System& system) - : ServiceFramework("IEnsureNetworkClockAvailabilityService") { + explicit IEnsureNetworkClockAvailabilityService(Core::System& system_) + : ServiceFramework{system_, "IEnsureNetworkClockAvailabilityService"} { static const FunctionInfo functions[] = { {0, &IEnsureNetworkClockAvailabilityService::StartTask, "StartTask"}, {1, &IEnsureNetworkClockAvailabilityService::GetFinishNotificationEvent, @@ -345,7 +348,7 @@ private: class NTC final : public ServiceFramework<NTC> { public: - explicit NTC(Core::System& system) : ServiceFramework{"ntc"}, system(system) { + explicit NTC(Core::System& system_) : ServiceFramework{system_, "ntc"} { // clang-format off static const FunctionInfo functions[] = { {0, &NTC::OpenEnsureNetworkClockAvailabilityService, "OpenEnsureNetworkClockAvailabilityService"}, @@ -380,13 +383,12 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } - Core::System& system; }; void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { - std::make_shared<NIM>()->InstallAsService(sm); - std::make_shared<NIM_ECA>()->InstallAsService(sm); - std::make_shared<NIM_SHP>()->InstallAsService(sm); + std::make_shared<NIM>(system)->InstallAsService(sm); + std::make_shared<NIM_ECA>(system)->InstallAsService(sm); + std::make_shared<NIM_SHP>(system)->InstallAsService(sm); std::make_shared<NTC>(system)->InstallAsService(sm); } diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h index dbe25dc01..571153fe6 100644 --- a/src/core/hle/service/nim/nim.h +++ b/src/core/hle/service/nim/nim.h @@ -4,14 +4,14 @@ #pragma once -namespace Service::SM { -class ServiceManager; -} - namespace Core { class System; } +namespace Service::SM { +class ServiceManager; +} + namespace Service::NIM { void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp index 8fa16fb08..f7a58f659 100644 --- a/src/core/hle/service/npns/npns.cpp +++ b/src/core/hle/service/npns/npns.cpp @@ -12,7 +12,7 @@ namespace Service::NPNS { class NPNS_S final : public ServiceFramework<NPNS_S> { public: - explicit NPNS_S() : ServiceFramework{"npns:s"} { + explicit NPNS_S(Core::System& system_) : ServiceFramework{system_, "npns:s"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "ListenAll"}, @@ -62,7 +62,7 @@ public: class NPNS_U final : public ServiceFramework<NPNS_U> { public: - explicit NPNS_U() : ServiceFramework{"npns:u"} { + explicit NPNS_U(Core::System& system_) : ServiceFramework{system_, "npns:u"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "ListenAll"}, @@ -91,9 +91,9 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<NPNS_S>()->InstallAsService(sm); - std::make_shared<NPNS_U>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<NPNS_S>(system)->InstallAsService(sm); + std::make_shared<NPNS_U>(system)->InstallAsService(sm); } } // namespace Service::NPNS diff --git a/src/core/hle/service/npns/npns.h b/src/core/hle/service/npns/npns.h index 861cd3e48..3b7596b6b 100644 --- a/src/core/hle/service/npns/npns.h +++ b/src/core/hle/service/npns/npns.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::NPNS { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::NPNS diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 58ee1f712..ef7584641 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/logging/log.h" +#include "core/core.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/vfs.h" @@ -17,7 +18,8 @@ namespace Service::NS { -IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} { +IAccountProxyInterface::IAccountProxyInterface(Core::System& system_) + : ServiceFramework{system_, "IAccountProxyInterface"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "CreateUserAccount"}, @@ -29,8 +31,8 @@ IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountPro IAccountProxyInterface::~IAccountProxyInterface() = default; -IApplicationManagerInterface::IApplicationManagerInterface() - : ServiceFramework{"IApplicationManagerInterface"} { +IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_) + : ServiceFramework{system_, "IApplicationManagerInterface"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ListApplicationRecord"}, @@ -298,7 +300,8 @@ void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestC const auto size = ctx.GetWriteBufferSize(); - const FileSys::PatchManager pm{title_id}; + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; const auto control = pm.GetControlMetadata(); std::vector<u8> out; @@ -426,8 +429,8 @@ ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguag return MakeResult(static_cast<u64>(*language_code)); } -IApplicationVersionInterface::IApplicationVersionInterface() - : ServiceFramework{"IApplicationVersionInterface"} { +IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) + : ServiceFramework{system_, "IApplicationVersionInterface"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetLaunchRequiredVersion"}, @@ -447,8 +450,8 @@ IApplicationVersionInterface::IApplicationVersionInterface() IApplicationVersionInterface::~IApplicationVersionInterface() = default; -IContentManagementInterface::IContentManagementInterface() - : ServiceFramework{"IContentManagementInterface"} { +IContentManagementInterface::IContentManagementInterface(Core::System& system_) + : ServiceFramework{system_, "IContentManagementInterface"} { // clang-format off static const FunctionInfo functions[] = { {11, nullptr, "CalculateApplicationOccupiedSize"}, @@ -467,7 +470,8 @@ IContentManagementInterface::IContentManagementInterface() IContentManagementInterface::~IContentManagementInterface() = default; -IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface"} { +IDocumentInterface::IDocumentInterface(Core::System& system_) + : ServiceFramework{system_, "IDocumentInterface"} { // clang-format off static const FunctionInfo functions[] = { {21, nullptr, "GetApplicationContentPath"}, @@ -481,7 +485,8 @@ IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface" IDocumentInterface::~IDocumentInterface() = default; -IDownloadTaskInterface::IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} { +IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_) + : ServiceFramework{system_, "IDownloadTaskInterface"} { // clang-format off static const FunctionInfo functions[] = { {701, nullptr, "ClearTaskStatusList"}, @@ -501,7 +506,8 @@ IDownloadTaskInterface::IDownloadTaskInterface() : ServiceFramework{"IDownloadTa IDownloadTaskInterface::~IDownloadTaskInterface() = default; -IECommerceInterface::IECommerceInterface() : ServiceFramework{"IECommerceInterface"} { +IECommerceInterface::IECommerceInterface(Core::System& system_) + : ServiceFramework{system_, "IECommerceInterface"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RequestLinkDevice"}, @@ -519,8 +525,8 @@ IECommerceInterface::IECommerceInterface() : ServiceFramework{"IECommerceInterfa IECommerceInterface::~IECommerceInterface() = default; -IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface() - : ServiceFramework{"IFactoryResetInterface"} { +IFactoryResetInterface::IFactoryResetInterface(Core::System& system_) + : ServiceFramework{system_, "IFactoryResetInterface"} { // clang-format off static const FunctionInfo functions[] = { {100, nullptr, "ResetToFactorySettings"}, @@ -538,14 +544,14 @@ IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface() IFactoryResetInterface::~IFactoryResetInterface() = default; -NS::NS(const char* name) : ServiceFramework{name} { +NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, - {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, + {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"}, {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, @@ -558,12 +564,12 @@ NS::NS(const char* name) : ServiceFramework{name} { NS::~NS() = default; std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { - return GetInterface<IApplicationManagerInterface>(); + return GetInterface<IApplicationManagerInterface>(system); } class NS_DEV final : public ServiceFramework<NS_DEV> { public: - explicit NS_DEV() : ServiceFramework{"ns:dev"} { + explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProgram"}, @@ -590,7 +596,8 @@ public: class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> { public: - explicit ISystemUpdateControl() : ServiceFramework{"ISystemUpdateControl"} { + explicit ISystemUpdateControl(Core::System& system_) + : ServiceFramework{system_, "ISystemUpdateControl"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "HasDownloaded"}, @@ -625,7 +632,7 @@ public: class NS_SU final : public ServiceFramework<NS_SU> { public: - explicit NS_SU() : ServiceFramework{"ns:su"} { + explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetBackgroundNetworkUpdateState"}, @@ -657,13 +664,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystemUpdateControl>(); + rb.PushIpcInterface<ISystemUpdateControl>(system); } }; class NS_VM final : public ServiceFramework<NS_VM> { public: - explicit NS_VM() : ServiceFramework{"ns:vm"} { + explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} { // clang-format off static const FunctionInfo functions[] = { {1200, nullptr, "NeedsUpdateVulnerability"}, @@ -678,15 +685,15 @@ public: void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { - std::make_shared<NS>("ns:am2")->InstallAsService(service_manager); - std::make_shared<NS>("ns:ec")->InstallAsService(service_manager); - std::make_shared<NS>("ns:rid")->InstallAsService(service_manager); - std::make_shared<NS>("ns:rt")->InstallAsService(service_manager); - std::make_shared<NS>("ns:web")->InstallAsService(service_manager); + std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager); + std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager); + std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); + std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); + std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); - std::make_shared<NS_DEV>()->InstallAsService(service_manager); - std::make_shared<NS_SU>()->InstallAsService(service_manager); - std::make_shared<NS_VM>()->InstallAsService(service_manager); + std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); + std::make_shared<NS_SU>(system)->InstallAsService(service_manager); + std::make_shared<NS_VM>(system)->InstallAsService(service_manager); std::make_shared<PL_U>(system)->InstallAsService(service_manager); } diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index c2554b878..991271f3e 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service { namespace FileSystem { @@ -16,13 +20,13 @@ namespace NS { class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { public: - explicit IAccountProxyInterface(); + explicit IAccountProxyInterface(Core::System& system_); ~IAccountProxyInterface() override; }; class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { public: - explicit IApplicationManagerInterface(); + explicit IApplicationManagerInterface(Core::System& system_); ~IApplicationManagerInterface() override; ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); @@ -36,63 +40,71 @@ private: class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { public: - explicit IApplicationVersionInterface(); + explicit IApplicationVersionInterface(Core::System& system_); ~IApplicationVersionInterface() override; }; class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> { public: - explicit IContentManagementInterface(); + explicit IContentManagementInterface(Core::System& system_); ~IContentManagementInterface() override; }; class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { public: - explicit IDocumentInterface(); + explicit IDocumentInterface(Core::System& system_); ~IDocumentInterface() override; }; class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { public: - explicit IDownloadTaskInterface(); + explicit IDownloadTaskInterface(Core::System& system_); ~IDownloadTaskInterface() override; }; class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { public: - explicit IECommerceInterface(); + explicit IECommerceInterface(Core::System& system_); ~IECommerceInterface() override; }; class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { public: - explicit IFactoryResetInterface(); + explicit IFactoryResetInterface(Core::System& system_); ~IFactoryResetInterface() override; }; class NS final : public ServiceFramework<NS> { public: - explicit NS(const char* name); + explicit NS(const char* name, Core::System& system_); ~NS() override; std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; private: - template <typename T> + template <typename T, typename... Args> void PushInterface(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NS, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<T>(); + rb.PushIpcInterface<T>(system); + } + + void PushIApplicationManagerInterface(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_NS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IApplicationManagerInterface>(system); } - template <typename T> - std::shared_ptr<T> GetInterface() const { + template <typename T, typename... Args> + std::shared_ptr<T> GetInterface(Args&&... args) const { static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, "Not a base of ServiceFrameworkBase"); - return std::make_shared<T>(); + return std::make_shared<T>(std::forward<Args>(args)...); } }; diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 5ccec2637..ccc137e40 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -141,8 +141,8 @@ struct PL_U::Impl { std::vector<FontRegion> shared_font_regions; }; -PL_U::PL_U(Core::System& system) - : ServiceFramework("pl:u"), impl{std::make_unique<Impl>()}, system(system) { +PL_U::PL_U(Core::System& system_) + : ServiceFramework{system_, "pl:u"}, impl{std::make_unique<Impl>()} { // clang-format off static const FunctionInfo functions[] = { {0, &PL_U::RequestLoad, "RequestLoad"}, diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h index 27161bd7a..224dcb997 100644 --- a/src/core/hle/service/ns/pl_u.h +++ b/src/core/hle/service/ns/pl_u.h @@ -20,7 +20,7 @@ void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, s class PL_U final : public ServiceFramework<PL_U> { public: - explicit PL_U(Core::System& system); + explicit PL_U(Core::System& system_); ~PL_U() override; private: @@ -33,7 +33,6 @@ private: struct Impl; std::unique_ptr<Impl> impl; - Core::System& system; }; } // namespace NS diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 0240d6643..44a8bc060 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -24,25 +24,38 @@ public: explicit nvdevice(Core::System& system) : system{system} {} virtual ~nvdevice() = default; - union Ioctl { - u32_le raw; - BitField<0, 8, u32> cmd; - BitField<8, 8, u32> group; - BitField<16, 14, u32> length; - BitField<30, 1, u32> is_in; - BitField<31, 1, u32> is_out; - }; + /** + * Handles an ioctl1 request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param output A buffer where the output data will be written to. + * @returns The result code of the ioctl. + */ + virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) = 0; + + /** + * Handles an ioctl2 request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param inline_input A buffer containing the input data for the ioctl which has been inlined. + * @param output A buffer where the output data will be written to. + * @returns The result code of the ioctl. + */ + virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) = 0; /** - * Handles an ioctl request. + * Handles an ioctl3 request. * @param command The ioctl command id. * @param input A buffer containing the input data for the ioctl. * @param output A buffer where the output data will be written to. + * @param inline_output A buffer where the inlined output data will be written to. * @returns The result code of the ioctl. */ - virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) = 0; + virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) = 0; protected: Core::System& system; diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 3f7b8e670..170a7c9a0 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -18,11 +18,23 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_de : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvdisp_disp0 ::~nvdisp_disp0() = default; -u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; +NvResult nvdisp_disp0::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvdisp_disp0::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvdisp_disp0::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 6fcdeee84..eb7575e40 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -20,9 +20,13 @@ public: explicit nvdisp_disp0(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); ~nvdisp_disp0() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; /// Performs a screen flip, drawing the buffer pointed to by the handle. void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride, diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index f2529a12e..4e0652c39 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -17,59 +17,78 @@ namespace Service::Nvidia::Devices { -namespace NvErrCodes { -constexpr u32 Success{}; -constexpr u32 OutOfMemory{static_cast<u32>(-12)}; -constexpr u32 InvalidInput{static_cast<u32>(-22)}; -} // namespace NvErrCodes - nvhost_as_gpu::nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_as_gpu::~nvhost_as_gpu() = default; -u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocInitalizeExCommand: - return InitalizeEx(input, output); - case IoctlCommand::IocAllocateSpaceCommand: - return AllocateSpace(input, output); - case IoctlCommand::IocMapBufferExCommand: - return MapBufferEx(input, output); - case IoctlCommand::IocBindChannelCommand: - return BindChannel(input, output); - case IoctlCommand::IocGetVaRegionsCommand: - return GetVARegions(input, output); - case IoctlCommand::IocUnmapBufferCommand: - return UnmapBuffer(input, output); - case IoctlCommand::IocFreeSpaceCommand: - return FreeSpace(input, output); +NvResult nvhost_as_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 'A': + switch (command.cmd) { + case 0x1: + return BindChannel(input, output); + case 0x2: + return AllocateSpace(input, output); + case 0x3: + return FreeSpace(input, output); + case 0x5: + return UnmapBuffer(input, output); + case 0x6: + return MapBufferEx(input, output); + case 0x8: + return GetVARegions(input, output); + case 0x9: + return InitalizeEx(input, output); + case 0x14: + return Remap(input, output); + default: + break; + } + break; default: break; } - if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand) { - return Remap(input, output); - } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_as_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} - UNIMPLEMENTED_MSG("Unimplemented ioctl command"); - return 0; +NvResult nvhost_as_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + switch (command.group) { + case 'A': + switch (command.cmd) { + case 0x8: + return GetVARegions(input, output, inline_output); + default: + break; + } + break; + default: + break; + } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } -u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { IoctlInitalizeEx params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x{:X}", params.big_page_size); - return 0; + return NvResult::Success; } -u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { IoctlAllocSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -83,17 +102,17 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& params.offset = system.GPU().MemoryManager().Allocate(size, params.align); } - auto result{NvErrCodes::Success}; + auto result = NvResult::Success; if (!params.offset) { LOG_CRITICAL(Service_NVDRV, "allocation failed for size {}", size); - result = NvErrCodes::OutOfMemory; + result = NvResult::InsufficientMemory; } std::memcpy(output.data(), ¶ms, output.size()); return result; } -u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { IoctlFreeSpace params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -104,15 +123,15 @@ u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& outp static_cast<std::size_t>(params.pages) * params.page_size); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { const auto num_entries = input.size() / sizeof(IoctlRemapEntry); LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries); - auto result{NvErrCodes::Success}; + auto result = NvResult::Success; std::vector<IoctlRemapEntry> entries(num_entries); std::memcpy(entries.data(), input.data(), input.size()); @@ -123,7 +142,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) const auto object{nvmap_dev->GetObject(entry.nvmap_handle)}; if (!object) { LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", entry.nvmap_handle); - result = NvErrCodes::InvalidInput; + result = NvResult::InvalidState; break; } @@ -134,7 +153,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) if (!addr) { LOG_CRITICAL(Service_NVDRV, "map returned an invalid address!"); - result = NvErrCodes::InvalidInput; + result = NvResult::InvalidState; break; } } @@ -143,7 +162,7 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) return result; } -u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { IoctlMapBufferEx params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -157,7 +176,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou if (!object) { LOG_CRITICAL(Service_NVDRV, "invalid nvmap_handle={:X}", params.nvmap_handle); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::InvalidInput; + return NvResult::InvalidState; } // The real nvservices doesn't make a distinction between handles and ids, and @@ -184,16 +203,16 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou params.mapping_size, params.offset); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::InvalidInput; + return NvResult::InvalidState; } std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::Success; + return NvResult::Success; } else { LOG_CRITICAL(Service_NVDRV, "address not mapped offset={}", params.offset); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::InvalidInput; + return NvResult::InvalidState; } } @@ -213,10 +232,10 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou params.offset = gpu.MemoryManager().Map(physical_address, params.offset, size); } - auto result{NvErrCodes::Success}; + auto result = NvResult::Success; if (!params.offset) { LOG_CRITICAL(Service_NVDRV, "failed to map size={}", size); - result = NvErrCodes::InvalidInput; + result = NvResult::InvalidState; } else { AddBufferMap(params.offset, size, physical_address, is_alloc); } @@ -225,7 +244,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou return result; } -u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { IoctlUnmapBuffer params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -238,20 +257,42 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou } std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { IoctlBindChannel params{}; std::memcpy(¶ms, input.data(), input.size()); - - LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd); + LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}", params.fd); channel = params.fd; - return 0; + return NvResult::Success; +} + +NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { + IoctlGetVaRegions params{}; + std::memcpy(¶ms, input.data(), input.size()); + + LOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr={:X}, buf_size={:X}", params.buf_addr, + params.buf_size); + + params.buf_size = 0x30; + params.regions[0].offset = 0x04000000; + params.regions[0].page_size = 0x1000; + params.regions[0].pages = 0x3fbfff; + + params.regions[1].offset = 0x04000000; + params.regions[1].page_size = 0x10000; + params.regions[1].pages = 0x1bffff; + + // TODO(ogniK): This probably can stay stubbed but should add support way way later + + std::memcpy(output.data(), ¶ms, output.size()); + return NvResult::Success; } -u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output) { IoctlGetVaRegions params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -270,7 +311,8 @@ u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& o // TODO(ogniK): This probably can stay stubbed but should add support way way later std::memcpy(output.data(), ¶ms, output.size()); - return 0; + std::memcpy(inline_output.data(), ¶ms.regions, inline_output.size()); + return NvResult::Success; } std::optional<nvhost_as_gpu::BufferMap> nvhost_as_gpu::FindBufferMap(GPUVAddr gpu_addr) const { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index fcdb40d93..2bd355af9 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -30,9 +30,13 @@ public: explicit nvhost_as_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); ~nvhost_as_gpu() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; private: class BufferMap final { @@ -74,32 +78,21 @@ private: bool is_allocated{}; }; - enum class IoctlCommand : u32_le { - IocInitalizeExCommand = 0x40284109, - IocAllocateSpaceCommand = 0xC0184102, - IocRemapCommand = 0x00000014, - IocMapBufferExCommand = 0xC0284106, - IocBindChannelCommand = 0x40044101, - IocGetVaRegionsCommand = 0xC0404108, - IocUnmapBufferCommand = 0xC0084105, - IocFreeSpaceCommand = 0xC0104103, - }; - struct IoctlInitalizeEx { - u32_le big_page_size; // depends on GPU's available_big_page_sizes; 0=default - s32_le as_fd; // ignored; passes 0 - u32_le flags; // passes 0 - u32_le reserved; // ignored; passes 0 - u64_le unk0; - u64_le unk1; - u64_le unk2; + u32_le big_page_size{}; // depends on GPU's available_big_page_sizes; 0=default + s32_le as_fd{}; // ignored; passes 0 + u32_le flags{}; // passes 0 + u32_le reserved{}; // ignored; passes 0 + u64_le unk0{}; + u64_le unk1{}; + u64_le unk2{}; }; static_assert(sizeof(IoctlInitalizeEx) == 40, "IoctlInitalizeEx is incorrect size"); struct IoctlAllocSpace { - u32_le pages; - u32_le page_size; - AddressSpaceFlags flags; + u32_le pages{}; + u32_le page_size{}; + AddressSpaceFlags flags{}; INSERT_PADDING_WORDS(1); union { u64_le offset; @@ -109,70 +102,73 @@ private: static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); struct IoctlFreeSpace { - u64_le offset; - u32_le pages; - u32_le page_size; + u64_le offset{}; + u32_le pages{}; + u32_le page_size{}; }; static_assert(sizeof(IoctlFreeSpace) == 16, "IoctlFreeSpace is incorrect size"); struct IoctlRemapEntry { - u16_le flags; - u16_le kind; - u32_le nvmap_handle; - u32_le map_offset; - u32_le offset; - u32_le pages; + u16_le flags{}; + u16_le kind{}; + u32_le nvmap_handle{}; + u32_le map_offset{}; + u32_le offset{}; + u32_le pages{}; }; static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size"); struct IoctlMapBufferEx { - AddressSpaceFlags flags; // bit0: fixed_offset, bit2: cacheable - u32_le kind; // -1 is default - u32_le nvmap_handle; - u32_le page_size; // 0 means don't care - s64_le buffer_offset; - u64_le mapping_size; - s64_le offset; + AddressSpaceFlags flags{}; // bit0: fixed_offset, bit2: cacheable + u32_le kind{}; // -1 is default + u32_le nvmap_handle{}; + u32_le page_size{}; // 0 means don't care + s64_le buffer_offset{}; + u64_le mapping_size{}; + s64_le offset{}; }; static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size"); struct IoctlUnmapBuffer { - s64_le offset; + s64_le offset{}; }; static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size"); struct IoctlBindChannel { - u32_le fd; + s32_le fd{}; }; static_assert(sizeof(IoctlBindChannel) == 4, "IoctlBindChannel is incorrect size"); struct IoctlVaRegion { - u64_le offset; - u32_le page_size; + u64_le offset{}; + u32_le page_size{}; INSERT_PADDING_WORDS(1); - u64_le pages; + u64_le pages{}; }; static_assert(sizeof(IoctlVaRegion) == 24, "IoctlVaRegion is incorrect size"); struct IoctlGetVaRegions { - u64_le buf_addr; // (contained output user ptr on linux, ignored) - u32_le buf_size; // forced to 2*sizeof(struct va_region) - u32_le reserved; - IoctlVaRegion regions[2]; + u64_le buf_addr{}; // (contained output user ptr on linux, ignored) + u32_le buf_size{}; // forced to 2*sizeof(struct va_region) + u32_le reserved{}; + IoctlVaRegion regions[2]{}; }; static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2, "IoctlGetVaRegions is incorrect size"); - u32 channel{}; + s32 channel{}; + + NvResult InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); + NvResult AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); + NvResult Remap(const std::vector<u8>& input, std::vector<u8>& output); + NvResult MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); + NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); + NvResult FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); + NvResult BindChannel(const std::vector<u8>& input, std::vector<u8>& output); - u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); - u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); - u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); - u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); - u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - u32 FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); - u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); - u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetVARegions(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output); std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 8356a8139..92d31b620 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -20,41 +20,56 @@ nvhost_ctrl::nvhost_ctrl(Core::System& system, EventInterface& events_interface, : nvdevice(system), events_interface{events_interface}, syncpoint_manager{syncpoint_manager} {} nvhost_ctrl::~nvhost_ctrl() = default; -u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocGetConfigCommand: - return NvOsGetConfigU32(input, output); - case IoctlCommand::IocCtrlEventWaitCommand: - return IocCtrlEventWait(input, output, false, ctrl); - case IoctlCommand::IocCtrlEventWaitAsyncCommand: - return IocCtrlEventWait(input, output, true, ctrl); - case IoctlCommand::IocCtrlEventRegisterCommand: - return IocCtrlEventRegister(input, output); - case IoctlCommand::IocCtrlEventUnregisterCommand: - return IocCtrlEventUnregister(input, output); - case IoctlCommand::IocCtrlClearEventWaitCommand: - return IocCtrlClearEventWait(input, output); +NvResult nvhost_ctrl::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 0x0: + switch (command.cmd) { + case 0x1b: + return NvOsGetConfigU32(input, output); + case 0x1c: + return IocCtrlClearEventWait(input, output); + case 0x1d: + return IocCtrlEventWait(input, output, false, ctrl); + case 0x1e: + return IocCtrlEventWait(input, output, true, ctrl); + case 0x1f: + return IocCtrlEventRegister(input, output); + case 0x20: + return IocCtrlEventUnregister(input, output); + } + break; default: - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; + break; } + + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_ctrl::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_ctrl::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } -u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { IocGetConfigParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(), params.param_str.data()); - return 0x30006; // Returns error on production mode + return NvResult::ConfigVarNotFound; // Returns error on production mode } -u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, - bool is_async, IoctlCtrl& ctrl) { +NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, + bool is_async, IoctlCtrl& ctrl) { IocCtrlEventWaitParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "syncpt_id={}, threshold={}, timeout={}, is_async={}", @@ -139,7 +154,7 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& return NvResult::BadParameter; } -u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) { IocCtrlEventRegisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; @@ -154,7 +169,8 @@ u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector< return NvResult::Success; } -u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, + std::vector<u8>& output) { IocCtrlEventUnregisterParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); const u32 event_id = params.user_event_id & 0x00FF; @@ -169,7 +185,7 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vecto return NvResult::Success; } -u32 nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) { IocCtrlEventSignalParams params{}; std::memcpy(¶ms, input.data(), sizeof(params)); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 24ad96cb9..107168e21 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -18,132 +18,116 @@ public: SyncpointManager& syncpoint_manager); ~nvhost_ctrl() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; private: - enum class IoctlCommand : u32_le { - IocSyncptReadCommand = 0xC0080014, - IocSyncptIncrCommand = 0x40040015, - IocSyncptWaitCommand = 0xC00C0016, - IocModuleMutexCommand = 0x40080017, - IocModuleRegRDWRCommand = 0xC0180018, - IocSyncptWaitexCommand = 0xC0100019, - IocSyncptReadMaxCommand = 0xC008001A, - IocGetConfigCommand = 0xC183001B, - IocCtrlClearEventWaitCommand = 0xC004001C, - IocCtrlEventWaitCommand = 0xC010001D, - IocCtrlEventWaitAsyncCommand = 0xC010001E, - IocCtrlEventRegisterCommand = 0xC004001F, - IocCtrlEventUnregisterCommand = 0xC0040020, - IocCtrlEventKillCommand = 0x40080021, - }; struct IocSyncptReadParams { - u32_le id; - u32_le value; + u32_le id{}; + u32_le value{}; }; static_assert(sizeof(IocSyncptReadParams) == 8, "IocSyncptReadParams is incorrect size"); struct IocSyncptIncrParams { - u32_le id; + u32_le id{}; }; static_assert(sizeof(IocSyncptIncrParams) == 4, "IocSyncptIncrParams is incorrect size"); struct IocSyncptWaitParams { - u32_le id; - u32_le thresh; - s32_le timeout; + u32_le id{}; + u32_le thresh{}; + s32_le timeout{}; }; static_assert(sizeof(IocSyncptWaitParams) == 12, "IocSyncptWaitParams is incorrect size"); struct IocModuleMutexParams { - u32_le id; - u32_le lock; // (0 = unlock and 1 = lock) + u32_le id{}; + u32_le lock{}; // (0 = unlock and 1 = lock) }; static_assert(sizeof(IocModuleMutexParams) == 8, "IocModuleMutexParams is incorrect size"); struct IocModuleRegRDWRParams { - u32_le id; - u32_le num_offsets; - u32_le block_size; - u32_le offsets; - u32_le values; - u32_le write; + u32_le id{}; + u32_le num_offsets{}; + u32_le block_size{}; + u32_le offsets{}; + u32_le values{}; + u32_le write{}; }; static_assert(sizeof(IocModuleRegRDWRParams) == 24, "IocModuleRegRDWRParams is incorrect size"); struct IocSyncptWaitexParams { - u32_le id; - u32_le thresh; - s32_le timeout; - u32_le value; + u32_le id{}; + u32_le thresh{}; + s32_le timeout{}; + u32_le value{}; }; static_assert(sizeof(IocSyncptWaitexParams) == 16, "IocSyncptWaitexParams is incorrect size"); struct IocSyncptReadMaxParams { - u32_le id; - u32_le value; + u32_le id{}; + u32_le value{}; }; static_assert(sizeof(IocSyncptReadMaxParams) == 8, "IocSyncptReadMaxParams is incorrect size"); struct IocGetConfigParams { - std::array<char, 0x41> domain_str; - std::array<char, 0x41> param_str; - std::array<char, 0x101> config_str; + std::array<char, 0x41> domain_str{}; + std::array<char, 0x41> param_str{}; + std::array<char, 0x101> config_str{}; }; static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size"); struct IocCtrlEventSignalParams { - u32_le event_id; + u32_le event_id{}; }; static_assert(sizeof(IocCtrlEventSignalParams) == 4, "IocCtrlEventSignalParams is incorrect size"); struct IocCtrlEventWaitParams { - u32_le syncpt_id; - u32_le threshold; - s32_le timeout; - u32_le value; + u32_le syncpt_id{}; + u32_le threshold{}; + s32_le timeout{}; + u32_le value{}; }; static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size"); struct IocCtrlEventWaitAsyncParams { - u32_le syncpt_id; - u32_le threshold; - u32_le timeout; - u32_le value; + u32_le syncpt_id{}; + u32_le threshold{}; + u32_le timeout{}; + u32_le value{}; }; static_assert(sizeof(IocCtrlEventWaitAsyncParams) == 16, "IocCtrlEventWaitAsyncParams is incorrect size"); struct IocCtrlEventRegisterParams { - u32_le user_event_id; + u32_le user_event_id{}; }; static_assert(sizeof(IocCtrlEventRegisterParams) == 4, "IocCtrlEventRegisterParams is incorrect size"); struct IocCtrlEventUnregisterParams { - u32_le user_event_id; + u32_le user_event_id{}; }; static_assert(sizeof(IocCtrlEventUnregisterParams) == 4, "IocCtrlEventUnregisterParams is incorrect size"); struct IocCtrlEventKill { - u64_le user_events; + u64_le user_events{}; }; static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size"); - u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); - - u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async, - IoctlCtrl& ctrl); - - u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); - - u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); - - u32 IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); + NvResult NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async, + IoctlCtrl& ctrl); + NvResult IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output); EventInterface& events_interface; SyncpointManager& syncpoint_manager; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index fba89e7a6..647f5907e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -15,39 +15,68 @@ namespace Service::Nvidia::Devices { nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system) : nvdevice(system) {} nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default; -u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, - const std::vector<u8>& input2, std::vector<u8>& output, - std::vector<u8>& output2, IoctlCtrl& ctrl, IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocGetCharacteristicsCommand: - return GetCharacteristics(input, output, output2, version); - case IoctlCommand::IocGetTPCMasksCommand: - return GetTPCMasks(input, output, output2, version); - case IoctlCommand::IocGetActiveSlotMaskCommand: - return GetActiveSlotMask(input, output); - case IoctlCommand::IocZcullGetCtxSizeCommand: - return ZCullGetCtxSize(input, output); - case IoctlCommand::IocZcullGetInfo: - return ZCullGetInfo(input, output); - case IoctlCommand::IocZbcSetTable: - return ZBCSetTable(input, output); - case IoctlCommand::IocZbcQueryTable: - return ZBCQueryTable(input, output); - case IoctlCommand::IocFlushL2: - return FlushL2(input, output); - case IoctlCommand::IocGetGpuTime: - return GetGpuTime(input, output); +NvResult nvhost_ctrl_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, IoctlCtrl& ctrl) { + switch (command.group) { + case 'G': + switch (command.cmd) { + case 0x1: + return ZCullGetCtxSize(input, output); + case 0x2: + return ZCullGetInfo(input, output); + case 0x3: + return ZBCSetTable(input, output); + case 0x4: + return ZBCQueryTable(input, output); + case 0x5: + return GetCharacteristics(input, output); + case 0x6: + return GetTPCMasks(input, output); + case 0x7: + return FlushL2(input, output); + case 0x14: + return GetActiveSlotMask(input, output); + case 0x1c: + return GetGpuTime(input, output); + default: + break; + } + break; + } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_ctrl_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_ctrl_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, std::vector<u8>& inline_output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 'G': + switch (command.cmd) { + case 0x5: + return GetCharacteristics(input, output, inline_output); + case 0x6: + return GetTPCMasks(input, output, inline_output); + default: + break; + } + break; default: - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; + break; } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } -u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& output2, IoctlVersion version) { +NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, + std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlCharacteristics params{}; std::memcpy(¶ms, input.data(), input.size()); @@ -88,36 +117,83 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto params.gc.gr_compbit_store_base_hw = 0x0; params.gpu_characteristics_buf_size = 0xA0; params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) + std::memcpy(output.data(), ¶ms, output.size()); + return NvResult::Success; +} - if (version == IoctlVersion::Version3) { - std::memcpy(output.data(), input.data(), output.size()); - std::memcpy(output2.data(), ¶ms.gc, output2.size()); - } else { - std::memcpy(output.data(), ¶ms, output.size()); - } - return 0; +NvResult nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output) { + LOG_DEBUG(Service_NVDRV, "called"); + IoctlCharacteristics params{}; + std::memcpy(¶ms, input.data(), input.size()); + params.gc.arch = 0x120; + params.gc.impl = 0xb; + params.gc.rev = 0xa1; + params.gc.num_gpc = 0x1; + params.gc.l2_cache_size = 0x40000; + params.gc.on_board_video_memory_size = 0x0; + params.gc.num_tpc_per_gpc = 0x2; + params.gc.bus_type = 0x20; + params.gc.big_page_size = 0x20000; + params.gc.compression_page_size = 0x20000; + params.gc.pde_coverage_bit_count = 0x1B; + params.gc.available_big_page_sizes = 0x30000; + params.gc.gpc_mask = 0x1; + params.gc.sm_arch_sm_version = 0x503; + params.gc.sm_arch_spa_version = 0x503; + params.gc.sm_arch_warp_count = 0x80; + params.gc.gpu_va_bit_count = 0x28; + params.gc.reserved = 0x0; + params.gc.flags = 0x55; + params.gc.twod_class = 0x902D; + params.gc.threed_class = 0xB197; + params.gc.compute_class = 0xB1C0; + params.gc.gpfifo_class = 0xB06F; + params.gc.inline_to_memory_class = 0xA140; + params.gc.dma_copy_class = 0xB0B5; + params.gc.max_fbps_count = 0x1; + params.gc.fbp_en_mask = 0x0; + params.gc.max_ltc_per_fbp = 0x2; + params.gc.max_lts_per_ltc = 0x1; + params.gc.max_tex_per_tpc = 0x0; + params.gc.max_gpc_count = 0x1; + params.gc.rop_l2_en_mask_0 = 0x21D70; + params.gc.rop_l2_en_mask_1 = 0x0; + params.gc.chipname = 0x6230326D67; + params.gc.gr_compbit_store_base_hw = 0x0; + params.gpu_characteristics_buf_size = 0xA0; + params.gpu_characteristics_buf_addr = 0xdeadbeef; // Cannot be 0 (UNUSED) + + std::memcpy(output.data(), ¶ms, output.size()); + std::memcpy(inline_output.data(), ¶ms.gc, inline_output.size()); + return NvResult::Success; } -u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& output2, IoctlVersion version) { +NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { IoctlGpuGetTpcMasksArgs params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); if (params.mask_buffer_size != 0) { params.tcp_mask = 3; } + std::memcpy(output.data(), ¶ms, output.size()); + return NvResult::Success; +} - if (version == IoctlVersion::Version3) { - std::memcpy(output.data(), input.data(), output.size()); - std::memcpy(output2.data(), ¶ms.tcp_mask, output2.size()); - } else { - std::memcpy(output.data(), ¶ms, output.size()); +NvResult nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output) { + IoctlGpuGetTpcMasksArgs params{}; + std::memcpy(¶ms, input.data(), input.size()); + LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size); + if (params.mask_buffer_size != 0) { + params.tcp_mask = 3; } - - return 0; + std::memcpy(output.data(), ¶ms, output.size()); + std::memcpy(inline_output.data(), ¶ms.tcp_mask, inline_output.size()); + return NvResult::Success; } -u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlActiveSlotMask params{}; @@ -127,10 +203,10 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector params.slot = 0x07; params.mask = 0x01; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlZcullGetCtxSize params{}; @@ -139,10 +215,10 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u } params.size = 0x1; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlNvgpuGpuZcullGetInfoArgs params{}; @@ -162,47 +238,47 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& params.subregion_height_align_pixels = 0x40; params.subregion_count = 0x10; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcSetTable params{}; std::memcpy(¶ms, input.data(), input.size()); // TODO(ogniK): What does this even actually do? std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlZbcQueryTable params{}; std::memcpy(¶ms, input.data(), input.size()); // TODO : To implement properly std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::FlushL2(const std::vector<u8>& input, std::vector<u8>& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); IoctlFlushL2 params{}; std::memcpy(¶ms, input.data(), input.size()); // TODO : To implement properly std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlGetGpuTime params{}; std::memcpy(¶ms, input.data(), input.size()); params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count()); std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index ef60f72ce..c2fffe734 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -16,32 +16,15 @@ public: explicit nvhost_ctrl_gpu(Core::System& system); ~nvhost_ctrl_gpu() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; private: - enum class IoctlCommand : u32_le { - IocGetCharacteristicsCommand = 0xC0B04705, - IocGetTPCMasksCommand = 0xC0184706, - IocGetActiveSlotMaskCommand = 0x80084714, - IocZcullGetCtxSizeCommand = 0x80044701, - IocZcullGetInfo = 0x80284702, - IocZbcSetTable = 0x402C4703, - IocZbcQueryTable = 0xC0344704, - IocFlushL2 = 0x40084707, - IocInvalICache = 0x4008470D, - IocSetMmudebugMode = 0x4008470E, - IocSetSmDebugMode = 0x4010470F, - IocWaitForPause = 0xC0084710, - IocGetTcpExceptionEnStatus = 0x80084711, - IocNumVsms = 0x80084712, - IocVsmsMapping = 0xC0044713, - IocGetErrorChannelUserData = 0xC008471B, - IocGetGpuTime = 0xC010471C, - IocGetCpuTimeCorrelationInfo = 0xC108471D, - }; - struct IoctlGpuCharacteristics { u32_le arch; // 0x120 (NVGPU_GPU_ARCH_GM200) u32_le impl; // 0xB (NVGPU_GPU_IMPL_GM20B) @@ -159,17 +142,21 @@ private: }; static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); - u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, - std::vector<u8>& output2, IoctlVersion version); - u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, std::vector<u8>& output2, - IoctlVersion version); - u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); - u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); - u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); - u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); - u32 ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); - u32 FlushL2(const std::vector<u8>& input, std::vector<u8>& output); - u32 GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output); + + NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output); + + NvResult GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output); + NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index b1d9d55b5..b0c2caba5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -23,107 +23,134 @@ nvhost_gpu::nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, nvhost_gpu::~nvhost_gpu() = default; -u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocSetNVMAPfdCommand: - return SetNVMAPfd(input, output); - case IoctlCommand::IocSetClientDataCommand: - return SetClientData(input, output); - case IoctlCommand::IocGetClientDataCommand: - return GetClientData(input, output); - case IoctlCommand::IocZCullBind: - return ZCullBind(input, output); - case IoctlCommand::IocSetErrorNotifierCommand: - return SetErrorNotifier(input, output); - case IoctlCommand::IocChannelSetPriorityCommand: - return SetChannelPriority(input, output); - case IoctlCommand::IocAllocGPFIFOEx2Command: - return AllocGPFIFOEx2(input, output); - case IoctlCommand::IocAllocObjCtxCommand: - return AllocateObjectContext(input, output); - case IoctlCommand::IocChannelGetWaitbaseCommand: - return GetWaitbase(input, output); - case IoctlCommand::IocChannelSetTimeoutCommand: - return ChannelSetTimeout(input, output); - case IoctlCommand::IocChannelSetTimeslice: - return ChannelSetTimeslice(input, output); - default: +NvResult nvhost_gpu::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 0x0: + switch (command.cmd) { + case 0x3: + return GetWaitbase(input, output); + default: + break; + } + break; + case 'H': + switch (command.cmd) { + case 0x1: + return SetNVMAPfd(input, output); + case 0x3: + return ChannelSetTimeout(input, output); + case 0x8: + return SubmitGPFIFOBase(input, output, false); + case 0x9: + return AllocateObjectContext(input, output); + case 0xb: + return ZCullBind(input, output); + case 0xc: + return SetErrorNotifier(input, output); + case 0xd: + return SetChannelPriority(input, output); + case 0x1a: + return AllocGPFIFOEx2(input, output); + case 0x1b: + return SubmitGPFIFOBase(input, output, true); + case 0x1d: + return ChannelSetTimeslice(input, output); + default: + break; + } + break; + case 'G': + switch (command.cmd) { + case 0x14: + return SetClientData(input, output); + case 0x15: + return GetClientData(input, output); + default: + break; + } break; } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +}; - if (command.group == NVGPU_IOCTL_MAGIC) { - if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { - return SubmitGPFIFO(input, output); - } - if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) { - return KickoffPB(input, output, input2, version); +NvResult nvhost_gpu::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 'H': + switch (command.cmd) { + case 0x1b: + return SubmitGPFIFOBase(input, inline_input, output); } + break; } + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; -}; +NvResult nvhost_gpu::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} -u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); nvmap_fd = params.nvmap_fd; - return 0; + return NvResult::Success; } -u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; std::memcpy(¶ms, input.data(), input.size()); user_data = params.data; - return 0; + return NvResult::Success; } -u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { LOG_DEBUG(Service_NVDRV, "called"); IoctlClientData params{}; std::memcpy(¶ms, input.data(), input.size()); params.data = user_data; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { std::memcpy(&zcull_params, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va, zcull_params.mode); std::memcpy(output.data(), &zcull_params, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { IoctlSetErrorNotifier params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset, params.size, params.mem); std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { std::memcpy(&channel_priority, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { IoctlAllocGpfifoEx2 params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, @@ -137,10 +164,10 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou params.fence_out = channel_fence; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { IoctlAllocObjCtx params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num, @@ -148,7 +175,7 @@ u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector< params.obj_id = 0x0; std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) { @@ -192,8 +219,8 @@ static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(Fence return result; } -u32 nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, - Tegra::CommandList&& entries) { +NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, + Tegra::CommandList&& entries) { LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address, params.num_entries, params.flags.raw); @@ -227,69 +254,70 @@ u32 nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& out } std::memcpy(output.data(), ¶ms, sizeof(IoctlSubmitGpfifo)); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, + bool kickoff) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); + return NvResult::InvalidSize; } IoctlSubmitGpfifo params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); - Tegra::CommandList entries(params.num_entries); - std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], - params.num_entries * sizeof(Tegra::CommandListHeader)); + + if (kickoff) { + system.Memory().ReadBlock(params.address, entries.command_lists.data(), + params.num_entries * sizeof(Tegra::CommandListHeader)); + } else { + std::memcpy(entries.command_lists.data(), &input[sizeof(IoctlSubmitGpfifo)], + params.num_entries * sizeof(Tegra::CommandListHeader)); + } return SubmitGPFIFOImpl(params, output, std::move(entries)); } -u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, - const std::vector<u8>& input2, IoctlVersion version) { +NvResult nvhost_gpu::SubmitGPFIFOBase(const std::vector<u8>& input, + const std::vector<u8>& input_inline, + std::vector<u8>& output) { if (input.size() < sizeof(IoctlSubmitGpfifo)) { UNIMPLEMENTED(); + return NvResult::InvalidSize; } IoctlSubmitGpfifo params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmitGpfifo)); - Tegra::CommandList entries(params.num_entries); - if (version == IoctlVersion::Version2) { - std::memcpy(entries.command_lists.data(), input2.data(), - params.num_entries * sizeof(Tegra::CommandListHeader)); - } else { - system.Memory().ReadBlock(params.address, entries.command_lists.data(), - params.num_entries * sizeof(Tegra::CommandListHeader)); - } - + std::memcpy(entries.command_lists.data(), input_inline.data(), input_inline.size()); return SubmitGPFIFOImpl(params, output, std::move(entries)); } -u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { IoctlGetWaitbase params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown); params.value = 0; // Seems to be hard coded at 0 std::memcpy(output.data(), ¶ms, output.size()); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) { IoctlChannelSetTimeout params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlChannelSetTimeout)); LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); - return 0; + return NvResult::Success; } -u32 nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output) { IoctlSetTimeslice params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetTimeslice)); LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); channel_timeslice = params.timeslice; - return 0; + return NvResult::Success; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index a252fc06d..aa0048a9d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -20,43 +20,21 @@ class SyncpointManager; namespace Service::Nvidia::Devices { class nvmap; -constexpr u32 NVGPU_IOCTL_MAGIC('H'); -constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); -constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b); - class nvhost_gpu final : public nvdevice { public: explicit nvhost_gpu(Core::System& system, std::shared_ptr<nvmap> nvmap_dev, SyncpointManager& syncpoint_manager); ~nvhost_gpu() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; private: - enum class IoctlCommand : u32_le { - IocSetNVMAPfdCommand = 0x40044801, - IocAllocGPFIFOCommand = 0x40084805, - IocSetClientDataCommand = 0x40084714, - IocGetClientDataCommand = 0x80084715, - IocZCullBind = 0xc010480b, - IocSetErrorNotifierCommand = 0xC018480C, - IocChannelSetPriorityCommand = 0x4004480D, - IocEnableCommand = 0x0000480E, - IocDisableCommand = 0x0000480F, - IocPreemptCommand = 0x00004810, - IocForceResetCommand = 0x00004811, - IocEventIdControlCommand = 0x40084812, - IocGetErrorNotificationCommand = 0xC0104817, - IocAllocGPFIFOExCommand = 0x40204818, - IocAllocGPFIFOEx2Command = 0xC020481A, - IocAllocObjCtxCommand = 0xC0104809, - IocChannelGetWaitbaseCommand = 0xC0080003, - IocChannelSetTimeoutCommand = 0x40044803, - IocChannelSetTimeslice = 0xC004481D, - }; - enum class CtxObjects : u32_le { Ctx2D = 0x902D, Ctx3D = 0xB197, @@ -67,63 +45,63 @@ private: }; struct IoctlSetNvmapFD { - u32_le nvmap_fd; + s32_le nvmap_fd{}; }; static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); struct IoctlChannelSetTimeout { - u32_le timeout; + u32_le timeout{}; }; static_assert(sizeof(IoctlChannelSetTimeout) == 4, "IoctlChannelSetTimeout is incorrect size"); struct IoctlAllocGPFIFO { - u32_le num_entries; - u32_le flags; + u32_le num_entries{}; + u32_le flags{}; }; static_assert(sizeof(IoctlAllocGPFIFO) == 8, "IoctlAllocGPFIFO is incorrect size"); struct IoctlClientData { - u64_le data; + u64_le data{}; }; static_assert(sizeof(IoctlClientData) == 8, "IoctlClientData is incorrect size"); struct IoctlZCullBind { - u64_le gpu_va; - u32_le mode; // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf + u64_le gpu_va{}; + u32_le mode{}; // 0=global, 1=no_ctxsw, 2=separate_buffer, 3=part_of_regular_buf INSERT_PADDING_WORDS(1); }; static_assert(sizeof(IoctlZCullBind) == 16, "IoctlZCullBind is incorrect size"); struct IoctlSetErrorNotifier { - u64_le offset; - u64_le size; - u32_le mem; // nvmap object handle + u64_le offset{}; + u64_le size{}; + u32_le mem{}; // nvmap object handle INSERT_PADDING_WORDS(1); }; static_assert(sizeof(IoctlSetErrorNotifier) == 24, "IoctlSetErrorNotifier is incorrect size"); struct IoctlChannelSetPriority { - u32_le priority; + u32_le priority{}; }; static_assert(sizeof(IoctlChannelSetPriority) == 4, "IoctlChannelSetPriority is incorrect size"); struct IoctlSetTimeslice { - u32_le timeslice; + u32_le timeslice{}; }; static_assert(sizeof(IoctlSetTimeslice) == 4, "IoctlSetTimeslice is incorrect size"); struct IoctlEventIdControl { - u32_le cmd; // 0=disable, 1=enable, 2=clear - u32_le id; + u32_le cmd{}; // 0=disable, 1=enable, 2=clear + u32_le id{}; }; static_assert(sizeof(IoctlEventIdControl) == 8, "IoctlEventIdControl is incorrect size"); struct IoctlGetErrorNotification { - u64_le timestamp; - u32_le info32; - u16_le info16; - u16_le status; // always 0xFFFF + u64_le timestamp{}; + u32_le info32{}; + u16_le info16{}; + u16_le status{}; // always 0xFFFF }; static_assert(sizeof(IoctlGetErrorNotification) == 16, "IoctlGetErrorNotification is incorrect size"); @@ -131,39 +109,39 @@ private: static_assert(sizeof(Fence) == 8, "Fence is incorrect size"); struct IoctlAllocGpfifoEx { - u32_le num_entries; - u32_le flags; - u32_le unk0; - u32_le unk1; - u32_le unk2; - u32_le unk3; - u32_le unk4; - u32_le unk5; + u32_le num_entries{}; + u32_le flags{}; + u32_le unk0{}; + u32_le unk1{}; + u32_le unk2{}; + u32_le unk3{}; + u32_le unk4{}; + u32_le unk5{}; }; static_assert(sizeof(IoctlAllocGpfifoEx) == 32, "IoctlAllocGpfifoEx is incorrect size"); struct IoctlAllocGpfifoEx2 { - u32_le num_entries; // in - u32_le flags; // in - u32_le unk0; // in (1 works) - Fence fence_out; // out - u32_le unk1; // in - u32_le unk2; // in - u32_le unk3; // in + u32_le num_entries{}; // in + u32_le flags{}; // in + u32_le unk0{}; // in (1 works) + Fence fence_out{}; // out + u32_le unk1{}; // in + u32_le unk2{}; // in + u32_le unk3{}; // in }; static_assert(sizeof(IoctlAllocGpfifoEx2) == 32, "IoctlAllocGpfifoEx2 is incorrect size"); struct IoctlAllocObjCtx { - u32_le class_num; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, - // 0xB06F=channel_gpfifo - u32_le flags; - u64_le obj_id; // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported + u32_le class_num{}; // 0x902D=2d, 0xB197=3d, 0xB1C0=compute, 0xA140=kepler, 0xB0B5=DMA, + // 0xB06F=channel_gpfifo + u32_le flags{}; + u64_le obj_id{}; // (ignored) used for FREE_OBJ_CTX ioctl, which is not supported }; static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size"); struct IoctlSubmitGpfifo { - u64_le address; // pointer to gpfifo entry structs - u32_le num_entries; // number of fence objects being submitted + u64_le address{}; // pointer to gpfifo entry structs + u32_le num_entries{}; // number of fence objects being submitted union { u32_le raw; BitField<0, 1, u32_le> add_wait; // append a wait sync_point to the list @@ -172,7 +150,7 @@ private: BitField<4, 1, u32_le> suppress_wfi; // suppress wait for interrupt BitField<8, 1, u32_le> increment; // increment the returned fence } flags; - Fence fence_out; // returned new fence object for others to wait on + Fence fence_out{}; // returned new fence object for others to wait on u32 AddIncrementValue() const { return flags.add_increment.Value() << 1; @@ -182,33 +160,34 @@ private: "IoctlSubmitGpfifo is incorrect size"); struct IoctlGetWaitbase { - u32 unknown; // seems to be ignored? Nintendo added this - u32 value; + u32 unknown{}; // seems to be ignored? Nintendo added this + u32 value{}; }; static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size"); - u32_le nvmap_fd{}; + s32_le nvmap_fd{}; u64_le user_data{}; IoctlZCullBind zcull_params{}; u32_le channel_priority{}; u32_le channel_timeslice{}; - u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); - u32 SetClientData(const std::vector<u8>& input, std::vector<u8>& output); - u32 GetClientData(const std::vector<u8>& input, std::vector<u8>& output); - u32 ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); - u32 SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); - u32 SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); - u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); - u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); - u32 SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, - Tegra::CommandList&& entries); - u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); - u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output, - const std::vector<u8>& input2, IoctlVersion version); - u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); - u32 ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetClientData(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetClientData(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ZCullBind(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output); + NvResult AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); + NvResult AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output, + Tegra::CommandList&& entries); + NvResult SubmitGPFIFOBase(const std::vector<u8>& input, std::vector<u8>& output, + bool kickoff = false); + NvResult SubmitGPFIFOBase(const std::vector<u8>& input, const std::vector<u8>& input_inline, + std::vector<u8>& output); + NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); + NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output); std::shared_ptr<nvmap> nvmap_dev; SyncpointManager& syncpoint_manager; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index b6df48360..b8328c314 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -15,46 +15,59 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_de : nvhost_nvdec_common(system, std::move(nvmap_dev)) {} nvhost_nvdec::~nvhost_nvdec() = default; -u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocSetNVMAPfdCommand: - return SetNVMAPfd(input); - case IoctlCommand::IocSubmit: - return Submit(input, output); - case IoctlCommand::IocGetSyncpoint: - return GetSyncpoint(input, output); - case IoctlCommand::IocGetWaitbase: - return GetWaitbase(input, output); - case IoctlCommand::IocMapBuffer: - case IoctlCommand::IocMapBuffer2: - case IoctlCommand::IocMapBuffer3: - case IoctlCommand::IocMapBufferEx: - return MapBuffer(input, output); - case IoctlCommand::IocUnmapBufferEx: { - // This command is sent when the video stream has ended, flush all video contexts - // This is usually sent in the folowing order: vic, nvdec, vic. - // Inform the GPU to clear any remaining nvdec buffers when this is detected. - LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); - Tegra::ChCommandHeaderList cmdlist(1); - cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; - system.GPU().PushCommandBuffer(cmdlist); - [[fallthrough]]; // fallthrough to unmap buffers - }; - case IoctlCommand::IocUnmapBuffer: - case IoctlCommand::IocUnmapBuffer2: - case IoctlCommand::IocUnmapBuffer3: - return UnmapBuffer(input, output); - case IoctlCommand::IocSetSubmitTimeout: - return SetSubmitTimeout(input, output); +NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 0x0: + switch (command.cmd) { + case 0x1: + return Submit(input, output); + case 0x2: + return GetSyncpoint(input, output); + case 0x3: + return GetWaitbase(input, output); + case 0x7: + return SetSubmitTimeout(input, output); + case 0x9: + return MapBuffer(input, output); + case 0xa: { + if (command.length == 0x1c) { + LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); + Tegra::ChCommandHeaderList cmdlist(1); + cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; + system.GPU().PushCommandBuffer(cmdlist); + } + return UnmapBuffer(input, output); + } + default: + break; + } + break; + case 'H': + switch (command.cmd) { + case 0x1: + return SetNVMAPfd(input); + default: + break; + } + break; } - UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); - return 0; + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_nvdec::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_nvdec::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 102777ddd..884ed6c5b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h @@ -14,26 +14,13 @@ public: explicit nvhost_nvdec(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); ~nvhost_nvdec() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; - -private: - enum class IoctlCommand : u32_le { - IocSetNVMAPfdCommand = 0x40044801, - IocSubmit = 0xC0400001, - IocGetSyncpoint = 0xC0080002, - IocGetWaitbase = 0xC0080003, - IocMapBuffer = 0xC01C0009, - IocMapBuffer2 = 0xC16C0009, - IocMapBuffer3 = 0xC15C0009, - IocMapBufferEx = 0xC0A40009, - IocUnmapBuffer = 0xC0A4000A, - IocUnmapBuffer2 = 0xC16C000A, - IocUnmapBufferEx = 0xC01C000A, - IocUnmapBuffer3 = 0xC15C000A, - IocSetSubmitTimeout = 0x40040007, - }; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 30f03f845..b49cecb42 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp @@ -36,26 +36,20 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s } } // Anonymous namespace -namespace NvErrCodes { -constexpr u32 Success{}; -[[maybe_unused]] constexpr u32 OutOfMemory{static_cast<u32>(-12)}; -constexpr u32 InvalidInput{static_cast<u32>(-22)}; -} // namespace NvErrCodes - nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) : nvdevice(system), nvmap_dev(std::move(nvmap_dev)) {} nvhost_nvdec_common::~nvhost_nvdec_common() = default; -u32 nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { +NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSetNvmapFD)); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); nvmap_fd = params.nvmap_fd; - return 0; + return NvResult::Success; } -u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& output) { IoctlSubmit params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlSubmit)); LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count); @@ -83,12 +77,12 @@ u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& o for (const auto& cmd_buffer : command_buffers) { auto object = nvmap_dev->GetObject(cmd_buffer.memory_id); - ASSERT_OR_EXECUTE(object, return NvErrCodes::InvalidInput;); + ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); const auto map = FindBufferMap(object->dma_map_addr); if (!map) { LOG_ERROR(Service_NVDRV, "Tried to submit an invalid offset 0x{:X} dma 0x{:X}", object->addr, object->dma_map_addr); - return 0; + return NvResult::Success; } Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); gpu.MemoryManager().ReadBlock(map->StartAddr() + cmd_buffer.offset, cmdlist.data(), @@ -105,10 +99,10 @@ u32 nvhost_nvdec_common::Submit(const std::vector<u8>& input, std::vector<u8>& o offset = WriteVectors(output, syncpt_increments, offset); offset = WriteVectors(output, wait_checks, offset); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output) { IoctlGetSyncpoint params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetSyncpoint)); LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param); @@ -118,18 +112,18 @@ u32 nvhost_nvdec_common::GetSyncpoint(const std::vector<u8>& input, std::vector< params.value = 0; std::memcpy(output.data(), ¶ms, sizeof(IoctlGetSyncpoint)); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) { IoctlGetWaitbase params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlGetWaitbase)); params.value = 0; // Seems to be hard coded at 0 std::memcpy(output.data(), ¶ms, sizeof(IoctlGetWaitbase)); - return 0; + return NvResult::Success; } -u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -143,7 +137,7 @@ u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8> if (!object) { LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::InvalidInput; + return NvResult::InvalidState; } if (object->dma_map_addr == 0) { // NVDEC and VIC memory is in the 32-bit address space @@ -165,10 +159,10 @@ u32 nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vector<u8> std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(), cmd_buffer_handles.size() * sizeof(MapBufferEntry)); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) { IoctlMapBuffer params{}; std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer)); std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries); @@ -181,7 +175,7 @@ u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u if (!object) { LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmf_buff.map_handle); std::memcpy(output.data(), ¶ms, output.size()); - return NvErrCodes::InvalidInput; + return NvResult::InvalidState; } if (const auto size{RemoveBufferMap(object->dma_map_addr)}; size) { gpu.MemoryManager().Unmap(object->dma_map_addr, *size); @@ -193,13 +187,14 @@ u32 nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u object->dma_map_addr = 0; } std::memset(output.data(), 0, output.size()); - return NvErrCodes::Success; + return NvResult::Success; } -u32 nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvdec_common::SetSubmitTimeout(const std::vector<u8>& input, + std::vector<u8>& output) { std::memcpy(&submit_timeout, input.data(), input.size()); LOG_WARNING(Service_NVDRV, "(STUBBED) called"); - return NvErrCodes::Success; + return NvResult::Success; } std::optional<nvhost_nvdec_common::BufferMap> nvhost_nvdec_common::FindBufferMap( diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index c249c5349..ab152bf0e 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h @@ -18,9 +18,38 @@ public: explicit nvhost_nvdec_common(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); ~nvhost_nvdec_common() override; - virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) = 0; + /** + * Handles an ioctl1 request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param output A buffer where the output data will be written to. + * @returns The result code of the ioctl. + */ + virtual NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) = 0; + + /** + * Handles an ioctl2 request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param inline_input A buffer containing the input data for the ioctl which has been inlined. + * @param output A buffer where the output data will be written to. + * @returns The result code of the ioctl. + */ + virtual NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) = 0; + + /** + * Handles an ioctl3 request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param output A buffer where the output data will be written to. + * @param inline_output A buffer where the inlined output data will be written to. + * @returns The result code of the ioctl. + */ + virtual NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) = 0; protected: class BufferMap final { @@ -63,102 +92,102 @@ protected: }; struct IoctlSetNvmapFD { - u32_le nvmap_fd; + s32_le nvmap_fd{}; }; static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); struct IoctlSubmitCommandBuffer { - u32_le id; - u32_le offset; - u32_le count; + u32_le id{}; + u32_le offset{}; + u32_le count{}; }; static_assert(sizeof(IoctlSubmitCommandBuffer) == 0xC, "IoctlSubmitCommandBuffer is incorrect size"); struct IoctlSubmit { - u32_le cmd_buffer_count; - u32_le relocation_count; - u32_le syncpoint_count; - u32_le fence_count; + u32_le cmd_buffer_count{}; + u32_le relocation_count{}; + u32_le syncpoint_count{}; + u32_le fence_count{}; }; static_assert(sizeof(IoctlSubmit) == 0x10, "IoctlSubmit has incorrect size"); struct CommandBuffer { - s32 memory_id; - u32 offset; - s32 word_count; + s32 memory_id{}; + u32 offset{}; + s32 word_count{}; }; static_assert(sizeof(CommandBuffer) == 0xC, "CommandBuffer has incorrect size"); struct Reloc { - s32 cmdbuffer_memory; - s32 cmdbuffer_offset; - s32 target; - s32 target_offset; + s32 cmdbuffer_memory{}; + s32 cmdbuffer_offset{}; + s32 target{}; + s32 target_offset{}; }; static_assert(sizeof(Reloc) == 0x10, "CommandBuffer has incorrect size"); struct SyncptIncr { - u32 id; - u32 increments; + u32 id{}; + u32 increments{}; }; static_assert(sizeof(SyncptIncr) == 0x8, "CommandBuffer has incorrect size"); struct Fence { - u32 id; - u32 value; + u32 id{}; + u32 value{}; }; static_assert(sizeof(Fence) == 0x8, "CommandBuffer has incorrect size"); struct IoctlGetSyncpoint { // Input - u32_le param; + u32_le param{}; // Output - u32_le value; + u32_le value{}; }; static_assert(sizeof(IoctlGetSyncpoint) == 8, "IocGetIdParams has wrong size"); struct IoctlGetWaitbase { - u32_le unknown; // seems to be ignored? Nintendo added this - u32_le value; + u32_le unknown{}; // seems to be ignored? Nintendo added this + u32_le value{}; }; static_assert(sizeof(IoctlGetWaitbase) == 0x8, "IoctlGetWaitbase is incorrect size"); struct IoctlMapBuffer { - u32_le num_entries; - u32_le data_address; // Ignored by the driver. - u32_le attach_host_ch_das; + u32_le num_entries{}; + u32_le data_address{}; // Ignored by the driver. + u32_le attach_host_ch_das{}; }; static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); struct IocGetIdParams { // Input - u32_le param; + u32_le param{}; // Output - u32_le value; + u32_le value{}; }; static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); // Used for mapping and unmapping command buffers struct MapBufferEntry { - u32_le map_handle; - u32_le map_address; + u32_le map_handle{}; + u32_le map_address{}; }; static_assert(sizeof(IoctlMapBuffer) == 0x0C, "IoctlMapBuffer is incorrect size"); /// Ioctl command implementations - u32 SetNVMAPfd(const std::vector<u8>& input); - u32 Submit(const std::vector<u8>& input, std::vector<u8>& output); - u32 GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); - u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); - u32 MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); - u32 SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(const std::vector<u8>& input); + NvResult Submit(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetSyncpoint(const std::vector<u8>& input, std::vector<u8>& output); + NvResult GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); + NvResult MapBuffer(const std::vector<u8>& input, std::vector<u8>& output); + NvResult UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetSubmitTimeout(const std::vector<u8>& input, std::vector<u8>& output); std::optional<BufferMap> FindBufferMap(GPUVAddr gpu_addr) const; void AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr, bool is_allocated); std::optional<std::size_t> RemoveBufferMap(GPUVAddr gpu_addr); - u32_le nvmap_fd{}; + s32_le nvmap_fd{}; u32_le submit_timeout{}; std::shared_ptr<nvmap> nvmap_dev; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp index 96e7b7dab..6f4ab0ab3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp @@ -13,28 +13,45 @@ namespace Service::Nvidia::Devices { nvhost_nvjpg::nvhost_nvjpg(Core::System& system) : nvdevice(system) {} nvhost_nvjpg::~nvhost_nvjpg() = default; -u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocSetNVMAPfdCommand: - return SetNVMAPfd(input, output); +NvResult nvhost_nvjpg::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 'H': + switch (command.cmd) { + case 0x1: + return SetNVMAPfd(input, output); + default: + break; + } + break; + default: + break; } - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } -u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvhost_nvjpg::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_nvjpg::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { IoctlSetNvmapFD params{}; std::memcpy(¶ms, input.data(), input.size()); LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); nvmap_fd = params.nvmap_fd; - return 0; + return NvResult::Success; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h index 98dcac52f..6fb99d959 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h @@ -16,23 +16,23 @@ public: explicit nvhost_nvjpg(Core::System& system); ~nvhost_nvjpg() override; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; private: - enum class IoctlCommand : u32_le { - IocSetNVMAPfdCommand = 0x40044801, - }; - struct IoctlSetNvmapFD { - u32_le nvmap_fd; + s32_le nvmap_fd{}; }; static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size"); - u32_le nvmap_fd{}; + s32_le nvmap_fd{}; - u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); + NvResult SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index 60db54d00..55a17f423 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -15,36 +15,52 @@ nvhost_vic::nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev) nvhost_vic::~nvhost_vic() = default; -u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", - command.raw, input.size(), output.size()); - - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::IocSetNVMAPfdCommand: - return SetNVMAPfd(input); - case IoctlCommand::IocSubmit: - return Submit(input, output); - case IoctlCommand::IocGetSyncpoint: - return GetSyncpoint(input, output); - case IoctlCommand::IocGetWaitbase: - return GetWaitbase(input, output); - case IoctlCommand::IocMapBuffer: - case IoctlCommand::IocMapBuffer2: - case IoctlCommand::IocMapBuffer3: - case IoctlCommand::IocMapBuffer4: - case IoctlCommand::IocMapBufferEx: - return MapBuffer(input, output); - case IoctlCommand::IocUnmapBuffer: - case IoctlCommand::IocUnmapBuffer2: - case IoctlCommand::IocUnmapBuffer3: - case IoctlCommand::IocUnmapBufferEx: - return UnmapBuffer(input, output); +NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 0x0: + switch (command.cmd) { + case 0x1: + return Submit(input, output); + case 0x2: + return GetSyncpoint(input, output); + case 0x3: + return GetWaitbase(input, output); + case 0x9: + return MapBuffer(input, output); + case 0xa: + return UnmapBuffer(input, output); + default: + break; + } + break; + case 'H': + switch (command.cmd) { + case 0x1: + return SetNVMAPfd(input); + default: + break; + } + break; + default: + break; } - UNIMPLEMENTED_MSG("Unimplemented ioctl 0x{:X}", command.raw); - return 0; + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_vic::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvhost_vic::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index f975b190c..7f4858cd4 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h @@ -13,25 +13,13 @@ class nvhost_vic final : public nvhost_nvdec_common { public: explicit nvhost_vic(Core::System& system, std::shared_ptr<nvmap> nvmap_dev); ~nvhost_vic(); - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; -private: - enum class IoctlCommand : u32_le { - IocSetNVMAPfdCommand = 0x40044801, - IocSubmit = 0xC0400001, - IocGetSyncpoint = 0xC0080002, - IocGetWaitbase = 0xC0080003, - IocMapBuffer = 0xC01C0009, - IocMapBuffer2 = 0xC0340009, - IocMapBuffer3 = 0xC0140009, - IocMapBuffer4 = 0xC00C0009, - IocMapBufferEx = 0xC03C0009, - IocUnmapBuffer = 0xC03C000A, - IocUnmapBuffer2 = 0xC034000A, - IocUnmapBuffer3 = 0xC00C000A, - IocUnmapBufferEx = 0xC01C000A, - }; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index 9436e16ad..910cfee51 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -11,13 +11,6 @@ namespace Service::Nvidia::Devices { -namespace NvErrCodes { -enum { - OperationNotPermitted = -1, - InvalidValue = -22, -}; -} - nvmap::nvmap(Core::System& system) : nvdevice(system) { // Handle 0 appears to be used when remapping, so we create a placeholder empty nvmap object to // represent this. @@ -26,6 +19,48 @@ nvmap::nvmap(Core::System& system) : nvdevice(system) { nvmap::~nvmap() = default; +NvResult nvmap::Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + switch (command.group) { + case 0x1: + switch (command.cmd) { + case 0x1: + return IocCreate(input, output); + case 0x3: + return IocFromId(input, output); + case 0x4: + return IocAlloc(input, output); + case 0x5: + return IocFree(input, output); + case 0x9: + return IocParam(input, output); + case 0xe: + return IocGetId(input, output); + default: + break; + } + break; + default: + break; + } + + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvmap::Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + +NvResult nvmap::Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw); + return NvResult::NotImplemented; +} + VAddr nvmap::GetObjectAddress(u32 handle) const { auto object = GetObject(handle); ASSERT(object); @@ -33,28 +68,6 @@ VAddr nvmap::GetObjectAddress(u32 handle) const { return object->addr; } -u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - switch (static_cast<IoctlCommand>(command.raw)) { - case IoctlCommand::Create: - return IocCreate(input, output); - case IoctlCommand::Alloc: - return IocAlloc(input, output); - case IoctlCommand::GetId: - return IocGetId(input, output); - case IoctlCommand::FromId: - return IocFromId(input, output); - case IoctlCommand::Param: - return IocParam(input, output); - case IoctlCommand::Free: - return IocFree(input, output); - } - - UNIMPLEMENTED_MSG("Unimplemented ioctl"); - return 0; -} - u32 nvmap::CreateObject(u32 size) { // Create a new nvmap object and obtain a handle to it. auto object = std::make_shared<Object>(); @@ -70,35 +83,35 @@ u32 nvmap::CreateObject(u32 size) { return handle; } -u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { IocCreateParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size); if (!params.size) { LOG_ERROR(Service_NVDRV, "Size is 0"); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } params.handle = CreateObject(params.size); std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } -u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { IocAllocParams params; std::memcpy(¶ms, input.data(), sizeof(params)); LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr); if (!params.handle) { LOG_ERROR(Service_NVDRV, "Handle is 0"); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } if ((params.align - 1) & params.align) { LOG_ERROR(Service_NVDRV, "Incorrect alignment used, alignment={:08X}", params.align); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } const u32 min_alignment = 0x1000; @@ -109,12 +122,12 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { auto object = GetObject(params.handle); if (!object) { LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } if (object->status == Object::Status::Allocated) { LOG_ERROR(Service_NVDRV, "Object is already allocated, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::OperationNotPermitted); + return NvResult::InsufficientMemory; } object->flags = params.flags; @@ -124,10 +137,10 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { object->status = Object::Status::Allocated; std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } -u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { IocGetIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -135,22 +148,22 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { if (!params.handle) { LOG_ERROR(Service_NVDRV, "Handle is zero"); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } auto object = GetObject(params.handle); if (!object) { LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::OperationNotPermitted); + return NvResult::BadValue; } params.id = object->id; std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } -u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { IocFromIdParams params; std::memcpy(¶ms, input.data(), sizeof(params)); @@ -160,13 +173,13 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { [&](const auto& entry) { return entry.second->id == params.id; }); if (itr == handles.end()) { LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } auto& object = itr->second; if (object->status != Object::Status::Allocated) { LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } itr->second->refcount++; @@ -175,10 +188,10 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { params.handle = itr->first; std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } -u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; IocParamParams params; @@ -189,12 +202,12 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { auto object = GetObject(params.handle); if (!object) { LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } if (object->status != Object::Status::Allocated) { LOG_ERROR(Service_NVDRV, "Object is not allocated, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::OperationNotPermitted); + return NvResult::BadValue; } switch (static_cast<ParamTypes>(params.param)) { @@ -216,10 +229,10 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { } std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } -u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { +NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { // TODO(Subv): These flags are unconfirmed. enum FreeFlags { Freed = 0, @@ -234,14 +247,14 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { auto itr = handles.find(params.handle); if (itr == handles.end()) { LOG_ERROR(Service_NVDRV, "Object does not exist, handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } if (!itr->second->refcount) { LOG_ERROR( Service_NVDRV, "There is no references to this object. The object is already freed. handle={:08X}", params.handle); - return static_cast<u32>(NvErrCodes::InvalidValue); + return NvResult::BadValue; } itr->second->refcount--; @@ -261,7 +274,7 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) { handles.erase(params.handle); std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; + return NvResult::Success; } } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 04b9ef540..c0c2fa5eb 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -19,13 +19,17 @@ public: explicit nvmap(Core::System& system); ~nvmap() override; + NvResult Ioctl1(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl2(Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) override; + NvResult Ioctl3(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output, + std::vector<u8>& inline_output, IoctlCtrl& ctrl) override; + /// Returns the allocated address of an nvmap object given its handle. VAddr GetObjectAddress(u32 handle) const; - u32 ioctl(Ioctl command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) override; - /// Represents an nvmap object. struct Object { enum class Status { Created, Allocated }; @@ -58,76 +62,68 @@ private: /// Mapping of currently allocated handles to the objects they represent. std::unordered_map<u32, std::shared_ptr<Object>> handles; - enum class IoctlCommand : u32 { - Create = 0xC0080101, - FromId = 0xC0080103, - Alloc = 0xC0200104, - Free = 0xC0180105, - Param = 0xC00C0109, - GetId = 0xC008010E, - }; struct IocCreateParams { // Input - u32_le size; + u32_le size{}; // Output - u32_le handle; + u32_le handle{}; }; static_assert(sizeof(IocCreateParams) == 8, "IocCreateParams has wrong size"); struct IocFromIdParams { // Input - u32_le id; + u32_le id{}; // Output - u32_le handle; + u32_le handle{}; }; static_assert(sizeof(IocFromIdParams) == 8, "IocFromIdParams has wrong size"); struct IocAllocParams { // Input - u32_le handle; - u32_le heap_mask; - u32_le flags; - u32_le align; - u8 kind; + u32_le handle{}; + u32_le heap_mask{}; + u32_le flags{}; + u32_le align{}; + u8 kind{}; INSERT_PADDING_BYTES(7); - u64_le addr; + u64_le addr{}; }; static_assert(sizeof(IocAllocParams) == 32, "IocAllocParams has wrong size"); struct IocFreeParams { - u32_le handle; + u32_le handle{}; INSERT_PADDING_BYTES(4); - u64_le address; - u32_le size; - u32_le flags; + u64_le address{}; + u32_le size{}; + u32_le flags{}; }; static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size"); struct IocParamParams { // Input - u32_le handle; - u32_le param; + u32_le handle{}; + u32_le param{}; // Output - u32_le result; + u32_le result{}; }; static_assert(sizeof(IocParamParams) == 12, "IocParamParams has wrong size"); struct IocGetIdParams { // Output - u32_le id; + u32_le id{}; // Input - u32_le handle; + u32_le handle{}; }; static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); u32 CreateObject(u32 size); - u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); - u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocCreate(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocGetId(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocFromId(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocParam(const std::vector<u8>& input, std::vector<u8>& output); + NvResult IocFree(const std::vector<u8>& input, std::vector<u8>& output); }; } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 88fbfa9b0..d72c531f6 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -23,41 +23,47 @@ void NVDRV::SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { void NVDRV::Open(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; + } + const auto& buffer = ctx.ReadBuffer(); - std::string device_name(buffer.begin(), buffer.end()); + const std::string device_name(buffer.begin(), buffer.end()); + DeviceFD fd = nvdrv->Open(device_name); - u32 fd = nvdrv->Open(device_name); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(fd); - rb.Push<u32>(0); + rb.Push<DeviceFD>(fd); + rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); +} + +void NVDRV::ServiceError(Kernel::HLERequestContext& ctx, NvResult result) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(result); } -void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) { +void NVDRV::Ioctl1(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u32 fd = rp.Pop<u32>(); - u32 command = rp.Pop<u32>(); - - /// Ioctl 3 has 2 outputs, first in the input params, second is the result - std::vector<u8> output(ctx.GetWriteBufferSize(0)); - std::vector<u8> output2; - if (version == IoctlVersion::Version3) { - output2.resize((ctx.GetWriteBufferSize(1))); + const auto fd = rp.Pop<DeviceFD>(); + const auto command = rp.PopRaw<Ioctl>(); + LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); + + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; } - /// Ioctl2 has 2 inputs. It's used to pass data directly instead of providing a pointer. - /// KickOfPB uses this - auto input = ctx.ReadBuffer(0); - - std::vector<u8> input2; - if (version == IoctlVersion::Version2) { - input2 = ctx.ReadBuffer(1); - } + // Check device + std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); + const auto input_buffer = ctx.ReadBuffer(0); IoctlCtrl ctrl{}; - u32 result = nvdrv->Ioctl(fd, command, input, input2, output, output2, ctrl, version); - + const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer, ctrl); if (ctrl.must_delay) { ctrl.fresh_call = false; ctx.SleepClientThread( @@ -65,82 +71,195 @@ void NVDRV::IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version) { [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_, Kernel::ThreadWakeupReason reason) { IoctlCtrl ctrl2{ctrl}; - std::vector<u8> tmp_output = output; - std::vector<u8> tmp_output2 = output2; - const u32 ioctl_result = nvdrv->Ioctl(fd, command, input, input2, tmp_output, - tmp_output2, ctrl2, version); - ctx_.WriteBuffer(tmp_output, 0); - if (version == IoctlVersion::Version3) { - ctx_.WriteBuffer(tmp_output2, 1); + std::vector<u8> tmp_output = output_buffer; + const auto nv_result2 = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output, ctrl2); + + if (command.is_out != 0) { + ctx.WriteBuffer(tmp_output); } + IPC::ResponseBuilder rb{ctx_, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(ioctl_result); + rb.PushEnum(nv_result2); }, nvdrv->GetEventWriteable(ctrl.event_id)); } else { - ctx.WriteBuffer(output); - if (version == IoctlVersion::Version3) { - ctx.WriteBuffer(output2, 1); + if (command.is_out != 0) { + ctx.WriteBuffer(output_buffer); } } + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(result); -} - -void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NVDRV, "called"); - IoctlBase(ctx, IoctlVersion::Version1); + rb.PushEnum(nv_result); } void NVDRV::Ioctl2(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NVDRV, "called"); - IoctlBase(ctx, IoctlVersion::Version2); + IPC::RequestParser rp{ctx}; + const auto fd = rp.Pop<DeviceFD>(); + const auto command = rp.PopRaw<Ioctl>(); + LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); + + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; + } + + const auto input_buffer = ctx.ReadBuffer(0); + const auto input_inlined_buffer = ctx.ReadBuffer(1); + std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); + + IoctlCtrl ctrl{}; + + const auto nv_result = + nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer, ctrl); + if (ctrl.must_delay) { + ctrl.fresh_call = false; + ctx.SleepClientThread( + "NVServices::DelayedResponse", ctrl.timeout, + [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_, + Kernel::ThreadWakeupReason reason) { + IoctlCtrl ctrl2{ctrl}; + std::vector<u8> tmp_output = output_buffer; + const auto nv_result2 = nvdrv->Ioctl2(fd, command, input_buffer, + input_inlined_buffer, tmp_output, ctrl2); + + if (command.is_out != 0) { + ctx.WriteBuffer(tmp_output); + } + + IPC::ResponseBuilder rb{ctx_, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(nv_result2); + }, + nvdrv->GetEventWriteable(ctrl.event_id)); + } else { + if (command.is_out != 0) { + ctx.WriteBuffer(output_buffer); + } + } + + if (command.is_out != 0) { + ctx.WriteBuffer(output_buffer); + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(nv_result); } void NVDRV::Ioctl3(Kernel::HLERequestContext& ctx) { - LOG_DEBUG(Service_NVDRV, "called"); - IoctlBase(ctx, IoctlVersion::Version3); + IPC::RequestParser rp{ctx}; + const auto fd = rp.Pop<DeviceFD>(); + const auto command = rp.PopRaw<Ioctl>(); + LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw); + + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; + } + + const auto input_buffer = ctx.ReadBuffer(0); + std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0)); + std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1)); + + IoctlCtrl ctrl{}; + const auto nv_result = + nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline, ctrl); + if (ctrl.must_delay) { + ctrl.fresh_call = false; + ctx.SleepClientThread( + "NVServices::DelayedResponse", ctrl.timeout, + [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx_, + Kernel::ThreadWakeupReason reason) { + IoctlCtrl ctrl2{ctrl}; + std::vector<u8> tmp_output = output_buffer; + std::vector<u8> tmp_output2 = output_buffer; + const auto nv_result2 = + nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output2, ctrl2); + + if (command.is_out != 0) { + ctx.WriteBuffer(tmp_output, 0); + ctx.WriteBuffer(tmp_output2, 1); + } + + IPC::ResponseBuilder rb{ctx_, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(nv_result2); + }, + nvdrv->GetEventWriteable(ctrl.event_id)); + } else { + if (command.is_out != 0) { + ctx.WriteBuffer(output_buffer, 0); + ctx.WriteBuffer(output_buffer_inline, 1); + } + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(nv_result); } void NVDRV::Close(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_NVDRV, "called"); - IPC::RequestParser rp{ctx}; - u32 fd = rp.Pop<u32>(); + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; + } - auto result = nvdrv->Close(fd); + IPC::RequestParser rp{ctx}; + const auto fd = rp.Pop<DeviceFD>(); + const auto result = nvdrv->Close(fd); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(result); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(result); } void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); + is_initialized = true; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); + rb.PushEnum(NvResult::Success); } void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u32 fd = rp.Pop<u32>(); - // TODO(Blinkhawk): Figure the meaning of the flag at bit 16 - u32 event_id = rp.Pop<u32>() & 0x000000FF; + const auto fd = rp.Pop<DeviceFD>(); + const auto event_id = rp.Pop<u32>() & 0x00FF; LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id); - IPC::ResponseBuilder rb{ctx, 3, 1}; - rb.Push(RESULT_SUCCESS); + if (!is_initialized) { + ServiceError(ctx, NvResult::NotInitialized); + LOG_ERROR(Service_NVDRV, "NvServices is not initalized!"); + return; + } + + const auto nv_result = nvdrv->VerifyFD(fd); + if (nv_result != NvResult::Success) { + LOG_ERROR(Service_NVDRV, "Invalid FD specified DeviceFD={}!", fd); + ServiceError(ctx, nv_result); + return; + } + if (event_id < MaxNvEvents) { + IPC::ResponseBuilder rb{ctx, 3, 1}; + rb.Push(RESULT_SUCCESS); auto event = nvdrv->GetEvent(event_id); event->Clear(); rb.PushCopyObjects(event); - rb.Push<u32>(NvResult::Success); + rb.PushEnum(NvResult::Success); } else { - rb.Push<u32>(0); - rb.Push<u32>(NvResult::BadParameter); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(NvResult::BadParameter); } } @@ -151,7 +270,7 @@ void NVDRV::SetAruid(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); + rb.PushEnum(NvResult::Success); } void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx) { @@ -164,8 +283,9 @@ void NVDRV::SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ct void NVDRV::GetStatus(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); + rb.PushEnum(NvResult::Success); } void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { @@ -177,11 +297,11 @@ void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) - : ServiceFramework(name), nvdrv(std::move(nvdrv)) { +NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name) + : ServiceFramework{system_, name}, nvdrv{std::move(nvdrv_)} { static const FunctionInfo functions[] = { {0, &NVDRV::Open, "Open"}, - {1, &NVDRV::Ioctl, "Ioctl"}, + {1, &NVDRV::Ioctl1, "Ioctl"}, {2, &NVDRV::Close, "Close"}, {3, &NVDRV::Initialize, "Initialize"}, {4, &NVDRV::QueryEvent, "QueryEvent"}, diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 72e17a728..5c777c59b 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h @@ -16,14 +16,14 @@ namespace Service::Nvidia { class NVDRV final : public ServiceFramework<NVDRV> { public: - NVDRV(std::shared_ptr<Module> nvdrv, const char* name); + explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name); ~NVDRV() override; - void SignalGPUInterruptSyncpt(const u32 syncpoint_id, const u32 value); + void SignalGPUInterruptSyncpt(u32 syncpoint_id, u32 value); private: void Open(Kernel::HLERequestContext& ctx); - void Ioctl(Kernel::HLERequestContext& ctx); + void Ioctl1(Kernel::HLERequestContext& ctx); void Ioctl2(Kernel::HLERequestContext& ctx); void Ioctl3(Kernel::HLERequestContext& ctx); void Close(Kernel::HLERequestContext& ctx); @@ -33,11 +33,13 @@ private: void SetGraphicsFirmwareMemoryMarginEnabled(Kernel::HLERequestContext& ctx); void GetStatus(Kernel::HLERequestContext& ctx); void DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx); - void IoctlBase(Kernel::HLERequestContext& ctx, IoctlVersion version); + + void ServiceError(Kernel::HLERequestContext& ctx, NvResult result); std::shared_ptr<Module> nvdrv; u64 pid{}; + bool is_initialized{}; }; } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdata.h b/src/core/hle/service/nvdrv/nvdata.h index 529b03471..a3c4ecd85 100644 --- a/src/core/hle/service/nvdrv/nvdata.h +++ b/src/core/hle/service/nvdrv/nvdata.h @@ -1,12 +1,16 @@ #pragma once #include <array> +#include "common/bit_field.h" #include "common/common_types.h" namespace Service::Nvidia { constexpr u32 MaxSyncPoints = 192; constexpr u32 MaxNvEvents = 64; +using DeviceFD = s32; + +constexpr DeviceFD INVALID_NVDRV_FD = -1; struct Fence { s32 id; @@ -20,11 +24,61 @@ struct MultiFence { std::array<Fence, 4> fences; }; -enum NvResult : u32 { - Success = 0, - BadParameter = 4, - Timeout = 5, - ResourceError = 15, +enum class NvResult : u32 { + Success = 0x0, + NotImplemented = 0x1, + NotSupported = 0x2, + NotInitialized = 0x3, + BadParameter = 0x4, + Timeout = 0x5, + InsufficientMemory = 0x6, + ReadOnlyAttribute = 0x7, + InvalidState = 0x8, + InvalidAddress = 0x9, + InvalidSize = 0xA, + BadValue = 0xB, + AlreadyAllocated = 0xD, + Busy = 0xE, + ResourceError = 0xF, + CountMismatch = 0x10, + OverFlow = 0x11, + InsufficientTransferMemory = 0x1000, + InsufficientVideoMemory = 0x10000, + BadSurfaceColorScheme = 0x10001, + InvalidSurface = 0x10002, + SurfaceNotSupported = 0x10003, + DispInitFailed = 0x20000, + DispAlreadyAttached = 0x20001, + DispTooManyDisplays = 0x20002, + DispNoDisplaysAttached = 0x20003, + DispModeNotSupported = 0x20004, + DispNotFound = 0x20005, + DispAttachDissallowed = 0x20006, + DispTypeNotSupported = 0x20007, + DispAuthenticationFailed = 0x20008, + DispNotAttached = 0x20009, + DispSamePwrState = 0x2000A, + DispEdidFailure = 0x2000B, + DispDsiReadAckError = 0x2000C, + DispDsiReadInvalidResp = 0x2000D, + FileWriteFailed = 0x30000, + FileReadFailed = 0x30001, + EndOfFile = 0x30002, + FileOperationFailed = 0x30003, + DirOperationFailed = 0x30004, + EndOfDirList = 0x30005, + ConfigVarNotFound = 0x30006, + InvalidConfigVar = 0x30007, + LibraryNotFound = 0x30008, + SymbolNotFound = 0x30009, + MemoryMapFailed = 0x3000A, + IoctlFailed = 0x3000F, + AccessDenied = 0x30010, + DeviceNotFound = 0x30011, + KernelDriverNotFound = 0x30012, + FileNotFound = 0x30013, + PathAlreadyExists = 0x30014, + ModuleNotPresent = 0xA000E, }; enum class EventState { @@ -34,10 +88,13 @@ enum class EventState { Busy = 3, }; -enum class IoctlVersion : u32 { - Version1, - Version2, - Version3, +union Ioctl { + u32_le raw; + BitField<0, 8, u32> cmd; + BitField<8, 8, u32> group; + BitField<16, 14, u32> length; + BitField<30, 1, u32> is_in; + BitField<31, 1, u32> is_out; }; struct IoctlCtrl { diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 046a1f28c..8e0c9f093 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -30,11 +30,11 @@ namespace Service::Nvidia { void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger, Core::System& system) { auto module_ = std::make_shared<Module>(system); - std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager); - std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager); - std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager); - std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager); - std::make_shared<NVMEMP>()->InstallAsService(service_manager); + std::make_shared<NVDRV>(system, module_, "nvdrv")->InstallAsService(service_manager); + std::make_shared<NVDRV>(system, module_, "nvdrv:a")->InstallAsService(service_manager); + std::make_shared<NVDRV>(system, module_, "nvdrv:s")->InstallAsService(service_manager); + std::make_shared<NVDRV>(system, module_, "nvdrv:t")->InstallAsService(service_manager); + std::make_shared<NVMEMP>(system)->InstallAsService(service_manager); nvflinger.SetNVDrvInstance(module_); } @@ -62,36 +62,102 @@ Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} { Module::~Module() = default; -u32 Module::Open(const std::string& device_name) { - ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}", - device_name); +NvResult Module::VerifyFD(DeviceFD fd) const { + if (fd < 0) { + LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); + return NvResult::InvalidState; + } + + if (open_files.find(fd) == open_files.end()) { + LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); + return NvResult::NotImplemented; + } + + return NvResult::Success; +} + +DeviceFD Module::Open(const std::string& device_name) { + if (devices.find(device_name) == devices.end()) { + LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name); + return INVALID_NVDRV_FD; + } auto device = devices[device_name]; - const u32 fd = next_fd++; + const DeviceFD fd = next_fd++; open_files[fd] = std::move(device); return fd; } -u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version) { - auto itr = open_files.find(fd); - ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); +NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, IoctlCtrl& ctrl) { + if (fd < 0) { + LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); + return NvResult::InvalidState; + } - auto& device = itr->second; - return device->ioctl({command}, input, input2, output, output2, ctrl, version); + const auto itr = open_files.find(fd); + + if (itr == open_files.end()) { + LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); + return NvResult::NotImplemented; + } + + return itr->second->Ioctl1(command, input, output, ctrl); } -ResultCode Module::Close(u32 fd) { - auto itr = open_files.find(fd); - ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); +NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, + IoctlCtrl& ctrl) { + if (fd < 0) { + LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); + return NvResult::InvalidState; + } + + const auto itr = open_files.find(fd); + + if (itr == open_files.end()) { + LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); + return NvResult::NotImplemented; + } + + return itr->second->Ioctl2(command, input, inline_input, output, ctrl); +} + +NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, std::vector<u8>& inline_output, IoctlCtrl& ctrl) { + if (fd < 0) { + LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); + return NvResult::InvalidState; + } + + const auto itr = open_files.find(fd); + + if (itr == open_files.end()) { + LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); + return NvResult::NotImplemented; + } + + return itr->second->Ioctl3(command, input, output, inline_output, ctrl); +} + +NvResult Module::Close(DeviceFD fd) { + if (fd < 0) { + LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); + return NvResult::InvalidState; + } + + const auto itr = open_files.find(fd); + + if (itr == open_files.end()) { + LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); + return NvResult::NotImplemented; + } open_files.erase(itr); - // TODO(flerovium): return correct result code if operation failed. - return RESULT_SUCCESS; + return NvResult::Success; } void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) { diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index f3d863dac..5985d2179 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -100,7 +100,7 @@ struct EventInterface { class Module final { public: - Module(Core::System& system); + explicit Module(Core::System& system_); ~Module(); /// Returns a pointer to one of the available devices, identified by its name. @@ -112,14 +112,23 @@ public: return std::static_pointer_cast<T>(itr->second); } + NvResult VerifyFD(DeviceFD fd) const; + /// Opens a device node and returns a file descriptor to it. - u32 Open(const std::string& device_name); + DeviceFD Open(const std::string& device_name); + /// Sends an ioctl command to the specified file descriptor. - u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, const std::vector<u8>& input2, - std::vector<u8>& output, std::vector<u8>& output2, IoctlCtrl& ctrl, - IoctlVersion version); + NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, IoctlCtrl& ctrl); + + NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + const std::vector<u8>& inline_input, std::vector<u8>& output, IoctlCtrl& ctrl); + + NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input, + std::vector<u8>& output, std::vector<u8>& inline_output, IoctlCtrl& ctrl); + /// Closes a device file descriptor and returns operation success. - ResultCode Close(u32 fd); + NvResult Close(DeviceFD fd); void SignalSyncpt(const u32 syncpoint_id, const u32 value); @@ -132,10 +141,10 @@ private: SyncpointManager syncpoint_manager; /// Id to use for the next open file descriptor. - u32 next_fd = 1; + DeviceFD next_fd = 1; /// Mapping of file descriptors to the devices they reference. - std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; + std::unordered_map<DeviceFD, std::shared_ptr<Devices::nvdevice>> open_files; /// Mapping of device node names to their implementation. std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp index 73b37e805..331c02243 100644 --- a/src/core/hle/service/nvdrv/nvmemp.cpp +++ b/src/core/hle/service/nvdrv/nvmemp.cpp @@ -8,7 +8,7 @@ namespace Service::Nvidia { -NVMEMP::NVMEMP() : ServiceFramework("nvmemp") { +NVMEMP::NVMEMP(Core::System& system_) : ServiceFramework{system_, "nvmemp"} { static const FunctionInfo functions[] = { {0, &NVMEMP::Open, "Open"}, {1, &NVMEMP::GetAruid, "GetAruid"}, diff --git a/src/core/hle/service/nvdrv/nvmemp.h b/src/core/hle/service/nvdrv/nvmemp.h index c453ee4db..724c27ef9 100644 --- a/src/core/hle/service/nvdrv/nvmemp.h +++ b/src/core/hle/service/nvdrv/nvmemp.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Nvidia { class NVMEMP final : public ServiceFramework<NVMEMP> { public: - NVMEMP(); + explicit NVMEMP(Core::System& system_); ~NVMEMP() override; private: diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.h b/src/core/hle/service/nvdrv/syncpoint_manager.h index 4168b6c7e..d395c5d0b 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/syncpoint_manager.h @@ -37,7 +37,7 @@ public: * @returns The lower bound for the specified syncpoint. */ u32 GetSyncpointMin(u32 syncpoint_id) const { - return syncpoints[syncpoint_id].min.load(std::memory_order_relaxed); + return syncpoints.at(syncpoint_id).min.load(std::memory_order_relaxed); } /** @@ -46,7 +46,7 @@ public: * @returns The upper bound for the specified syncpoint. */ u32 GetSyncpointMax(u32 syncpoint_id) const { - return syncpoints[syncpoint_id].max.load(std::memory_order_relaxed); + return syncpoints.at(syncpoint_id).max.load(std::memory_order_relaxed); } /** diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp new file mode 100644 index 000000000..4440135ed --- /dev/null +++ b/src/core/hle/service/olsc/olsc.cpp @@ -0,0 +1,69 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/olsc/olsc.h" +#include "core/hle/service/service.h" +#include "core/hle/service/sm/sm.h" + +namespace Service::OLSC { + +class OLSC final : public ServiceFramework<OLSC> { +public: + explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &OLSC::Initialize, "Initialize"}, + {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, + {13, nullptr, "GetSaveDataBackupSetting"}, + {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, + {15, nullptr, "SetCustomData"}, + {16, nullptr, "DeleteSaveDataBackupSetting"}, + {18, nullptr, "GetSaveDataBackupInfoCache"}, + {19, nullptr, "UpdateSaveDataBackupInfoCacheAsync"}, + {22, nullptr, "DeleteSaveDataBackupAsync"}, + {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, + {26, nullptr, "DownloadSaveDataBackupAsync"}, + {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(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_OLSC, "(STUBBED) called"); + + initialized = true; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void SetSaveDataBackupSettingEnabled(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_OLSC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + bool initialized{}; +}; + +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<OLSC>(system)->InstallAsService(service_manager); +} + +} // namespace Service::OLSC diff --git a/src/core/hle/service/olsc/olsc.h b/src/core/hle/service/olsc/olsc.h new file mode 100644 index 000000000..24f24ca6b --- /dev/null +++ b/src/core/hle/service/olsc/olsc.h @@ -0,0 +1,20 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Core { +class System; +} + +namespace Service::SM { +class ServiceManager; +} + +namespace Service::OLSC { + +/// Registers all SSL services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); + +} // namespace Service::OLSC diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp index c568a0adc..80c0fc7ac 100644 --- a/src/core/hle/service/pcie/pcie.cpp +++ b/src/core/hle/service/pcie/pcie.cpp @@ -12,7 +12,7 @@ namespace Service::PCIe { class ISession final : public ServiceFramework<ISession> { public: - explicit ISession() : ServiceFramework{"ISession"} { + explicit ISession(Core::System& system_) : ServiceFramework{system_, "ISession"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "QueryFunctions"}, @@ -48,7 +48,7 @@ public: class PCIe final : public ServiceFramework<PCIe> { public: - explicit PCIe() : ServiceFramework{"pcie"} { + explicit PCIe(Core::System& system_) : ServiceFramework{system, "pcie"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "RegisterClassDriver"}, @@ -60,8 +60,8 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<PCIe>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<PCIe>(system)->InstallAsService(sm); } } // namespace Service::PCIe diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h index 59c22ca45..e5709a72f 100644 --- a/src/core/hle/service/pcie/pcie.h +++ b/src/core/hle/service/pcie/pcie.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::PCIe { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::PCIe diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp index caf14ed61..6ab1e4124 100644 --- a/src/core/hle/service/pctl/module.cpp +++ b/src/core/hle/service/pctl/module.cpp @@ -11,7 +11,8 @@ namespace Service::PCTL { class IParentalControlService final : public ServiceFramework<IParentalControlService> { public: - IParentalControlService() : ServiceFramework("IParentalControlService") { + explicit IParentalControlService(Core::System& system_) + : ServiceFramework{system_, "IParentalControlService"} { // clang-format off static const FunctionInfo functions[] = { {1, &IParentalControlService::Initialize, "Initialize"}, @@ -137,7 +138,7 @@ void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IParentalControlService>(); + rb.PushIpcInterface<IParentalControlService>(system); } void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) { @@ -145,20 +146,20 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IParentalControlService>(); + rb.PushIpcInterface<IParentalControlService>(system); } -Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) - : ServiceFramework(name), module(std::move(module)) {} +Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)} {} Module::Interface::~Interface() = default; -void InstallInterfaces(SM::ServiceManager& service_manager) { +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { auto module = std::make_shared<Module>(); - std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager); - std::make_shared<PCTL>(module, "pctl:a")->InstallAsService(service_manager); - std::make_shared<PCTL>(module, "pctl:r")->InstallAsService(service_manager); - std::make_shared<PCTL>(module, "pctl:s")->InstallAsService(service_manager); + std::make_shared<PCTL>(system, module, "pctl")->InstallAsService(service_manager); + std::make_shared<PCTL>(system, module, "pctl:a")->InstallAsService(service_manager); + std::make_shared<PCTL>(system, module, "pctl:r")->InstallAsService(service_manager); + std::make_shared<PCTL>(system, module, "pctl:s")->InstallAsService(service_manager); } } // namespace Service::PCTL diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h index 3e449110d..4c7e09a3b 100644 --- a/src/core/hle/service/pctl/module.h +++ b/src/core/hle/service/pctl/module.h @@ -6,13 +6,18 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::PCTL { class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, const char* name); + explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, + const char* name); ~Interface() override; void CreateService(Kernel::HLERequestContext& ctx); @@ -24,6 +29,6 @@ public: }; /// Registers all PCTL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::PCTL diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp index af9d1433a..16dd34f90 100644 --- a/src/core/hle/service/pctl/pctl.cpp +++ b/src/core/hle/service/pctl/pctl.cpp @@ -6,8 +6,8 @@ namespace Service::PCTL { -PCTL::PCTL(std::shared_ptr<Module> module, const char* name) - : Module::Interface(std::move(module), name) { +PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name) + : Interface{system_, std::move(module_), name} { static const FunctionInfo functions[] = { {0, &PCTL::CreateService, "CreateService"}, {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h index c33ea80b6..275d23007 100644 --- a/src/core/hle/service/pctl/pctl.h +++ b/src/core/hle/service/pctl/pctl.h @@ -6,11 +6,15 @@ #include "core/hle/service/pctl/module.h" +namespace Core { +class System; +} + namespace Service::PCTL { class PCTL final : public Module::Interface { public: - explicit PCTL(std::shared_ptr<Module> module, const char* name); + explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name); ~PCTL() override; }; diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp index 8bfc0276e..68b2c4178 100644 --- a/src/core/hle/service/pcv/pcv.cpp +++ b/src/core/hle/service/pcv/pcv.cpp @@ -12,7 +12,7 @@ namespace Service::PCV { class PCV final : public ServiceFramework<PCV> { public: - explicit PCV() : ServiceFramework{"pcv"} { + explicit PCV(Core::System& system_) : ServiceFramework{system_, "pcv"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetPowerEnabled"}, @@ -54,7 +54,7 @@ public: class PCV_ARB final : public ServiceFramework<PCV_ARB> { public: - explicit PCV_ARB() : ServiceFramework{"pcv:arb"} { + explicit PCV_ARB(Core::System& system_) : ServiceFramework{system_, "pcv:arb"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "ReleaseControl"}, @@ -67,7 +67,7 @@ public: class PCV_IMM final : public ServiceFramework<PCV_IMM> { public: - explicit PCV_IMM() : ServiceFramework{"pcv:imm"} { + explicit PCV_IMM(Core::System& system_) : ServiceFramework{system_, "pcv:imm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetClockRate"}, @@ -78,10 +78,10 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<PCV>()->InstallAsService(sm); - std::make_shared<PCV_ARB>()->InstallAsService(sm); - std::make_shared<PCV_IMM>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<PCV>(system)->InstallAsService(sm); + std::make_shared<PCV_ARB>(system)->InstallAsService(sm); + std::make_shared<PCV_IMM>(system)->InstallAsService(sm); } } // namespace Service::PCV diff --git a/src/core/hle/service/pcv/pcv.h b/src/core/hle/service/pcv/pcv.h index 219a893c3..c61a0b591 100644 --- a/src/core/hle/service/pcv/pcv.h +++ b/src/core/hle/service/pcv/pcv.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::PCV { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::PCV diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index a771a51b4..68736c40c 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -44,7 +44,7 @@ void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, class BootMode final : public ServiceFramework<BootMode> { public: - explicit BootMode() : ServiceFramework{"pm:bm"} { + explicit BootMode(Core::System& system_) : ServiceFramework{system_, "pm:bm"} { static const FunctionInfo functions[] = { {0, &BootMode::GetBootMode, "GetBootMode"}, {1, &BootMode::SetMaintenanceBoot, "SetMaintenanceBoot"}, @@ -75,8 +75,8 @@ private: class DebugMonitor final : public ServiceFramework<DebugMonitor> { public: - explicit DebugMonitor(const Kernel::KernelCore& kernel) - : ServiceFramework{"pm:dmnt"}, kernel(kernel) { + explicit DebugMonitor(Core::System& system_) + : ServiceFramework{system_, "pm:dmnt"}, kernel{system_.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetJitDebugProcessIdList"}, @@ -125,8 +125,9 @@ private: class Info final : public ServiceFramework<Info> { public: - explicit Info(const std::vector<std::shared_ptr<Kernel::Process>>& process_list) - : ServiceFramework{"pm:info"}, process_list(process_list) { + explicit Info(Core::System& system_, + const std::vector<std::shared_ptr<Kernel::Process>>& process_list_) + : ServiceFramework{system_, "pm:info"}, process_list{process_list_} { static const FunctionInfo functions[] = { {0, &Info::GetTitleId, "GetTitleId"}, }; @@ -160,8 +161,8 @@ private: class Shell final : public ServiceFramework<Shell> { public: - explicit Shell(const Kernel::KernelCore& kernel) - : ServiceFramework{"pm:shell"}, kernel(kernel) { + explicit Shell(Core::System& system_) + : ServiceFramework{system_, "pm:shell"}, kernel{system_.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProgram"}, @@ -190,11 +191,11 @@ private: }; void InstallInterfaces(Core::System& system) { - std::make_shared<BootMode>()->InstallAsService(system.ServiceManager()); - std::make_shared<DebugMonitor>(system.Kernel())->InstallAsService(system.ServiceManager()); - std::make_shared<Info>(system.Kernel().GetProcessList()) + std::make_shared<BootMode>(system)->InstallAsService(system.ServiceManager()); + std::make_shared<DebugMonitor>(system)->InstallAsService(system.ServiceManager()); + std::make_shared<Info>(system, system.Kernel().GetProcessList()) ->InstallAsService(system.ServiceManager()); - std::make_shared<Shell>(system.Kernel())->InstallAsService(system.ServiceManager()); + std::make_shared<Shell>(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::PM diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index b9ef86b72..392fda73e 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp @@ -16,8 +16,7 @@ namespace Service::PlayReport { class PlayReport final : public ServiceFramework<PlayReport> { public: - explicit PlayReport(const char* name, Core::System& system) - : ServiceFramework{name}, system(system) { + explicit PlayReport(const char* name, Core::System& system_) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {10100, &PlayReport::SaveReport<Core::Reporter::PlayReportType::Old>, "SaveReportOld"}, @@ -140,8 +139,6 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } - - Core::System& system; }; void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { diff --git a/src/core/hle/service/prepo/prepo.h b/src/core/hle/service/prepo/prepo.h index a5682ee26..395b57ead 100644 --- a/src/core/hle/service/prepo/prepo.h +++ b/src/core/hle/service/prepo/prepo.h @@ -4,14 +4,14 @@ #pragma once -namespace Service::SM { -class ServiceManager; -} - namespace Core { class System; } +namespace Service::SM { +class ServiceManager; +} + namespace Service::PlayReport { void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp index 99e1c9042..5a52b2b05 100644 --- a/src/core/hle/service/psc/psc.cpp +++ b/src/core/hle/service/psc/psc.cpp @@ -14,7 +14,7 @@ namespace Service::PSC { class PSC_C final : public ServiceFramework<PSC_C> { public: - explicit PSC_C() : ServiceFramework{"psc:c"} { + explicit PSC_C(Core::System& system_) : ServiceFramework{system_, "psc:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -35,7 +35,7 @@ public: class IPmModule final : public ServiceFramework<IPmModule> { public: - explicit IPmModule() : ServiceFramework{"IPmModule"} { + explicit IPmModule(Core::System& system_) : ServiceFramework{system_, "IPmModule"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -52,7 +52,7 @@ public: class PSC_M final : public ServiceFramework<PSC_M> { public: - explicit PSC_M() : ServiceFramework{"psc:m"} { + explicit PSC_M(Core::System& system_) : ServiceFramework{system_, "psc:m"} { // clang-format off static const FunctionInfo functions[] = { {0, &PSC_M::GetPmModule, "GetPmModule"}, @@ -68,13 +68,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IPmModule>(); + rb.PushIpcInterface<IPmModule>(system); } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<PSC_C>()->InstallAsService(sm); - std::make_shared<PSC_M>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<PSC_C>(system)->InstallAsService(sm); + std::make_shared<PSC_M>(system)->InstallAsService(sm); } } // namespace Service::PSC diff --git a/src/core/hle/service/psc/psc.h b/src/core/hle/service/psc/psc.h index 5052eb02c..89344f32d 100644 --- a/src/core/hle/service/psc/psc.h +++ b/src/core/hle/service/psc/psc.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::PSC { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::PSC diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index 6d9e6bd09..b4b0dd241 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -14,7 +14,7 @@ namespace Service::PSM { class PSM final : public ServiceFramework<PSM> { public: - explicit PSM() : ServiceFramework{"psm"} { + explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"} { // clang-format off static const FunctionInfo functions[] = { {0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"}, @@ -72,8 +72,8 @@ private: ChargerType charger_type{ChargerType::RegularCharger}; }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<PSM>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<PSM>(system)->InstallAsService(sm); } } // namespace Service::PSM diff --git a/src/core/hle/service/ptm/psm.h b/src/core/hle/service/ptm/psm.h index a286793ae..2930ce26a 100644 --- a/src/core/hle/service/ptm/psm.h +++ b/src/core/hle/service/ptm/psm.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::PSM { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::PSM diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index ba9159ee0..360e0bf37 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -51,6 +51,7 @@ #include "core/hle/service/ns/ns.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvflinger/nvflinger.h" +#include "core/hle/service/olsc/olsc.h" #include "core/hle/service/pcie/pcie.h" #include "core/hle/service/pctl/module.h" #include "core/hle/service/pcv/pcv.h" @@ -89,9 +90,10 @@ namespace Service { return function_string; } -ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions, - InvokerFn* handler_invoker) - : service_name(service_name), max_sessions(max_sessions), handler_invoker(handler_invoker) {} +ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_, + u32 max_sessions_, InvokerFn* handler_invoker_) + : system{system_}, service_name{service_name_}, max_sessions{max_sessions_}, + handler_invoker{handler_invoker_} {} ServiceFrameworkBase::~ServiceFrameworkBase() = default; @@ -145,8 +147,8 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext } buf.push_back('}'); - Core::System::GetInstance().GetReporter().SaveUnimplementedFunctionReport( - ctx, ctx.GetCommand(), function_name, service_name); + system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, + service_name); UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); } @@ -170,7 +172,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co } case IPC::CommandType::ControlWithContext: case IPC::CommandType::Control: { - Core::System::GetInstance().ServiceManager().InvokeControlRequest(context); + system.ServiceManager().InvokeControlRequest(context); break; } case IPC::CommandType::RequestWithContext: @@ -187,71 +189,70 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co return RESULT_SUCCESS; } -/// Initialize ServiceManager -void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { +/// Initialize Services +Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) + : nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} { + // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it // here and pass it into the respective InstallInterfaces functions. - auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system); + system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); - SM::ServiceManager::InstallInterfaces(sm, system.Kernel()); + SM::ServiceManager::InstallInterfaces(sm, system); Account::InstallInterfaces(system); - AM::InstallInterfaces(*sm, nv_flinger, system); + AM::InstallInterfaces(*sm, *nv_flinger, system); AOC::InstallInterfaces(*sm, system); APM::InstallInterfaces(system); Audio::InstallInterfaces(*sm, system); BCAT::InstallInterfaces(system); - BPC::InstallInterfaces(*sm); + BPC::InstallInterfaces(*sm, system); BtDrv::InstallInterfaces(*sm, system); BTM::InstallInterfaces(*sm, system); - Capture::InstallInterfaces(*sm); - ERPT::InstallInterfaces(*sm); - ES::InstallInterfaces(*sm); - EUPLD::InstallInterfaces(*sm); + Capture::InstallInterfaces(*sm, system); + ERPT::InstallInterfaces(*sm, system); + ES::InstallInterfaces(*sm, system); + EUPLD::InstallInterfaces(*sm, system); Fatal::InstallInterfaces(*sm, system); - FGM::InstallInterfaces(*sm); + FGM::InstallInterfaces(*sm, system); FileSystem::InstallInterfaces(system); Friend::InstallInterfaces(*sm, system); Glue::InstallInterfaces(system); - GRC::InstallInterfaces(*sm); + GRC::InstallInterfaces(*sm, system); HID::InstallInterfaces(*sm, system); - LBL::InstallInterfaces(*sm); - LDN::InstallInterfaces(*sm); + LBL::InstallInterfaces(*sm, system); + LDN::InstallInterfaces(*sm, system); LDR::InstallInterfaces(*sm, system); LM::InstallInterfaces(system); - Migration::InstallInterfaces(*sm); - Mii::InstallInterfaces(*sm); - MM::InstallInterfaces(*sm); - NCM::InstallInterfaces(*sm); - NFC::InstallInterfaces(*sm); + Migration::InstallInterfaces(*sm, system); + Mii::InstallInterfaces(*sm, system); + MM::InstallInterfaces(*sm, system); + NCM::InstallInterfaces(*sm, system); + NFC::InstallInterfaces(*sm, system); NFP::InstallInterfaces(*sm, system); NIFM::InstallInterfaces(*sm, system); NIM::InstallInterfaces(*sm, system); - NPNS::InstallInterfaces(*sm); + NPNS::InstallInterfaces(*sm, system); NS::InstallInterfaces(*sm, system); Nvidia::InstallInterfaces(*sm, *nv_flinger, system); - PCIe::InstallInterfaces(*sm); - PCTL::InstallInterfaces(*sm); - PCV::InstallInterfaces(*sm); + OLSC::InstallInterfaces(*sm, system); + PCIe::InstallInterfaces(*sm, system); + PCTL::InstallInterfaces(*sm, system); + PCV::InstallInterfaces(*sm, system); PlayReport::InstallInterfaces(*sm, system); PM::InstallInterfaces(system); - PSC::InstallInterfaces(*sm); - PSM::InstallInterfaces(*sm); - Set::InstallInterfaces(*sm); + PSC::InstallInterfaces(*sm, system); + PSM::InstallInterfaces(*sm, system); + Set::InstallInterfaces(*sm, system); Sockets::InstallInterfaces(*sm, system); - SPL::InstallInterfaces(*sm); - SSL::InstallInterfaces(*sm); + SPL::InstallInterfaces(*sm, system); + SSL::InstallInterfaces(*sm, system); Time::InstallInterfaces(system); - USB::InstallInterfaces(*sm); - VI::InstallInterfaces(*sm, nv_flinger); - WLAN::InstallInterfaces(*sm); - - LOG_DEBUG(Service, "initialized OK"); + USB::InstallInterfaces(*sm, system); + VI::InstallInterfaces(*sm, system, *nv_flinger); + WLAN::InstallInterfaces(*sm, system); } -/// Shutdown ServiceManager -void Shutdown() { - LOG_DEBUG(Service, "shutdown OK"); -} +Services::~Services() = default; + } // namespace Service diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index a01ef3353..62a182310 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -29,7 +29,11 @@ namespace Service { namespace FileSystem { class FileSystemController; -} // namespace FileSystem +} + +namespace NVFlinger { +class NVFlinger; +} namespace SM { class ServiceManager; @@ -76,6 +80,9 @@ protected: template <typename Self> using HandlerFnP = void (Self::*)(Kernel::HLERequestContext&); + /// System context that the service operates under. + Core::System& system; + private: template <typename T> friend class ServiceFramework; @@ -89,7 +96,8 @@ private: using InvokerFn = void(ServiceFrameworkBase* object, HandlerFnP<ServiceFrameworkBase> member, Kernel::HLERequestContext& ctx); - ServiceFrameworkBase(const char* service_name, u32 max_sessions, InvokerFn* handler_invoker); + explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_, + u32 max_sessions_, InvokerFn* handler_invoker_); ~ServiceFrameworkBase() override; void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); @@ -147,11 +155,15 @@ protected: /** * Initializes the handler with no functions installed. - * @param max_sessions Maximum number of sessions that can be - * connected to this service at the same time. + * + * @param system_ The system context to construct this service under. + * @param service_name_ Name of the service. + * @param max_sessions_ Maximum number of sessions that can be + * connected to this service at the same time. */ - explicit ServiceFramework(const char* service_name, u32 max_sessions = DefaultMaxSessions) - : ServiceFrameworkBase(service_name, max_sessions, Invoker) {} + explicit ServiceFramework(Core::System& system_, const char* service_name_, + u32 max_sessions_ = DefaultMaxSessions) + : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {} /// Registers handlers in the service. template <std::size_t N> @@ -181,10 +193,17 @@ private: } }; -/// Initialize ServiceManager -void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); +/** + * The purpose of this class is to own any objects that need to be shared across the other service + * implementations. Will be torn down when the global system instance is shutdown. + */ +class Services final { +public: + explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); + ~Services(); -/// Shutdown ServiceManager -void Shutdown(); +private: + std::unique_ptr<NVFlinger::NVFlinger> nv_flinger; +}; } // namespace Service diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index ffbf90b00..d953b4303 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -188,7 +188,7 @@ void SET::GetKeyCodeMap2(Kernel::HLERequestContext& ctx) { GetKeyCodeMapImpl(ctx); } -SET::SET() : ServiceFramework("set") { +SET::SET(Core::System& system_) : ServiceFramework{system_, "set"} { // clang-format off static const FunctionInfo functions[] = { {0, &SET::GetLanguageCode, "GetLanguageCode"}, diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h index 8ac9c169d..d5bd7828d 100644 --- a/src/core/hle/service/set/set.h +++ b/src/core/hle/service/set/set.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Set { /// This is "nn::settings::LanguageCode", which is a NUL-terminated string stored in a u64. @@ -32,7 +36,7 @@ LanguageCode GetLanguageCodeFromIndex(std::size_t idx); class SET final : public ServiceFramework<SET> { public: - explicit SET(); + explicit SET(Core::System& system_); ~SET() override; private: diff --git a/src/core/hle/service/set/set_cal.cpp b/src/core/hle/service/set/set_cal.cpp index 3fbfecc9e..b2aa7bc0c 100644 --- a/src/core/hle/service/set/set_cal.cpp +++ b/src/core/hle/service/set/set_cal.cpp @@ -6,7 +6,7 @@ namespace Service::Set { -SET_CAL::SET_CAL() : ServiceFramework("set:cal") { +SET_CAL::SET_CAL(Core::System& system_) : ServiceFramework{system_, "set:cal"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetBluetoothBdAddress"}, diff --git a/src/core/hle/service/set/set_cal.h b/src/core/hle/service/set/set_cal.h index a0677e815..a29fc3ddd 100644 --- a/src/core/hle/service/set/set_cal.h +++ b/src/core/hle/service/set/set_cal.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Set { class SET_CAL final : public ServiceFramework<SET_CAL> { public: - explicit SET_CAL(); + explicit SET_CAL(Core::System& system_); ~SET_CAL() override; }; diff --git a/src/core/hle/service/set/set_fd.cpp b/src/core/hle/service/set/set_fd.cpp index 565882a31..f04dc5047 100644 --- a/src/core/hle/service/set/set_fd.cpp +++ b/src/core/hle/service/set/set_fd.cpp @@ -6,7 +6,7 @@ namespace Service::Set { -SET_FD::SET_FD() : ServiceFramework("set:fd") { +SET_FD::SET_FD(Core::System& system_) : ServiceFramework{system_, "set:fd"} { // clang-format off static const FunctionInfo functions[] = { {2, nullptr, "SetSettingsItemValue"}, diff --git a/src/core/hle/service/set/set_fd.h b/src/core/hle/service/set/set_fd.h index 216e65f1f..c28cb301e 100644 --- a/src/core/hle/service/set/set_fd.h +++ b/src/core/hle/service/set/set_fd.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Set { class SET_FD final : public ServiceFramework<SET_FD> { public: - explicit SET_FD(); + explicit SET_FD(Core::System& system_); ~SET_FD() override; }; diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 080b5743e..19b8f113d 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -103,7 +103,7 @@ void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -SET_SYS::SET_SYS() : ServiceFramework("set:sys") { +SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetLanguageCode"}, diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index 13ee2cf46..edb185a68 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Set { class SET_SYS final : public ServiceFramework<SET_SYS> { public: - explicit SET_SYS(); + explicit SET_SYS(Core::System& system_); ~SET_SYS() override; private: diff --git a/src/core/hle/service/set/settings.cpp b/src/core/hle/service/set/settings.cpp index cf5541ca8..212ebc427 100644 --- a/src/core/hle/service/set/settings.cpp +++ b/src/core/hle/service/set/settings.cpp @@ -7,14 +7,15 @@ #include "core/hle/service/set/set_fd.h" #include "core/hle/service/set/set_sys.h" #include "core/hle/service/set/settings.h" +#include "core/hle/service/sm/sm.h" namespace Service::Set { -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<SET>()->InstallAsService(service_manager); - std::make_shared<SET_CAL>()->InstallAsService(service_manager); - std::make_shared<SET_FD>()->InstallAsService(service_manager); - std::make_shared<SET_SYS>()->InstallAsService(service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<SET>(system)->InstallAsService(service_manager); + std::make_shared<SET_CAL>(system)->InstallAsService(service_manager); + std::make_shared<SET_FD>(system)->InstallAsService(service_manager); + std::make_shared<SET_SYS>(system)->InstallAsService(service_manager); } } // namespace Service::Set diff --git a/src/core/hle/service/set/settings.h b/src/core/hle/service/set/settings.h index 6606ce776..7a6950dd0 100644 --- a/src/core/hle/service/set/settings.h +++ b/src/core/hle/service/set/settings.h @@ -4,11 +4,17 @@ #pragma once -#include "core/hle/service/service.h" +namespace Core { +class System; +} + +namespace Service::SM { +class ServiceManager; +} namespace Service::Set { /// Registers all Settings services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::Set diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index 972aaa6d9..916177efd 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp @@ -48,7 +48,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { } // https://switchbrew.org/wiki/IPC_Marshalling -Controller::Controller() : ServiceFramework("IpcController") { +Controller::Controller(Core::System& system_) : ServiceFramework{system_, "IpcController"} { static const FunctionInfo functions[] = { {0, &Controller::ConvertCurrentObjectToDomain, "ConvertCurrentObjectToDomain"}, {1, nullptr, "CopyFromCurrentDomain"}, diff --git a/src/core/hle/service/sm/controller.h b/src/core/hle/service/sm/controller.h index 180c6da50..7494f898d 100644 --- a/src/core/hle/service/sm/controller.h +++ b/src/core/hle/service/sm/controller.h @@ -6,11 +6,15 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::SM { class Controller final : public ServiceFramework<Controller> { public: - Controller(); + explicit Controller(Core::System& system_); ~Controller() override; private: diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 9c1da361b..4da69f503 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -38,14 +38,13 @@ static ResultCode ValidateServiceName(const std::string& name) { return RESULT_SUCCESS; } -void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, - Kernel::KernelCore& kernel) { +void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { ASSERT(self->sm_interface.expired()); - auto sm = std::make_shared<SM>(self, kernel); - sm->InstallAsNamedPort(kernel); + auto sm = std::make_shared<SM>(self, system); + sm->InstallAsNamedPort(system.Kernel()); self->sm_interface = sm; - self->controller_interface = std::make_unique<Controller>(); + self->controller_interface = std::make_unique<Controller>(system); } ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(std::string name, @@ -190,8 +189,9 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) { rb.Push(service_manager->UnregisterService(name)); } -SM::SM(std::shared_ptr<ServiceManager> service_manager, Kernel::KernelCore& kernel) - : ServiceFramework{"sm:", 4}, service_manager{std::move(service_manager)}, kernel{kernel} { +SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) + : ServiceFramework{system_, "sm:", 4}, + service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { static const FunctionInfo functions[] = { {0x00000000, &SM::Initialize, "Initialize"}, {0x00000001, &SM::GetService, "GetService"}, diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 6790c86f0..3f46ae44f 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h @@ -16,6 +16,10 @@ #include "core/hle/result.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class ClientPort; class ClientSession; @@ -31,7 +35,7 @@ class Controller; /// Interface to "sm:" service class SM final : public ServiceFramework<SM> { public: - explicit SM(std::shared_ptr<ServiceManager> service_manager, Kernel::KernelCore& kernel); + explicit SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_); ~SM() override; private: @@ -46,7 +50,7 @@ private: class ServiceManager { public: - static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Kernel::KernelCore& kernel); + static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system); explicit ServiceManager(Kernel::KernelCore& kernel_); ~ServiceManager(); diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index a74be9370..a9875b9a6 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -827,8 +827,8 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co rb.PushEnum(bsd_errno); } -BSD::BSD(Core::System& system, const char* name) - : ServiceFramework(name), worker_pool{system, this} { +BSD::BSD(Core::System& system_, const char* name) + : ServiceFramework{system_, name}, worker_pool{system_, this} { // clang-format off static const FunctionInfo functions[] = { {0, &BSD::RegisterClient, "RegisterClient"}, @@ -873,7 +873,7 @@ BSD::BSD(Core::System& system, const char* name) BSD::~BSD() = default; -BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} { +BSDCFG::BSDCFG(Core::System& system_) : ServiceFramework{system_, "bsdcfg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetIfUp"}, diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 357531951..f14713fc4 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -26,7 +26,7 @@ namespace Service::Sockets { class BSD final : public ServiceFramework<BSD> { public: - explicit BSD(Core::System& system, const char* name); + explicit BSD(Core::System& system_, const char* name); ~BSD() override; private: @@ -176,7 +176,7 @@ private: class BSDCFG final : public ServiceFramework<BSDCFG> { public: - explicit BSDCFG(); + explicit BSDCFG(Core::System& system_); ~BSDCFG() override; }; diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp index abbeb4c50..05681ca2d 100644 --- a/src/core/hle/service/sockets/ethc.cpp +++ b/src/core/hle/service/sockets/ethc.cpp @@ -6,7 +6,7 @@ namespace Service::Sockets { -ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} { +ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Initialize"}, @@ -23,7 +23,7 @@ ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} { ETHC_C::~ETHC_C() = default; -ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} { +ETHC_I::ETHC_I(Core::System& system_) : ServiceFramework{system_, "ethc:i"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetReadableHandle"}, diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h index da2c7f741..71884182e 100644 --- a/src/core/hle/service/sockets/ethc.h +++ b/src/core/hle/service/sockets/ethc.h @@ -6,17 +6,21 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Sockets { class ETHC_C final : public ServiceFramework<ETHC_C> { public: - explicit ETHC_C(); + explicit ETHC_C(Core::System& system_); ~ETHC_C() override; }; class ETHC_I final : public ServiceFramework<ETHC_I> { public: - explicit ETHC_I(); + explicit ETHC_I(Core::System& system_); ~ETHC_I() override; }; diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index 40d781124..51c3739bb 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp @@ -6,7 +6,7 @@ namespace Service::Sockets { -NSD::NSD(const char* name) : ServiceFramework(name) { +NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {10, nullptr, "GetSettingName"}, diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h index d842e3232..becf93125 100644 --- a/src/core/hle/service/sockets/nsd.h +++ b/src/core/hle/service/sockets/nsd.h @@ -4,14 +4,17 @@ #pragma once -#include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Sockets { class NSD final : public ServiceFramework<NSD> { public: - explicit NSD(const char* name); + explicit NSD(Core::System& system_, const char* name); ~NSD() override; }; diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index e3017451f..3a6329f56 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -7,25 +7,7 @@ namespace Service::Sockets { -void SFDNSRES::GetAddrInfoRequest(Kernel::HLERequestContext& ctx) { - struct Parameters { - u8 use_nsd_resolve; - u32 unknown; - u64 process_id; - }; - - IPC::RequestParser rp{ctx}; - const auto parameters = rp.PopRaw<Parameters>(); - - LOG_WARNING(Service, - "(STUBBED) called. use_nsd_resolve={}, unknown=0x{:08X}, process_id=0x{:016X}", - parameters.use_nsd_resolve, parameters.unknown, parameters.process_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); -} - -SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") { +SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} { static const FunctionInfo functions[] = { {0, nullptr, "SetDnsAddressesPrivate"}, {1, nullptr, "GetDnsAddressPrivate"}, @@ -49,4 +31,22 @@ SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") { SFDNSRES::~SFDNSRES() = default; +void SFDNSRES::GetAddrInfoRequest(Kernel::HLERequestContext& ctx) { + struct Parameters { + u8 use_nsd_resolve; + u32 unknown; + u64 process_id; + }; + + IPC::RequestParser rp{ctx}; + const auto parameters = rp.PopRaw<Parameters>(); + + LOG_WARNING(Service, + "(STUBBED) called. use_nsd_resolve={}, unknown=0x{:08X}, process_id=0x{:016X}", + parameters.use_nsd_resolve, parameters.unknown, parameters.process_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h index acd3647bb..faa6b7d0d 100644 --- a/src/core/hle/service/sockets/sfdnsres.h +++ b/src/core/hle/service/sockets/sfdnsres.h @@ -7,11 +7,15 @@ #include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Sockets { class SFDNSRES final : public ServiceFramework<SFDNSRES> { public: - explicit SFDNSRES(); + explicit SFDNSRES(Core::System& system_); ~SFDNSRES() override; private: diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp index 1d27f7906..96f73bce3 100644 --- a/src/core/hle/service/sockets/sockets.cpp +++ b/src/core/hle/service/sockets/sockets.cpp @@ -13,15 +13,15 @@ namespace Service::Sockets { void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { std::make_shared<BSD>(system, "bsd:s")->InstallAsService(service_manager); std::make_shared<BSD>(system, "bsd:u")->InstallAsService(service_manager); - std::make_shared<BSDCFG>()->InstallAsService(service_manager); + std::make_shared<BSDCFG>(system)->InstallAsService(service_manager); - std::make_shared<ETHC_C>()->InstallAsService(service_manager); - std::make_shared<ETHC_I>()->InstallAsService(service_manager); + std::make_shared<ETHC_C>(system)->InstallAsService(service_manager); + std::make_shared<ETHC_I>(system)->InstallAsService(service_manager); - std::make_shared<NSD>("nsd:a")->InstallAsService(service_manager); - std::make_shared<NSD>("nsd:u")->InstallAsService(service_manager); + std::make_shared<NSD>(system, "nsd:a")->InstallAsService(service_manager); + std::make_shared<NSD>(system, "nsd:u")->InstallAsService(service_manager); - std::make_shared<SFDNSRES>()->InstallAsService(service_manager); + std::make_shared<SFDNSRES>(system)->InstallAsService(service_manager); } } // namespace Service::Sockets diff --git a/src/core/hle/service/spl/csrng.cpp b/src/core/hle/service/spl/csrng.cpp index 674928798..1beca417c 100644 --- a/src/core/hle/service/spl/csrng.cpp +++ b/src/core/hle/service/spl/csrng.cpp @@ -6,7 +6,8 @@ namespace Service::SPL { -CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "csrng") { +CSRNG::CSRNG(Core::System& system_, std::shared_ptr<Module> module_) + : Interface(system_, std::move(module_), "csrng") { static const FunctionInfo functions[] = { {0, &CSRNG::GetRandomBytes, "GetRandomBytes"}, }; diff --git a/src/core/hle/service/spl/csrng.h b/src/core/hle/service/spl/csrng.h index 764d5ceb0..5c0bd2199 100644 --- a/src/core/hle/service/spl/csrng.h +++ b/src/core/hle/service/spl/csrng.h @@ -6,11 +6,15 @@ #include "core/hle/service/spl/module.h" +namespace Core { +class System; +} + namespace Service::SPL { class CSRNG final : public Module::Interface { public: - explicit CSRNG(std::shared_ptr<Module> module); + explicit CSRNG(Core::System& system_, std::shared_ptr<Module> module_); ~CSRNG() override; }; diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp index 865ed3b91..dea6b0fe0 100644 --- a/src/core/hle/service/spl/module.cpp +++ b/src/core/hle/service/spl/module.cpp @@ -17,8 +17,9 @@ namespace Service::SPL { -Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) - : ServiceFramework(name), module(std::move(module)), +Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_, + const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)}, rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr))) {} Module::Interface::~Interface() = default; @@ -38,10 +39,10 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -void InstallInterfaces(SM::ServiceManager& service_manager) { +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { auto module = std::make_shared<Module>(); - std::make_shared<CSRNG>(module)->InstallAsService(service_manager); - std::make_shared<SPL>(module)->InstallAsService(service_manager); + std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager); + std::make_shared<SPL>(system, module)->InstallAsService(service_manager); } } // namespace Service::SPL diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h index afa1f0295..71855c1bf 100644 --- a/src/core/hle/service/spl/module.h +++ b/src/core/hle/service/spl/module.h @@ -7,13 +7,18 @@ #include <random> #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::SPL { class Module final { public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, const char* name); + explicit Interface(Core::System& system_, std::shared_ptr<Module> module_, + const char* name); ~Interface() override; void GetRandomBytes(Kernel::HLERequestContext& ctx); @@ -27,6 +32,6 @@ public: }; /// Registers all SPL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::SPL diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp index 773551464..3fabc2c79 100644 --- a/src/core/hle/service/spl/spl.cpp +++ b/src/core/hle/service/spl/spl.cpp @@ -6,7 +6,8 @@ namespace Service::SPL { -SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "spl:") { +SPL::SPL(Core::System& system_, std::shared_ptr<Module> module_) + : Interface(system_, std::move(module_), "spl:") { static const FunctionInfo functions[] = { {0, nullptr, "GetConfig"}, {1, nullptr, "ModularExponentiate"}, diff --git a/src/core/hle/service/spl/spl.h b/src/core/hle/service/spl/spl.h index 3637d1623..d27d16b86 100644 --- a/src/core/hle/service/spl/spl.h +++ b/src/core/hle/service/spl/spl.h @@ -6,11 +6,15 @@ #include "core/hle/service/spl/module.h" +namespace Core { +class System; +} + namespace Service::SPL { class SPL final : public Module::Interface { public: - explicit SPL(std::shared_ptr<Module> module); + explicit SPL(Core::System& system_, std::shared_ptr<Module> module_); ~SPL() override; }; diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 1ba8c19a0..dc2baca4a 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -12,7 +12,7 @@ namespace Service::SSL { class ISslConnection final : public ServiceFramework<ISslConnection> { public: - ISslConnection() : ServiceFramework("ISslConnection") { + explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "SetSocketDescriptor"}, @@ -52,7 +52,7 @@ public: class ISslContext final : public ServiceFramework<ISslContext> { public: - ISslContext() : ServiceFramework("ISslContext") { + explicit ISslContext(Core::System& system_) : ServiceFramework{system_, "ISslContext"} { static const FunctionInfo functions[] = { {0, &ISslContext::SetOption, "SetOption"}, {1, nullptr, "GetOption"}, @@ -92,13 +92,13 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISslConnection>(); + rb.PushIpcInterface<ISslConnection>(system); } }; class SSL final : public ServiceFramework<SSL> { public: - explicit SSL() : ServiceFramework{"ssl"} { + explicit SSL(Core::System& system_) : ServiceFramework{system_, "ssl"} { // clang-format off static const FunctionInfo functions[] = { {0, &SSL::CreateContext, "CreateContext"}, @@ -123,7 +123,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISslContext>(); + rb.PushIpcInterface<ISslContext>(system); } void SetInterfaceVersion(Kernel::HLERequestContext& ctx) { @@ -137,8 +137,8 @@ private: } }; -void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared<SSL>()->InstallAsService(service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { + std::make_shared<SSL>(system)->InstallAsService(service_manager); } } // namespace Service::SSL diff --git a/src/core/hle/service/ssl/ssl.h b/src/core/hle/service/ssl/ssl.h index 5cb04c3b9..a3aa4b4b5 100644 --- a/src/core/hle/service/ssl/ssl.h +++ b/src/core/hle/service/ssl/ssl.h @@ -4,6 +4,10 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } @@ -11,6 +15,6 @@ class ServiceManager; namespace Service::SSL { /// Registers all SSL services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system); } // namespace Service::SSL diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp index ba8fd6152..a01d9e0ff 100644 --- a/src/core/hle/service/time/interface.cpp +++ b/src/core/hle/service/time/interface.cpp @@ -7,7 +7,7 @@ namespace Service::Time { Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* name) - : Module::Interface(std::move(module), system, name) { + : Interface(std::move(module), system, name) { // clang-format off static const FunctionInfo functions[] = { {0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 7d0474e0b..7b7ac282d 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -21,8 +21,8 @@ namespace Service::Time { class ISystemClock final : public ServiceFramework<ISystemClock> { public: - explicit ISystemClock(Clock::SystemClockCore& clock_core, Core::System& system) - : ServiceFramework("ISystemClock"), clock_core{clock_core}, system{system} { + explicit ISystemClock(Clock::SystemClockCore& clock_core_, Core::System& system_) + : ServiceFramework{system_, "ISystemClock"}, clock_core{clock_core_} { // clang-format off static const FunctionInfo functions[] = { {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, @@ -82,13 +82,12 @@ private: } Clock::SystemClockCore& clock_core; - Core::System& system; }; class ISteadyClock final : public ServiceFramework<ISteadyClock> { public: - explicit ISteadyClock(Clock::SteadyClockCore& clock_core, Core::System& system) - : ServiceFramework("ISteadyClock"), clock_core{clock_core}, system{system} { + explicit ISteadyClock(Clock::SteadyClockCore& clock_core_, Core::System& system_) + : ServiceFramework{system_, "ISteadyClock"}, clock_core{clock_core_} { static const FunctionInfo functions[] = { {0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"}, {2, nullptr, "GetTestOffset"}, @@ -119,7 +118,6 @@ private: } Clock::SteadyClockCore& clock_core; - Core::System& system; }; ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( @@ -206,7 +204,8 @@ void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_Time, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ITimeZoneService>(system.GetTimeManager().GetTimeZoneContentManager()); + rb.PushIpcInterface<ITimeZoneService>(system, + system.GetTimeManager().GetTimeZoneContentManager()); } void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { @@ -375,8 +374,9 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem())); } -Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) - : ServiceFramework(name), module{std::move(module)}, system{system} {} +Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name) + : ServiceFramework{system_, name}, module{std::move(module_)} {} Module::Interface::~Interface() = default; diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 49f4aac0a..975a8ae5b 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -20,7 +20,8 @@ public: class Interface : public ServiceFramework<Interface> { public: - explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name); + explicit Interface(std::shared_ptr<Module> module_, Core::System& system_, + const char* name); ~Interface() override; void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); @@ -44,7 +45,6 @@ public: protected: std::shared_ptr<Module> module; - Core::System& system; }; }; diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp index ff3a10b3e..25cecbc83 100644 --- a/src/core/hle/service/time/time_zone_service.cpp +++ b/src/core/hle/service/time/time_zone_service.cpp @@ -10,8 +10,9 @@ namespace Service::Time { -ITimeZoneService ::ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_content_manager) - : ServiceFramework("ITimeZoneService"), time_zone_content_manager{time_zone_content_manager} { +ITimeZoneService ::ITimeZoneService(Core::System& system_, + TimeZone::TimeZoneContentManager& time_zone_manager_) + : ServiceFramework{system_, "ITimeZoneService"}, time_zone_content_manager{time_zone_manager_} { static const FunctionInfo functions[] = { {0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"}, {1, nullptr, "SetDeviceLocationName"}, diff --git a/src/core/hle/service/time/time_zone_service.h b/src/core/hle/service/time/time_zone_service.h index cb495748b..2c9b97603 100644 --- a/src/core/hle/service/time/time_zone_service.h +++ b/src/core/hle/service/time/time_zone_service.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Service::Time { namespace TimeZone { @@ -14,7 +18,8 @@ class TimeZoneContentManager; class ITimeZoneService final : public ServiceFramework<ITimeZoneService> { public: - explicit ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_manager); + explicit ITimeZoneService(Core::System& system_, + TimeZone::TimeZoneContentManager& time_zone_manager_); private: void GetDeviceLocationName(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp index d033f8603..579de83e4 100644 --- a/src/core/hle/service/usb/usb.cpp +++ b/src/core/hle/service/usb/usb.cpp @@ -15,7 +15,7 @@ namespace Service::USB { class IDsInterface final : public ServiceFramework<IDsInterface> { public: - explicit IDsInterface() : ServiceFramework{"IDsInterface"} { + explicit IDsInterface(Core::System& system_) : ServiceFramework{system_, "IDsInterface"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetDsEndpoint"}, @@ -40,7 +40,7 @@ public: class USB_DS final : public ServiceFramework<USB_DS> { public: - explicit USB_DS() : ServiceFramework{"usb:ds"} { + explicit USB_DS(Core::System& system_) : ServiceFramework{system_, "usb:ds"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "BindDevice"}, @@ -65,7 +65,8 @@ public: class IClientEpSession final : public ServiceFramework<IClientEpSession> { public: - explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} { + explicit IClientEpSession(Core::System& system_) + : ServiceFramework{system_, "IClientEpSession"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Open"}, @@ -86,7 +87,8 @@ public: class IClientIfSession final : public ServiceFramework<IClientIfSession> { public: - explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} { + explicit IClientIfSession(Core::System& system_) + : ServiceFramework{system_, "IClientIfSession"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown0"}, @@ -108,7 +110,7 @@ public: class USB_HS final : public ServiceFramework<USB_HS> { public: - explicit USB_HS() : ServiceFramework{"usb:hs"} { + explicit USB_HS(Core::System& system_) : ServiceFramework{system_, "usb:hs"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "BindClientProcess"}, @@ -129,7 +131,7 @@ public: class IPdSession final : public ServiceFramework<IPdSession> { public: - explicit IPdSession() : ServiceFramework{"IPdSession"} { + explicit IPdSession(Core::System& system_) : ServiceFramework{system_, "IPdSession"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "BindNoticeEvent"}, @@ -148,7 +150,7 @@ public: class USB_PD final : public ServiceFramework<USB_PD> { public: - explicit USB_PD() : ServiceFramework{"usb:pd"} { + explicit USB_PD(Core::System& system_) : ServiceFramework{system_, "usb:pd"} { // clang-format off static const FunctionInfo functions[] = { {0, &USB_PD::GetPdSession, "GetPdSession"}, @@ -164,13 +166,14 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IPdSession>(); + rb.PushIpcInterface<IPdSession>(system); } }; class IPdCradleSession final : public ServiceFramework<IPdCradleSession> { public: - explicit IPdCradleSession() : ServiceFramework{"IPdCradleSession"} { + explicit IPdCradleSession(Core::System& system_) + : ServiceFramework{system_, "IPdCradleSession"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "VdmUserWrite"}, @@ -191,7 +194,7 @@ public: class USB_PD_C final : public ServiceFramework<USB_PD_C> { public: - explicit USB_PD_C() : ServiceFramework{"usb:pd:c"} { + explicit USB_PD_C(Core::System& system_) : ServiceFramework{system_, "usb:pd:c"} { // clang-format off static const FunctionInfo functions[] = { {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"}, @@ -205,7 +208,7 @@ private: void GetPdCradleSession(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IPdCradleSession>(); + rb.PushIpcInterface<IPdCradleSession>(system); LOG_DEBUG(Service_USB, "called"); } @@ -213,7 +216,7 @@ private: class USB_PM final : public ServiceFramework<USB_PM> { public: - explicit USB_PM() : ServiceFramework{"usb:pm"} { + explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown0"}, @@ -229,12 +232,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<USB_DS>()->InstallAsService(sm); - std::make_shared<USB_HS>()->InstallAsService(sm); - std::make_shared<USB_PD>()->InstallAsService(sm); - std::make_shared<USB_PD_C>()->InstallAsService(sm); - std::make_shared<USB_PM>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<USB_DS>(system)->InstallAsService(sm); + std::make_shared<USB_HS>(system)->InstallAsService(sm); + std::make_shared<USB_PD>(system)->InstallAsService(sm); + std::make_shared<USB_PD_C>(system)->InstallAsService(sm); + std::make_shared<USB_PM>(system)->InstallAsService(sm); } } // namespace Service::USB diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h index 970a11fe8..fc366df34 100644 --- a/src/core/hle/service/usb/usb.h +++ b/src/core/hle/service/usb/usb.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::USB { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::USB diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 55e00dd93..af5b8b0b9 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -492,8 +492,8 @@ private: class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { public: - explicit IHOSBinderDriver(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) { + explicit IHOSBinderDriver(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "IHOSBinderDriver"}, nv_flinger(nv_flinger_) { static const FunctionInfo functions[] = { {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, @@ -530,8 +530,8 @@ private: LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, static_cast<u32>(transaction), flags); - const auto guard = nv_flinger->Lock(); - auto& buffer_queue = nv_flinger->FindBufferQueue(id); + const auto guard = nv_flinger.Lock(); + auto& buffer_queue = nv_flinger.FindBufferQueue(id); switch (transaction) { case TransactionId::Connect: { @@ -570,8 +570,8 @@ private: [=, this](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { // Repeat TransactParcel DequeueBuffer when a buffer is available - const auto guard = nv_flinger->Lock(); - auto& buffer_queue = nv_flinger->FindBufferQueue(id); + const auto guard = nv_flinger.Lock(); + auto& buffer_queue = nv_flinger.FindBufferQueue(id); auto result = buffer_queue.DequeueBuffer(width, height); ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); @@ -676,7 +676,7 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); - const auto& buffer_queue = nv_flinger->FindBufferQueue(id); + const auto& buffer_queue = nv_flinger.FindBufferQueue(id); // TODO(Subv): Find out what this actually is. IPC::ResponseBuilder rb{ctx, 2, 1}; @@ -684,12 +684,13 @@ private: rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent()); } - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; -}; // namespace VI + NVFlinger::NVFlinger& nv_flinger; +}; class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { public: - explicit ISystemDisplayService() : ServiceFramework("ISystemDisplayService") { + explicit ISystemDisplayService(Core::System& system_) + : ServiceFramework{system_, "ISystemDisplayService"} { static const FunctionInfo functions[] = { {1200, nullptr, "GetZOrderCountMin"}, {1202, nullptr, "GetZOrderCountMax"}, @@ -790,8 +791,8 @@ private: class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { public: - explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) { + explicit IManagerDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "IManagerDisplayService"}, nv_flinger{nv_flinger_} { // clang-format off static const FunctionInfo functions[] = { {200, nullptr, "AllocateProcessHeapBlock"}, @@ -893,7 +894,7 @@ private: "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", unknown, display, aruid); - const auto layer_id = nv_flinger->CreateLayer(display); + const auto layer_id = nv_flinger.CreateLayer(display); if (!layer_id) { LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); IPC::ResponseBuilder rb{ctx, 2}; @@ -930,12 +931,12 @@ private: rb.Push(RESULT_SUCCESS); } - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; + NVFlinger::NVFlinger& nv_flinger; }; class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { public: - explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); + explicit IApplicationDisplayService(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); private: enum class ConvertedScaleMode : u64 { @@ -959,7 +960,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger); + rb.PushIpcInterface<IHOSBinderDriver>(system, nv_flinger); } void GetSystemDisplayService(Kernel::HLERequestContext& ctx) { @@ -967,7 +968,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<ISystemDisplayService>(); + rb.PushIpcInterface<ISystemDisplayService>(system); } void GetManagerDisplayService(Kernel::HLERequestContext& ctx) { @@ -975,7 +976,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); + rb.PushIpcInterface<IManagerDisplayService>(system, nv_flinger); } void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) { @@ -983,7 +984,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger); + rb.PushIpcInterface<IHOSBinderDriver>(system, nv_flinger); } void OpenDisplay(Kernel::HLERequestContext& ctx) { @@ -1010,7 +1011,7 @@ private: ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); - const auto display_id = nv_flinger->OpenDisplay(name); + const auto display_id = nv_flinger.OpenDisplay(name); if (!display_id) { LOG_ERROR(Service_VI, "Display not found! display_name={}", name); IPC::ResponseBuilder rb{ctx, 2}; @@ -1110,7 +1111,7 @@ private: LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); - const auto display_id = nv_flinger->OpenDisplay(display_name); + const auto display_id = nv_flinger.OpenDisplay(display_name); if (!display_id) { LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1118,7 +1119,7 @@ private: return; } - const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id); + const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id); if (!buffer_queue_id) { LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1138,7 +1139,7 @@ private: LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); - nv_flinger->CloseLayer(layer_id); + nv_flinger.CloseLayer(layer_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -1154,7 +1155,7 @@ private: // TODO(Subv): What's the difference between a Stray and a Managed layer? - const auto layer_id = nv_flinger->CreateLayer(display_id); + const auto layer_id = nv_flinger.CreateLayer(display_id); if (!layer_id) { LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1162,7 +1163,7 @@ private: return; } - const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id); + const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id); if (!buffer_queue_id) { LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1193,7 +1194,7 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); - const auto vsync_event = nv_flinger->FindVsyncEvent(display_id); + const auto vsync_event = nv_flinger.FindVsyncEvent(display_id); if (!vsync_event) { LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); IPC::ResponseBuilder rb{ctx, 2}; @@ -1258,12 +1259,12 @@ private: } } - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; + NVFlinger::NVFlinger& nv_flinger; }; -IApplicationDisplayService::IApplicationDisplayService( - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework("IApplicationDisplayService"), nv_flinger(std::move(nv_flinger)) { +IApplicationDisplayService::IApplicationDisplayService(Core::System& system_, + NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "IApplicationDisplayService"}, nv_flinger{nv_flinger_} { static const FunctionInfo functions[] = { {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, @@ -1304,9 +1305,8 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) { return false; } -void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, - Permission permission) { +void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, + NVFlinger::NVFlinger& nv_flinger, Permission permission) { IPC::RequestParser rp{ctx}; const auto policy = rp.PopEnum<Policy>(); @@ -1319,14 +1319,14 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IApplicationDisplayService>(std::move(nv_flinger)); + rb.PushIpcInterface<IApplicationDisplayService>(system, nv_flinger); } -void InstallInterfaces(SM::ServiceManager& service_manager, - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) { - std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager); - std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager); - std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, + NVFlinger::NVFlinger& nv_flinger) { + std::make_shared<VI_M>(system, nv_flinger)->InstallAsService(service_manager); + std::make_shared<VI_S>(system, nv_flinger)->InstallAsService(service_manager); + std::make_shared<VI_U>(system, nv_flinger)->InstallAsService(service_manager); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 6b66f8b81..eec531d54 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h @@ -7,6 +7,10 @@ #include <memory> #include "common/common_types.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -43,12 +47,12 @@ enum class Policy { }; namespace detail { -void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, Permission permission); +void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, Core::System& system, + NVFlinger::NVFlinger& nv_flinger, Permission permission); } // namespace detail /// Registers all VI services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager, - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); +void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system, + NVFlinger::NVFlinger& nv_flinger); } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp index 06070087f..87db1c416 100644 --- a/src/core/hle/service/vi/vi_m.cpp +++ b/src/core/hle/service/vi/vi_m.cpp @@ -8,8 +8,8 @@ namespace Service::VI { -VI_M::VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework{"vi:m"}, nv_flinger{std::move(nv_flinger)} { +VI_M::VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_} { static const FunctionInfo functions[] = { {2, &VI_M::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -22,7 +22,7 @@ VI_M::~VI_M() = default; void VI_M::GetDisplayService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); - detail::GetDisplayServiceImpl(ctx, nv_flinger, Permission::Manager); + detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::Manager); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h index 290e06689..d79c41beb 100644 --- a/src/core/hle/service/vi/vi_m.h +++ b/src/core/hle/service/vi/vi_m.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -18,13 +22,13 @@ namespace Service::VI { class VI_M final : public ServiceFramework<VI_M> { public: - explicit VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); + explicit VI_M(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); ~VI_M() override; private: void GetDisplayService(Kernel::HLERequestContext& ctx); - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; + NVFlinger::NVFlinger& nv_flinger; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp index 57c596cc4..5cd22f7df 100644 --- a/src/core/hle/service/vi/vi_s.cpp +++ b/src/core/hle/service/vi/vi_s.cpp @@ -8,8 +8,8 @@ namespace Service::VI { -VI_S::VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework{"vi:s"}, nv_flinger{std::move(nv_flinger)} { +VI_S::VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_} { static const FunctionInfo functions[] = { {1, &VI_S::GetDisplayService, "GetDisplayService"}, {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -22,7 +22,7 @@ VI_S::~VI_S() = default; void VI_S::GetDisplayService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); - detail::GetDisplayServiceImpl(ctx, nv_flinger, Permission::System); + detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::System); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h index 47804dc0b..5f1f8f290 100644 --- a/src/core/hle/service/vi/vi_s.h +++ b/src/core/hle/service/vi/vi_s.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -18,13 +22,13 @@ namespace Service::VI { class VI_S final : public ServiceFramework<VI_S> { public: - explicit VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); + explicit VI_S(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); ~VI_S() override; private: void GetDisplayService(Kernel::HLERequestContext& ctx); - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; + NVFlinger::NVFlinger& nv_flinger; }; } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp index 6b7329345..0079d51f0 100644 --- a/src/core/hle/service/vi/vi_u.cpp +++ b/src/core/hle/service/vi/vi_u.cpp @@ -8,8 +8,8 @@ namespace Service::VI { -VI_U::VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) - : ServiceFramework{"vi:u"}, nv_flinger{std::move(nv_flinger)} { +VI_U::VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_) + : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_} { static const FunctionInfo functions[] = { {0, &VI_U::GetDisplayService, "GetDisplayService"}, {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, @@ -22,7 +22,7 @@ VI_U::~VI_U() = default; void VI_U::GetDisplayService(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_VI, "called"); - detail::GetDisplayServiceImpl(ctx, nv_flinger, Permission::User); + detail::GetDisplayServiceImpl(ctx, system, nv_flinger, Permission::User); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h index 19bdb73b0..8e3885c73 100644 --- a/src/core/hle/service/vi/vi_u.h +++ b/src/core/hle/service/vi/vi_u.h @@ -6,6 +6,10 @@ #include "core/hle/service/service.h" +namespace Core { +class System; +} + namespace Kernel { class HLERequestContext; } @@ -18,13 +22,13 @@ namespace Service::VI { class VI_U final : public ServiceFramework<VI_U> { public: - explicit VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); + explicit VI_U(Core::System& system_, NVFlinger::NVFlinger& nv_flinger_); ~VI_U() override; private: void GetDisplayService(Kernel::HLERequestContext& ctx); - std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; + NVFlinger::NVFlinger& nv_flinger; }; } // namespace Service::VI diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp index 0260d7dcf..ddbf04069 100644 --- a/src/core/hle/service/wlan/wlan.cpp +++ b/src/core/hle/service/wlan/wlan.cpp @@ -12,7 +12,7 @@ namespace Service::WLAN { class WLANInfra final : public ServiceFramework<WLANInfra> { public: - explicit WLANInfra() : ServiceFramework{"wlan:inf"} { + explicit WLANInfra(Core::System& system_) : ServiceFramework{system_, "wlan:inf"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenMode"}, @@ -55,7 +55,7 @@ public: class WLANLocal final : public ServiceFramework<WLANLocal> { public: - explicit WLANLocal() : ServiceFramework{"wlan:lcl"} { + explicit WLANLocal(Core::System& system_) : ServiceFramework{system_, "wlan:lcl"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown0"}, @@ -120,7 +120,7 @@ public: class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> { public: - explicit WLANLocalGetFrame() : ServiceFramework{"wlan:lg"} { + explicit WLANLocalGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:lg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown"}, @@ -133,7 +133,7 @@ public: class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> { public: - explicit WLANSocketGetFrame() : ServiceFramework{"wlan:sg"} { + explicit WLANSocketGetFrame(Core::System& system_) : ServiceFramework{system_, "wlan:sg"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown"}, @@ -146,7 +146,7 @@ public: class WLANSocketManager final : public ServiceFramework<WLANSocketManager> { public: - explicit WLANSocketManager() : ServiceFramework{"wlan:soc"} { + explicit WLANSocketManager(Core::System& system_) : ServiceFramework{system_, "wlan:soc"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "Unknown0"}, @@ -169,12 +169,12 @@ public: } }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<WLANInfra>()->InstallAsService(sm); - std::make_shared<WLANLocal>()->InstallAsService(sm); - std::make_shared<WLANLocalGetFrame>()->InstallAsService(sm); - std::make_shared<WLANSocketGetFrame>()->InstallAsService(sm); - std::make_shared<WLANSocketManager>()->InstallAsService(sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) { + std::make_shared<WLANInfra>(system)->InstallAsService(sm); + std::make_shared<WLANLocal>(system)->InstallAsService(sm); + std::make_shared<WLANLocalGetFrame>(system)->InstallAsService(sm); + std::make_shared<WLANSocketGetFrame>(system)->InstallAsService(sm); + std::make_shared<WLANSocketManager>(system)->InstallAsService(sm); } } // namespace Service::WLAN diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h index 054ea928a..3899eedbb 100644 --- a/src/core/hle/service/wlan/wlan.h +++ b/src/core/hle/service/wlan/wlan.h @@ -4,12 +4,16 @@ #pragma once +namespace Core { +class System; +} + namespace Service::SM { class ServiceManager; } namespace Service::WLAN { -void InstallInterfaces(SM::ServiceManager& sm); +void InstallInterfaces(SM::ServiceManager& sm, Core::System& system); } // namespace Service::WLAN diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 394a1bf26..79ebf11de 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -12,7 +12,6 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/romfs_factory.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" @@ -114,7 +113,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect } if (override_update) { - const FileSys::PatchManager patch_manager(metadata.GetTitleID()); + const FileSys::PatchManager patch_manager( + metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider()); dir = patch_manager.PatchExeFS(dir); } @@ -160,7 +160,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect modules.clear(); const VAddr base_address{process.PageTable().GetCodeRegionStart()}; VAddr next_load_addr{base_address}; - const FileSys::PatchManager pm{metadata.GetTitleID()}; + const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), + system.GetContentProvider()}; for (const auto& module : static_modules) { const FileSys::VirtualFile module_file{dir->GetFile(module)}; if (!module_file) { @@ -178,8 +179,6 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect next_load_addr = *tentative_next_load_addr; modules.insert_or_assign(load_addr, module); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr); - // Register module with GDBStub - GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false); } // Find the RomFS by searching for a ".romfs" file in this directory diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 2a905d3e4..e162c4ff0 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -5,7 +5,6 @@ #include <cstring> #include "core/file_sys/kernel_executable.h" #include "core/file_sys/program_metadata.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" @@ -91,8 +90,6 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process, program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize()); codeset.DataSegment().size += kip->GetBSSSize(); - GDBStub::RegisterModule(kip->GetName(), base_address, base_address + program_image.size()); - codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), base_address); diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 9bc3a8840..d91c15561 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -10,6 +10,7 @@ #include "common/file_util.h" #include "common/logging/log.h" #include "common/string_util.h" +#include "core/core.h" #include "core/hle/kernel/process.h" #include "core/loader/deconstructed_rom_directory.h" #include "core/loader/elf.h" @@ -194,15 +195,15 @@ AppLoader::~AppLoader() = default; /** * Get a loader for a file with a specific type - * @param file The file to load - * @param type The type of the file - * @param file the file to retrieve the loader for - * @param type the file type + * @param system The system context to use. + * @param file The file to retrieve the loader for + * @param type The file type + * @param program_index Specifies the index within the container of the program to launch. * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type */ -static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileType type) { +static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file, + FileType type, std::size_t program_index) { switch (type) { - // Standard ELF file format. case FileType::ELF: return std::make_unique<AppLoader_ELF>(std::move(file)); @@ -221,7 +222,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT // NX XCI (nX Card Image) file format. case FileType::XCI: - return std::make_unique<AppLoader_XCI>(std::move(file)); + return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(), + system.GetContentProvider(), program_index); // NX NAX (NintendoAesXts) file format. case FileType::NAX: @@ -229,7 +231,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT // NX NSP (Nintendo Submission Package) file format case FileType::NSP: - return std::make_unique<AppLoader_NSP>(std::move(file)); + return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(), + system.GetContentProvider(), program_index); // NX KIP (Kernel Internal Process) file format case FileType::KIP: @@ -244,20 +247,22 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT } } -std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file) { +std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, + std::size_t program_index) { FileType type = IdentifyFile(file); - FileType filename_type = GuessFromFilename(file->GetName()); + const FileType filename_type = GuessFromFilename(file->GetName()); // Special case: 00 is either a NCA or NAX. if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) { LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName()); - if (FileType::Unknown == type) + if (FileType::Unknown == type) { type = filename_type; + } } LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); - return GetFileLoader(std::move(file), type); + return GetFileLoader(system, std::move(file), type, program_index); } } // namespace Loader diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index ac60b097a..36e79e71d 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -290,9 +290,14 @@ protected: /** * Identifies a bootable file and return a suitable loader - * @param file The bootable file - * @return the best loader for this file + * + * @param system The system context. + * @param file The bootable file. + * @param program_index Specifies the index within the container of the program to launch. + * + * @return the best loader for this file. */ -std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file); +std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, + std::size_t program_index = 0); } // namespace Loader diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 5f4b3104b..ccf8cc153 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -14,10 +14,10 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/vfs_offset.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/nro.h" #include "core/loader/nso.h" @@ -197,10 +197,6 @@ static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data, codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart()); - // Register module with GDBStub - GDBStub::RegisterModule(name, process.PageTable().GetCodeRegionStart(), - process.PageTable().GetCodeRegionEnd()); - return true; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 497f438a1..95b6f339a 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -14,10 +14,10 @@ #include "common/swap.h" #include "core/core.h" #include "core/file_sys/patch_manager.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/thread.h" #include "core/loader/nso.h" #include "core/memory.h" #include "core/settings.h" @@ -149,7 +149,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S // Apply cheats if they exist and the program has a valid title ID if (pm) { system.SetCurrentProcessBuildID(nso_header.build_id); - const auto cheats = pm->CreateCheatList(system, nso_header.build_id); + const auto cheats = pm->CreateCheatList(nso_header.build_id); if (!cheats.empty()) { system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size); } @@ -159,9 +159,6 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S codeset.memory = std::move(program_image); process.LoadModule(std::move(codeset), load_base); - // Register module with GDBStub - GDBStub::RegisterModule(file.GetName(), load_base, load_base); - return load_base + image_size; } diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 15e528fa8..928f64c8c 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -21,26 +21,34 @@ namespace Loader { -AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) - : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)), +AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider, + std::size_t program_index) + : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file, program_index)), title_id(nsp->GetProgramTitleID()) { - if (nsp->GetStatus() != ResultStatus::Success) + if (nsp->GetStatus() != ResultStatus::Success) { return; + } if (nsp->IsExtractedType()) { secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); } else { const auto control_nca = nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); - if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) + if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) { return; + } - std::tie(nacp_file, icon_file) = - FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca); + std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] { + const FileSys::PatchManager pm{nsp->GetProgramTitleID(), fsc, content_provider}; + return pm.ParseControlNCA(*control_nca); + }(); - if (title_id == 0) + if (title_id == 0) { return; + } secondary_loader = std::make_unique<AppLoader_NCA>( nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h index b27deb686..f0518ac47 100644 --- a/src/core/loader/nsp.h +++ b/src/core/loader/nsp.h @@ -9,15 +9,16 @@ #include "core/file_sys/vfs.h" #include "core/loader/loader.h" -namespace Core { -class System; -} - namespace FileSys { +class ContentProvider; class NACP; class NSP; } // namespace FileSys +namespace Service::FileSystem { +class FileSystemController; +} + namespace Loader { class AppLoader_NCA; @@ -25,7 +26,10 @@ class AppLoader_NCA; /// Loads an XCI file class AppLoader_NSP final : public AppLoader { public: - explicit AppLoader_NSP(FileSys::VirtualFile file); + explicit AppLoader_NSP(FileSys::VirtualFile file, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider, + std::size_t program_index); ~AppLoader_NSP() override; /** diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index 25e83af0f..aaa250cea 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -20,18 +20,25 @@ namespace Loader { -AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) - : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), +AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider, + std::size_t program_index) + : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file, program_index)), nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { - if (xci->GetStatus() != ResultStatus::Success) + if (xci->GetStatus() != ResultStatus::Success) { return; + } const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); - if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) + if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) { return; + } - std::tie(nacp_file, icon_file) = - FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(*control_nca); + std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] { + const FileSys::PatchManager pm{xci->GetProgramTitleID(), fsc, content_provider}; + return pm.ParseControlNCA(*control_nca); + }(); } AppLoader_XCI::~AppLoader_XCI() = default; diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h index 04aea286f..764dc8328 100644 --- a/src/core/loader/xci.h +++ b/src/core/loader/xci.h @@ -9,15 +9,16 @@ #include "core/file_sys/vfs.h" #include "core/loader/loader.h" -namespace Core { -class System; -} - namespace FileSys { +class ContentProvider; class NACP; class XCI; } // namespace FileSys +namespace Service::FileSystem { +class FileSystemController; +} + namespace Loader { class AppLoader_NCA; @@ -25,7 +26,10 @@ class AppLoader_NCA; /// Loads an XCI file class AppLoader_XCI final : public AppLoader { public: - explicit AppLoader_XCI(FileSys::VirtualFile file); + explicit AppLoader_XCI(FileSys::VirtualFile file, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider, + std::size_t program_index); ~AppLoader_XCI() override; /** diff --git a/src/core/settings.cpp b/src/core/settings.cpp index aadbc3932..e9997a263 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -4,9 +4,10 @@ #include <string_view> +#include "common/assert.h" #include "common/file_util.h" +#include "common/logging/log.h" #include "core/core.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/service/hid/hid.h" #include "core/settings.h" #include "video_core/renderer_base.h" @@ -31,13 +32,9 @@ std::string GetTimeZoneString() { return timezones[time_zone_index]; } -void Apply() { - GDBStub::SetServerPort(values.gdbstub_port); - GDBStub::ToggleServer(values.use_gdbstub); - - auto& system_instance = Core::System::GetInstance(); - if (system_instance.IsPoweredOn()) { - system_instance.Renderer().RefreshBaseSettings(); +void Apply(Core::System& system) { + if (system.IsPoweredOn()) { + system.Renderer().RefreshBaseSettings(); } Service::HID::ReloadInputDevices(); @@ -106,9 +103,9 @@ float Volume() { return values.volume.GetValue(); } -void RestoreGlobalState() { +void RestoreGlobalState(bool is_powered_on) { // If a game is running, DO NOT restore the global settings state - if (Core::System::GetInstance().IsPoweredOn()) { + if (is_powered_on) { return; } diff --git a/src/core/settings.h b/src/core/settings.h index 476c3fdf3..3df611d5b 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -14,6 +14,10 @@ #include "common/common_types.h" #include "input_common/settings.h" +namespace Core { +class System; +} + namespace Settings { enum class RendererBackend { @@ -215,6 +219,7 @@ struct Values { bool reporting_services; bool quest_flag; bool disable_macro_jit; + bool extended_logging; // Misceallaneous std::string log_filter; @@ -246,11 +251,11 @@ float Volume(); std::string GetTimeZoneString(); -void Apply(); +void Apply(Core::System& system); void LogSettings(); // Restore the global state of all applicable settings in the Values struct -void RestoreGlobalState(); +void RestoreGlobalState(bool is_powered_on); // Fixes settings that are known to cause issues with the emulator void Sanitize(); diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index e0908186b..d11b15f38 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -147,7 +147,9 @@ TelemetrySession::~TelemetrySession() { } } -void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { +void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider) { // Log one-time top-level information AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); @@ -167,7 +169,10 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { app_loader.ReadTitle(name); if (name.empty()) { - const auto metadata = FileSys::PatchManager(program_id).GetControlMetadata(); + const auto metadata = [&content_provider, &fsc, program_id] { + const FileSys::PatchManager pm{program_id, fsc, content_provider}; + return pm.GetControlMetadata(); + }(); if (metadata.first != nullptr) { name = metadata.first->GetApplicationName(); } diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 66789d4bd..6f3d45bea 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -7,10 +7,18 @@ #include <string> #include "common/telemetry.h" +namespace FileSys { +class ContentProvider; +} + namespace Loader { class AppLoader; } +namespace Service::FileSystem { +class FileSystemController; +} + namespace Core { /** @@ -40,10 +48,14 @@ public: * - Title file format * - Miscellaneous settings values. * - * @param app_loader The application loader to use to retrieve - * title-specific information. + * @param app_loader The application loader to use to retrieve + * title-specific information. + * @param fsc Filesystem controller to use to retrieve info. + * @param content_provider Content provider to use to retrieve info. */ - void AddInitialInfo(Loader::AppLoader& app_loader); + void AddInitialInfo(Loader::AppLoader& app_loader, + const Service::FileSystem::FileSystemController& fsc, + const FileSys::ContentProvider& content_provider); /** * Wrapper around the Telemetry::FieldCollection::AddField method. diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 1619e5e4e..38ab31898 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -33,6 +33,9 @@ add_library(input_common STATIC if (MSVC) target_compile_options(input_common PRIVATE + /W4 + /WX + # 'expression' : signed/unsigned mismatch /we4018 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) @@ -48,14 +51,15 @@ if (MSVC) ) else() target_compile_options(input_common PRIVATE + -Werror -Werror=conversion -Werror=ignored-qualifiers -Werror=implicit-fallthrough -Werror=reorder -Werror=shadow -Werror=sign-compare - -Werror=unused-but-set-parameter - -Werror=unused-but-set-variable + $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> + $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> -Werror=unused-variable ) endif() diff --git a/src/input_common/analog_from_button.cpp b/src/input_common/analog_from_button.cpp index 74744d7f3..d748c1c04 100755 --- a/src/input_common/analog_from_button.cpp +++ b/src/input_common/analog_from_button.cpp @@ -2,6 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <chrono> +#include <cmath> +#include <thread> +#include "common/math_util.h" #include "input_common/analog_from_button.h" namespace InputCommon { @@ -11,31 +15,104 @@ public: using Button = std::unique_ptr<Input::ButtonDevice>; Analog(Button up_, Button down_, Button left_, Button right_, Button modifier_, - float modifier_scale_) + float modifier_scale_, float modifier_angle_) : up(std::move(up_)), down(std::move(down_)), left(std::move(left_)), - right(std::move(right_)), modifier(std::move(modifier_)), - modifier_scale(modifier_scale_) {} - - std::tuple<float, float> GetStatus() const override { - constexpr float SQRT_HALF = 0.707106781f; - int x = 0, y = 0; + right(std::move(right_)), modifier(std::move(modifier_)), modifier_scale(modifier_scale_), + modifier_angle(modifier_angle_) { + update_thread = std::thread(&Analog::UpdateStatus, this); + } - if (right->GetStatus()) { - ++x; + ~Analog() override { + update_thread_running = false; + if (update_thread.joinable()) { + update_thread.join(); } - if (left->GetStatus()) { - --x; + } + + void MoveToDirection(bool enable, float to_angle) { + if (!enable) { + return; } - if (up->GetStatus()) { - ++y; + constexpr float TAU = Common::PI * 2.0f; + // Use wider angle to ease the transition. + constexpr float aperture = TAU * 0.15f; + const float top_limit = to_angle + aperture; + const float bottom_limit = to_angle - aperture; + + if ((angle > to_angle && angle <= top_limit) || + (angle + TAU > to_angle && angle + TAU <= top_limit)) { + angle -= modifier_angle; + if (angle < 0) { + angle += TAU; + } + } else if ((angle >= bottom_limit && angle < to_angle) || + (angle - TAU >= bottom_limit && angle - TAU < to_angle)) { + angle += modifier_angle; + if (angle >= TAU) { + angle -= TAU; + } + } else { + angle = to_angle; } - if (down->GetStatus()) { - --y; + } + + void UpdateStatus() { + while (update_thread_running) { + const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; + + bool r = right->GetStatus(); + bool l = left->GetStatus(); + bool u = up->GetStatus(); + bool d = down->GetStatus(); + + // Eliminate contradictory movements + if (r && l) { + r = false; + l = false; + } + if (u && d) { + u = false; + d = false; + } + + // Move to the right + MoveToDirection(r && !u && !d, 0.0f); + + // Move to the upper right + MoveToDirection(r && u && !d, Common::PI * 0.25f); + + // Move up + MoveToDirection(u && !l && !r, Common::PI * 0.5f); + + // Move to the upper left + MoveToDirection(l && u && !d, Common::PI * 0.75f); + + // Move to the left + MoveToDirection(l && !u && !d, Common::PI); + + // Move to the bottom left + MoveToDirection(l && !u && d, Common::PI * 1.25f); + + // Move down + MoveToDirection(d && !l && !r, Common::PI * 1.5f); + + // Move to the bottom right + MoveToDirection(r && !u && d, Common::PI * 1.75f); + + // Move if a key is pressed + if (r || l || u || d) { + amplitude = coef; + } else { + amplitude = 0; + } + + // Delay the update rate to 100hz + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + } - const float coef = modifier->GetStatus() ? modifier_scale : 1.0f; - return std::make_tuple(static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF), - static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF)); + std::tuple<float, float> GetStatus() const override { + return std::make_tuple(std::cos(angle) * amplitude, std::sin(angle) * amplitude); } bool GetAnalogDirectionStatus(Input::AnalogDirection direction) const override { @@ -59,6 +136,11 @@ private: Button right; Button modifier; float modifier_scale; + float modifier_angle; + float angle{}; + float amplitude{}; + std::thread update_thread; + bool update_thread_running{true}; }; std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::ParamPackage& params) { @@ -69,8 +151,10 @@ std::unique_ptr<Input::AnalogDevice> AnalogFromButton::Create(const Common::Para auto right = Input::CreateDevice<Input::ButtonDevice>(params.Get("right", null_engine)); auto modifier = Input::CreateDevice<Input::ButtonDevice>(params.Get("modifier", null_engine)); auto modifier_scale = params.Get("modifier_scale", 0.5f); + auto modifier_angle = params.Get("modifier_angle", 0.035f); return std::make_unique<Analog>(std::move(up), std::move(down), std::move(left), - std::move(right), std::move(modifier), modifier_scale); + std::move(right), std::move(modifier), modifier_scale, + modifier_angle); } } // namespace InputCommon diff --git a/src/input_common/gcadapter/gc_poller.cpp b/src/input_common/gcadapter/gc_poller.cpp index fe57c13a5..4d1052414 100644 --- a/src/input_common/gcadapter/gc_poller.cpp +++ b/src/input_common/gcadapter/gc_poller.cpp @@ -96,7 +96,6 @@ std::unique_ptr<Input::ButtonDevice> GCButtonFactory::Create(const Common::Param adapter.get()); } - UNREACHABLE(); return nullptr; } @@ -300,10 +299,11 @@ public: return gcadapter->RumblePlay(port, 0); } - bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { + bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high, + [[maybe_unused]] f32 freq_high) const override { const auto mean_amplitude = (amp_low + amp_high) * 0.5f; - const auto processed_amplitude = static_cast<u8>( - pow(mean_amplitude, 0.5f) * (3.0f - 2.0f * pow(mean_amplitude, 0.15f)) * 0x8); + const auto processed_amplitude = + static_cast<u8>((mean_amplitude + std::pow(mean_amplitude, 0.3f)) * 0.5f * 0x8); return gcadapter->RumblePlay(port, processed_amplitude); } diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index f3554be9a..42bbf14d4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h @@ -23,7 +23,7 @@ public: /// Unregisters SDL device factories and shut them down. virtual ~State() = default; - virtual Pollers GetPollers(Polling::DeviceType type) { + virtual Pollers GetPollers(Polling::DeviceType) { return {}; } diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 8c48bb861..7827e324c 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -400,10 +400,10 @@ public: return joystick->RumblePlay(0, 0); } - bool SetRumblePlay(f32 amp_low, f32 freq_low, f32 amp_high, f32 freq_high) const override { + bool SetRumblePlay(f32 amp_low, [[maybe_unused]] f32 freq_low, f32 amp_high, + [[maybe_unused]] f32 freq_high) const override { const auto process_amplitude = [](f32 amplitude) { - return static_cast<u16>(std::pow(amplitude, 0.5f) * - (3.0f - 2.0f * std::pow(amplitude, 0.15f)) * 0xFFFF); + return static_cast<u16>((amplitude + std::pow(amplitude, 0.3f)) * 0.5f * 0xFFFF); }; const auto processed_amp_low = process_amplitude(amp_low); @@ -865,6 +865,8 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) { switch (binding.bindType) { + case SDL_CONTROLLER_BINDTYPE_NONE: + break; case SDL_CONTROLLER_BINDTYPE_AXIS: return BuildAnalogParamPackageForButton(port, guid, binding.value.axis); case SDL_CONTROLLER_BINDTYPE_BUTTON: @@ -985,7 +987,7 @@ class SDLPoller : public InputCommon::Polling::DevicePoller { public: explicit SDLPoller(SDLState& state_) : state(state_) {} - void Start(const std::string& device_id) override { + void Start([[maybe_unused]] const std::string& device_id) override { state.event_queue.Clear(); state.polling = true; } diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index c37716aae..a07124a86 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp @@ -44,8 +44,7 @@ private: std::vector<std::tuple<std::unique_ptr<Input::ButtonDevice>, int, int>> map; }; -std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create( - const Common::ParamPackage& params) { +std::unique_ptr<Input::TouchDevice> TouchFromButtonFactory::Create(const Common::ParamPackage&) { return std::make_unique<TouchFromButtonDevice>(); } diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 3677e79ca..c0bb90048 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp @@ -63,7 +63,7 @@ public: } private: - void HandleReceive(const boost::system::error_code& error, std::size_t bytes_transferred) { + void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) { if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { switch (*type) { case Type::Version: { @@ -90,7 +90,7 @@ private: StartReceive(); } - void HandleSend(const boost::system::error_code& error) { + void HandleSend(const boost::system::error_code&) { boost::system::error_code _ignored{}; // Send a request for getting port info for the pad const Request::PortInfo port_info{1, {static_cast<u8>(pad_index), 0, 0, 0}}; @@ -189,11 +189,11 @@ void Client::ReloadSocket(const std::string& host, u16 port, std::size_t pad_ind StartCommunication(client, host, port, pad_index, client_id); } -void Client::OnVersion(Response::Version data) { +void Client::OnVersion([[maybe_unused]] Response::Version data) { LOG_TRACE(Input, "Version packet received: {}", data.version); } -void Client::OnPortInfo(Response::PortInfo data) { +void Client::OnPortInfo([[maybe_unused]] Response::PortInfo data) { LOG_TRACE(Input, "PortInfo packet received: {}", data.model); } @@ -369,7 +369,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( u16 max_y{}; Status current_status{Status::Initialized}; - SocketCallback callback{[](Response::Version version) {}, [](Response::PortInfo info) {}, + SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) { if (current_status == Status::Initialized) { // Receiving data means the communication is ready now diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h index 3ba4d1fc8..fc1aea4b9 100644 --- a/src/input_common/udp/protocol.h +++ b/src/input_common/udp/protocol.h @@ -7,7 +7,16 @@ #include <array> #include <optional> #include <type_traits> + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4701) +#endif #include <boost/crc.hpp> +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #include "common/bit_field.h" #include "common/swap.h" @@ -93,7 +102,7 @@ static_assert(std::is_trivially_copyable_v<PadData>, /** * Creates a message with the proper header data that can be sent to the server. - * @param T data Request body to send + * @param data Request body to send * @param client_id ID of the udp client (usually not checked on the server) */ template <typename T> diff --git a/src/tests/common/bit_field.cpp b/src/tests/common/bit_field.cpp index 8ca1889f9..182638000 100644 --- a/src/tests/common/bit_field.cpp +++ b/src/tests/common/bit_field.cpp @@ -68,7 +68,7 @@ TEST_CASE("BitField", "[common]") { }}); // bit fields: 01101100111101'10101110'1011'101100 - REQUIRE(be_bitfield.raw == 0b01101100'11110110'10111010'11101100); + REQUIRE(be_bitfield.raw == 0b01101100'11110110'10111010'11101100U); REQUIRE(be_bitfield.a == 0b101100); REQUIRE(be_bitfield.b == -5); // 1011 as two's complement REQUIRE(be_bitfield.c == TestEnum::B); @@ -80,7 +80,7 @@ TEST_CASE("BitField", "[common]") { be_bitfield.d.Assign(0b01010101010101); std::memcpy(&raw, &be_bitfield, sizeof(raw)); // bit fields: 01010101010101'00001111'1111'000111 - REQUIRE(be_bitfield.raw == 0b01010101'01010100'00111111'11000111); + REQUIRE(be_bitfield.raw == 0b01010101'01010100'00111111'11000111U); REQUIRE(raw == std::array<u8, 4>{{ 0b01010101, 0b01010100, diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index 5bbe6a332..ee5d62540 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h @@ -10,6 +10,7 @@ extern "C" { #if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #endif #include <libavcodec/avcodec.h> diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index a3c05d1b0..37d17efdc 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -32,31 +32,31 @@ struct Register { constexpr Register() = default; - constexpr Register(u64 value) : value(value) {} + constexpr Register(u64 value_) : value(value_) {} - constexpr operator u64() const { + [[nodiscard]] constexpr operator u64() const { return value; } template <typename T> - constexpr u64 operator-(const T& oth) const { + [[nodiscard]] constexpr u64 operator-(const T& oth) const { return value - oth; } template <typename T> - constexpr u64 operator&(const T& oth) const { + [[nodiscard]] constexpr u64 operator&(const T& oth) const { return value & oth; } - constexpr u64 operator&(const Register& oth) const { + [[nodiscard]] constexpr u64 operator&(const Register& oth) const { return value & oth.value; } - constexpr u64 operator~() const { + [[nodiscard]] constexpr u64 operator~() const { return ~value; } - u64 GetSwizzledIndex(u64 elem) const { + [[nodiscard]] u64 GetSwizzledIndex(u64 elem) const { elem = (value + elem) & 3; return (value & ~3) + elem; } @@ -75,7 +75,7 @@ enum class AttributeSize : u64 { union Attribute { Attribute() = default; - constexpr explicit Attribute(u64 value) : value(value) {} + constexpr explicit Attribute(u64 value_) : value(value_) {} enum class Index : u64 { LayerViewportPointSize = 6, @@ -107,7 +107,7 @@ union Attribute { BitField<31, 1, u64> patch; BitField<47, 3, AttributeSize> size; - bool IsPhysical() const { + [[nodiscard]] bool IsPhysical() const { return patch == 0 && element == 0 && static_cast<u64>(index.Value()) == 0; } } fmt20; @@ -124,7 +124,7 @@ union Attribute { union Sampler { Sampler() = default; - constexpr explicit Sampler(u64 value) : value(value) {} + constexpr explicit Sampler(u64 value_) : value(value_) {} enum class Index : u64 { Sampler_0 = 8, @@ -137,7 +137,7 @@ union Sampler { union Image { Image() = default; - constexpr explicit Image(u64 value) : value{value} {} + constexpr explicit Image(u64 value_) : value{value_} {} BitField<36, 13, u64> index; u64 value; @@ -505,14 +505,14 @@ struct IpaMode { IpaInterpMode interpolation_mode; IpaSampleMode sampling_mode; - bool operator==(const IpaMode& a) const { + [[nodiscard]] bool operator==(const IpaMode& a) const { return std::tie(interpolation_mode, sampling_mode) == std::tie(a.interpolation_mode, a.sampling_mode); } - bool operator!=(const IpaMode& a) const { + [[nodiscard]] bool operator!=(const IpaMode& a) const { return !operator==(a); } - bool operator<(const IpaMode& a) const { + [[nodiscard]] bool operator<(const IpaMode& a) const { return std::tie(interpolation_mode, sampling_mode) < std::tie(a.interpolation_mode, a.sampling_mode); } @@ -658,10 +658,10 @@ union Instruction { return *this; } - constexpr Instruction(u64 value) : value{value} {} + constexpr Instruction(u64 value_) : value{value_} {} constexpr Instruction(const Instruction& instr) : value(instr.value) {} - constexpr bool Bit(u64 offset) const { + [[nodiscard]] constexpr bool Bit(u64 offset) const { return ((value >> offset) & 1) != 0; } @@ -746,34 +746,34 @@ union Instruction { BitField<28, 8, u64> imm_lut28; BitField<48, 8, u64> imm_lut48; - u32 GetImmLut28() const { + [[nodiscard]] u32 GetImmLut28() const { return static_cast<u32>(imm_lut28); } - u32 GetImmLut48() const { + [[nodiscard]] u32 GetImmLut48() const { return static_cast<u32>(imm_lut48); } } lop3; - u16 GetImm20_16() const { + [[nodiscard]] u16 GetImm20_16() const { return static_cast<u16>(imm20_16); } - u32 GetImm20_19() const { + [[nodiscard]] u32 GetImm20_19() const { u32 imm{static_cast<u32>(imm20_19)}; imm <<= 12; imm |= negate_imm ? 0x80000000 : 0; return imm; } - u32 GetImm20_32() const { + [[nodiscard]] u32 GetImm20_32() const { return static_cast<u32>(imm20_32); } - s32 GetSignedImm20_20() const { - u32 immediate = static_cast<u32>(imm20_19 | (negate_imm << 19)); + [[nodiscard]] s32 GetSignedImm20_20() const { + const auto immediate = static_cast<u32>(imm20_19 | (negate_imm << 19)); // Sign extend the 20-bit value. - u32 mask = 1U << (20 - 1); + const auto mask = 1U << (20 - 1); return static_cast<s32>((immediate ^ mask) - mask); } } alu; @@ -857,7 +857,7 @@ union Instruction { BitField<56, 1, u64> second_negate; BitField<30, 9, u64> second; - u32 PackImmediates() const { + [[nodiscard]] u32 PackImmediates() const { // Immediates are half floats shifted. constexpr u32 imm_shift = 6; return static_cast<u32>((first << imm_shift) | (second << (16 + imm_shift))); @@ -1033,7 +1033,7 @@ union Instruction { BitField<28, 2, AtomicType> type; BitField<30, 22, s64> offset; - s32 GetImmediateOffset() const { + [[nodiscard]] s32 GetImmediateOffset() const { return static_cast<s32>(offset << 2); } } atoms; @@ -1215,7 +1215,7 @@ union Instruction { BitField<39, 4, u64> rounding; // H0, H1 extract for F16 missing BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value - F2fRoundingOp GetRoundingMode() const { + [[nodiscard]] F2fRoundingOp GetRoundingMode() const { constexpr u64 rounding_mask = 0x0B; return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask); } @@ -1239,15 +1239,15 @@ union Instruction { BitField<54, 1, u64> aoffi_flag; BitField<55, 3, TextureProcessMode> process_mode; - bool IsComponentEnabled(std::size_t component) const { - return ((1ull << component) & component_mask) != 0; + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { + return ((1ULL << component) & component_mask) != 0; } - TextureProcessMode GetTextureProcessMode() const { + [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { return process_mode; } - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::DC: return dc_flag != 0; @@ -1271,15 +1271,15 @@ union Instruction { BitField<36, 1, u64> aoffi_flag; BitField<37, 3, TextureProcessMode> process_mode; - bool IsComponentEnabled(std::size_t component) const { + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { return ((1ULL << component) & component_mask) != 0; } - TextureProcessMode GetTextureProcessMode() const { + [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { return process_mode; } - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::DC: return dc_flag != 0; @@ -1299,7 +1299,7 @@ union Instruction { BitField<31, 4, u64> component_mask; BitField<49, 1, u64> nodep_flag; - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::NODEP: return nodep_flag != 0; @@ -1309,7 +1309,7 @@ union Instruction { return false; } - bool IsComponentEnabled(std::size_t component) const { + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { return ((1ULL << component) & component_mask) != 0; } } txq; @@ -1321,11 +1321,11 @@ union Instruction { BitField<35, 1, u64> ndv_flag; BitField<49, 1, u64> nodep_flag; - bool IsComponentEnabled(std::size_t component) const { - return ((1ull << component) & component_mask) != 0; + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { + return ((1ULL << component) & component_mask) != 0; } - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::NDV: return (ndv_flag != 0); @@ -1347,7 +1347,7 @@ union Instruction { BitField<54, 2, u64> offset_mode; BitField<56, 2, u64> component; - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::NDV: return ndv_flag != 0; @@ -1373,7 +1373,7 @@ union Instruction { BitField<33, 2, u64> offset_mode; BitField<37, 2, u64> component; - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::NDV: return ndv_flag != 0; @@ -1399,7 +1399,7 @@ union Instruction { BitField<52, 2, u64> component; BitField<55, 1, u64> fp16_flag; - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::DC: return dc_flag != 0; @@ -1422,16 +1422,20 @@ union Instruction { BitField<53, 4, u64> texture_info; BitField<59, 1, u64> fp32_flag; - TextureType GetTextureType() const { + [[nodiscard]] TextureType GetTextureType() const { // The TEXS instruction has a weird encoding for the texture type. - if (texture_info == 0) + if (texture_info == 0) { return TextureType::Texture1D; - if (texture_info >= 1 && texture_info <= 9) + } + if (texture_info >= 1 && texture_info <= 9) { return TextureType::Texture2D; - if (texture_info >= 10 && texture_info <= 11) + } + if (texture_info >= 10 && texture_info <= 11) { return TextureType::Texture3D; - if (texture_info >= 12 && texture_info <= 13) + } + if (texture_info >= 12 && texture_info <= 13) { return TextureType::TextureCube; + } LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}", static_cast<u32>(texture_info.Value())); @@ -1439,7 +1443,7 @@ union Instruction { return TextureType::Texture1D; } - TextureProcessMode GetTextureProcessMode() const { + [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { switch (texture_info) { case 0: case 2: @@ -1458,7 +1462,7 @@ union Instruction { return TextureProcessMode::None; } - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::DC: return (texture_info >= 4 && texture_info <= 6) || texture_info == 9; @@ -1470,16 +1474,16 @@ union Instruction { return false; } - bool IsArrayTexture() const { + [[nodiscard]] bool IsArrayTexture() const { // TEXS only supports Texture2D arrays. return texture_info >= 7 && texture_info <= 9; } - bool HasTwoDestinations() const { + [[nodiscard]] bool HasTwoDestinations() const { return gpr28.Value() != Register::ZeroIndex; } - bool IsComponentEnabled(std::size_t component) const { + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { static constexpr std::array<std::array<u32, 8>, 4> mask_lut{{ {}, {0x1, 0x2, 0x4, 0x8, 0x3, 0x9, 0xa, 0xc}, @@ -1506,7 +1510,7 @@ union Instruction { BitField<54, 1, u64> cl; BitField<55, 1, u64> process_mode; - TextureProcessMode GetTextureProcessMode() const { + [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { return process_mode == 0 ? TextureProcessMode::LZ : TextureProcessMode::LL; } } tld; @@ -1516,7 +1520,7 @@ union Instruction { BitField<53, 4, u64> texture_info; BitField<59, 1, u64> fp32_flag; - TextureType GetTextureType() const { + [[nodiscard]] TextureType GetTextureType() const { // The TLDS instruction has a weird encoding for the texture type. if (texture_info <= 1) { return TextureType::Texture1D; @@ -1535,13 +1539,14 @@ union Instruction { return TextureType::Texture1D; } - TextureProcessMode GetTextureProcessMode() const { - if (texture_info == 1 || texture_info == 5 || texture_info == 12) + [[nodiscard]] TextureProcessMode GetTextureProcessMode() const { + if (texture_info == 1 || texture_info == 5 || texture_info == 12) { return TextureProcessMode::LL; + } return TextureProcessMode::LZ; } - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::AOFFI: return texture_info == 12 || texture_info == 4; @@ -1555,7 +1560,7 @@ union Instruction { return false; } - bool IsArrayTexture() const { + [[nodiscard]] bool IsArrayTexture() const { // TEXS only supports Texture2D arrays. return texture_info == 8; } @@ -1567,7 +1572,7 @@ union Instruction { BitField<35, 1, u64> aoffi_flag; BitField<49, 1, u64> nodep_flag; - bool UsesMiscMode(TextureMiscMode mode) const { + [[nodiscard]] bool UsesMiscMode(TextureMiscMode mode) const { switch (mode) { case TextureMiscMode::AOFFI: return aoffi_flag != 0; @@ -1591,7 +1596,7 @@ union Instruction { BitField<20, 3, StoreType> store_data_layout; BitField<20, 4, u64> component_mask_selector; - bool IsComponentEnabled(std::size_t component) const { + [[nodiscard]] bool IsComponentEnabled(std::size_t component) const { ASSERT(mode == SurfaceDataMode::P); constexpr u8 R = 0b0001; constexpr u8 G = 0b0010; @@ -1604,7 +1609,7 @@ union Instruction { return std::bitset<4>{mask.at(component_mask_selector)}.test(component); } - StoreType GetStoreDataLayout() const { + [[nodiscard]] StoreType GetStoreDataLayout() const { ASSERT(mode == SurfaceDataMode::D_BA); return store_data_layout; } @@ -1622,14 +1627,15 @@ union Instruction { BitField<20, 24, u64> target; BitField<5, 1, u64> constant_buffer; - s32 GetBranchTarget() const { + [[nodiscard]] s32 GetBranchTarget() const { // Sign extend the branch target offset - u32 mask = 1U << (24 - 1); - u32 value = static_cast<u32>(target); + const auto mask = 1U << (24 - 1); + const auto target_value = static_cast<u32>(target); + constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction)); + // The branch offset is relative to the next instruction and is stored in bytes, so // divide it by the size of an instruction and add 1 to it. - return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) + - 1; + return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1; } } bra; @@ -1637,14 +1643,15 @@ union Instruction { BitField<20, 24, u64> target; BitField<5, 1, u64> constant_buffer; - s32 GetBranchExtend() const { + [[nodiscard]] s32 GetBranchExtend() const { // Sign extend the branch target offset - u32 mask = 1U << (24 - 1); - u32 value = static_cast<u32>(target); + const auto mask = 1U << (24 - 1); + const auto target_value = static_cast<u32>(target); + constexpr auto instruction_size = static_cast<s32>(sizeof(Instruction)); + // The branch offset is relative to the next instruction and is stored in bytes, so // divide it by the size of an instruction and add 1 to it. - return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) + - 1; + return static_cast<s32>((target_value ^ mask) - mask) / instruction_size + 1; } } brx; @@ -1697,7 +1704,7 @@ union Instruction { BitField<50, 1, u64> is_op_b_register; BitField<51, 3, VmnmxOperation> operation; - VmnmxType SourceFormatA() const { + [[nodiscard]] VmnmxType SourceFormatA() const { switch (src_format_a) { case 0b11: return VmnmxType::Bits32; @@ -1708,7 +1715,7 @@ union Instruction { } } - VmnmxType SourceFormatB() const { + [[nodiscard]] VmnmxType SourceFormatB() const { switch (src_format_b) { case 0b11: return VmnmxType::Bits32; @@ -1739,7 +1746,7 @@ union Instruction { BitField<20, 14, u64> shifted_offset; BitField<34, 5, u64> index; - u64 GetOffset() const { + [[nodiscard]] u64 GetOffset() const { return shifted_offset * 4; } } cbuf34; @@ -1748,7 +1755,7 @@ union Instruction { BitField<20, 16, s64> offset; BitField<36, 5, u64> index; - s64 GetOffset() const { + [[nodiscard]] s64 GetOffset() const { return offset; } } cbuf36; @@ -1997,29 +2004,29 @@ public: /// Returns whether an opcode has an execution predicate field or not (ie, whether it can be /// conditionally executed). - static bool IsPredicatedInstruction(Id opcode) { + [[nodiscard]] static bool IsPredicatedInstruction(Id opcode) { // TODO(Subv): Add the rest of unpredicated instructions. return opcode != Id::SSY && opcode != Id::PBK; } class Matcher { public: - constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type) - : name{name}, mask{mask}, expected{expected}, id{id}, type{type} {} + constexpr Matcher(const char* const name_, u16 mask_, u16 expected_, Id id_, Type type_) + : name{name_}, mask{mask_}, expected{expected_}, id{id_}, type{type_} {} - constexpr const char* GetName() const { + [[nodiscard]] constexpr const char* GetName() const { return name; } - constexpr u16 GetMask() const { + [[nodiscard]] constexpr u16 GetMask() const { return mask; } - constexpr Id GetId() const { + [[nodiscard]] constexpr Id GetId() const { return id; } - constexpr Type GetType() const { + [[nodiscard]] constexpr Type GetType() const { return type; } @@ -2028,7 +2035,7 @@ public: * @param instruction The instruction to test * @returns true if the given instruction matches. */ - constexpr bool Matches(u16 instruction) const { + [[nodiscard]] constexpr bool Matches(u16 instruction) const { return (instruction & mask) == expected; } @@ -2040,7 +2047,8 @@ public: Type type; }; - static std::optional<std::reference_wrapper<const Matcher>> Decode(Instruction instr) { + using DecodeResult = std::optional<std::reference_wrapper<const Matcher>>; + [[nodiscard]] static DecodeResult Decode(Instruction instr) { static const auto table{GetDecodeTable()}; const auto matches_instruction = [instr](const auto& matcher) { @@ -2062,7 +2070,7 @@ private: * A '0' in a bitstring indicates that a zero must be present at that bit position. * A '1' in a bitstring indicates that a one must be present at that bit position. */ - static constexpr auto GetMaskAndExpect(const char* const bitstring) { + [[nodiscard]] static constexpr auto GetMaskAndExpect(const char* const bitstring) { u16 mask = 0, expect = 0; for (std::size_t i = 0; i < opcode_bitsize; i++) { const std::size_t bit_position = opcode_bitsize - i - 1; @@ -2084,14 +2092,14 @@ private: public: /// Creates a matcher that can match and parse instructions based on bitstring. - static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type, - const char* const name) { + [[nodiscard]] static constexpr auto GetMatcher(const char* const bitstring, Id op, + Type type, const char* const name) { const auto [mask, expected] = GetMaskAndExpect(bitstring); return Matcher(name, mask, expected, op, type); } }; - static std::vector<Matcher> GetDecodeTable() { + [[nodiscard]] static std::vector<Matcher> GetDecodeTable() { std::vector<Matcher> table = { #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) INST("111000110011----", Id::KIL, Type::Flow, "KIL"), diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index ebd149c3a..e91f52938 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -95,22 +95,29 @@ void GPU::WaitFence(u32 syncpoint_id, u32 value) { if (!is_async) { return; } + if (syncpoint_id == UINT32_MAX) { + // TODO: Research what this does. + LOG_ERROR(HW_GPU, "Waiting for syncpoint -1 not implemented"); + return; + } MICROPROFILE_SCOPE(GPU_wait); std::unique_lock lock{sync_mutex}; - sync_cv.wait(lock, [=, this] { return syncpoints[syncpoint_id].load() >= value; }); + sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; }); } void GPU::IncrementSyncPoint(const u32 syncpoint_id) { - syncpoints[syncpoint_id]++; + auto& syncpoint = syncpoints.at(syncpoint_id); + syncpoint++; std::lock_guard lock{sync_mutex}; sync_cv.notify_all(); - if (!syncpt_interrupts[syncpoint_id].empty()) { - u32 value = syncpoints[syncpoint_id].load(); - auto it = syncpt_interrupts[syncpoint_id].begin(); - while (it != syncpt_interrupts[syncpoint_id].end()) { + auto& interrupt = syncpt_interrupts.at(syncpoint_id); + if (!interrupt.empty()) { + u32 value = syncpoint.load(); + auto it = interrupt.begin(); + while (it != interrupt.end()) { if (value >= *it) { TriggerCpuInterrupt(syncpoint_id, *it); - it = syncpt_interrupts[syncpoint_id].erase(it); + it = interrupt.erase(it); continue; } it++; @@ -119,22 +126,22 @@ void GPU::IncrementSyncPoint(const u32 syncpoint_id) { } u32 GPU::GetSyncpointValue(const u32 syncpoint_id) const { - return syncpoints[syncpoint_id].load(); + return syncpoints.at(syncpoint_id).load(); } void GPU::RegisterSyncptInterrupt(const u32 syncpoint_id, const u32 value) { - auto& interrupt = syncpt_interrupts[syncpoint_id]; + auto& interrupt = syncpt_interrupts.at(syncpoint_id); bool contains = std::any_of(interrupt.begin(), interrupt.end(), [value](u32 in_value) { return in_value == value; }); if (contains) { return; } - syncpt_interrupts[syncpoint_id].emplace_back(value); + interrupt.emplace_back(value); } bool GPU::CancelSyncptInterrupt(const u32 syncpoint_id, const u32 value) { std::lock_guard lock{sync_mutex}; - auto& interrupt = syncpt_interrupts[syncpoint_id]; + auto& interrupt = syncpt_interrupts.at(syncpoint_id); const auto iter = std::find_if(interrupt.begin(), interrupt.end(), [value](u32 interrupt_value) { return value == interrupt_value; }); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 36bf92808..cfddbde5d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1156,7 +1156,7 @@ void RasterizerOpenGL::SyncViewport() { flags[Dirty::ClipControl] = false; bool flip_y = false; - if (regs.viewport_transform[0].scale_y < 0.0) { + if (regs.viewport_transform[0].scale_y < 0.0f) { flip_y = !flip_y; } if (regs.screen_y_control.y_negate != 0) { @@ -1579,10 +1579,6 @@ void RasterizerOpenGL::SyncAlphaTest() { flags[Dirty::AlphaTest] = false; const auto& regs = maxwell3d.regs; - if (regs.alpha_test_enabled && regs.rt_control.count > 1) { - LOG_WARNING(Render_OpenGL, "Alpha testing with more than one render target is not tested"); - } - if (regs.alpha_test_enabled) { glEnable(GL_ALPHA_TEST); glAlphaFunc(MaxwellToGL::ComparisonOp(regs.alpha_test_func), regs.alpha_test_ref); diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 2ccca1993..c869bb0e2 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -151,8 +151,8 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { rasterizer->TickFrame(); - render_window.PollEvents(); context->SwapBuffers(); + render_window.OnFrameDisplayed(); } void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index da5c550ea..fffae528e 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp @@ -8,6 +8,7 @@ #include <boost/functional/hash.hpp> +#include "common/bit_cast.h" #include "common/cityhash.h" #include "common/common_types.h" #include "video_core/renderer_vulkan/fixed_pipeline_state.h" @@ -60,7 +61,13 @@ void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_sta rasterize_enable.Assign(regs.rasterize_enable != 0 ? 1 : 0); topology.Assign(regs.draw.topology); - std::memcpy(&point_size, ®s.point_size, sizeof(point_size)); // TODO: C++20 std::bit_cast + alpha_raw = 0; + const auto test_func = + regs.alpha_test_enabled == 1 ? regs.alpha_test_func : Maxwell::ComparisonOp::Always; + alpha_test_func.Assign(PackComparisonOp(test_func)); + alpha_test_ref = Common::BitCast<u32>(regs.alpha_test_ref); + + point_size = Common::BitCast<u32>(regs.point_size); for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { binding_divisors[index] = diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 2c18eeaae..42480e8d0 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h @@ -187,6 +187,13 @@ struct FixedPipelineState { BitField<23, 1, u32> rasterize_enable; BitField<24, 4, Maxwell::PrimitiveTopology> topology; }; + + u32 alpha_test_ref; ///< Alpha test reference value + union { + u32 alpha_raw; + BitField<0, 3, u32> alpha_test_func; + }; + u32 point_size; std::array<u32, Maxwell::NumVertexArrays> binding_divisors; std::array<VertexAttribute, Maxwell::NumVertexAttributes> attributes; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index f2610868e..a2173edd2 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -252,8 +252,6 @@ RendererVulkan::~RendererVulkan() { } void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { - render_window.PollEvents(); - if (!framebuffer) { return; } @@ -283,7 +281,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { rasterizer->TickFrame(); } - render_window.PollEvents(); + render_window.OnFrameDisplayed(); } bool RendererVulkan::Init() { diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index dedc9c466..f9efe526d 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -7,6 +7,7 @@ #include <memory> #include <vector> +#include "common/bit_cast.h" #include "common/microprofile.h" #include "core/core.h" #include "core/memory.h" @@ -344,6 +345,11 @@ VKPipelineCache::DecompileShaders(const FixedPipelineState& fixed_state) { } specialization.ndc_minus_one_to_one = fixed_state.ndc_minus_one_to_one; + // Alpha test + specialization.alpha_test_func = + FixedPipelineState::UnpackComparisonOp(fixed_state.alpha_test_func.Value()); + specialization.alpha_test_ref = Common::BitCast<float>(fixed_state.alpha_test_ref); + SPIRVProgram program; std::vector<VkDescriptorSetLayoutBinding> bindings; diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index a20452b87..1c52f40bb 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -2075,6 +2075,45 @@ private: return {}; } + Id MaxwellToSpirvComparison(Maxwell::ComparisonOp compare_op, Id operand_1, Id operand_2) { + using Compare = Maxwell::ComparisonOp; + switch (compare_op) { + case Compare::NeverOld: + return v_false; // Never let the test pass + case Compare::LessOld: + return OpFOrdLessThan(t_bool, operand_1, operand_2); + case Compare::EqualOld: + return OpFOrdEqual(t_bool, operand_1, operand_2); + case Compare::LessEqualOld: + return OpFOrdLessThanEqual(t_bool, operand_1, operand_2); + case Compare::GreaterOld: + return OpFOrdGreaterThan(t_bool, operand_1, operand_2); + case Compare::NotEqualOld: + return OpFOrdNotEqual(t_bool, operand_1, operand_2); + case Compare::GreaterEqualOld: + return OpFOrdGreaterThanEqual(t_bool, operand_1, operand_2); + default: + UNREACHABLE(); + } + } + + void AlphaTest(Id pointer) { + if (specialization.alpha_test_func == Maxwell::ComparisonOp::AlwaysOld) { + return; + } + const Id true_label = OpLabel(); + const Id discard_label = OpLabel(); + const Id alpha_reference = Constant(t_float, specialization.alpha_test_ref); + const Id alpha_value = OpLoad(t_float, pointer); + const Id condition = + MaxwellToSpirvComparison(specialization.alpha_test_func, alpha_value, alpha_reference); + + OpBranchConditional(condition, true_label, discard_label); + AddLabel(discard_label); + OpKill(); + AddLabel(true_label); + } + void PreExit() { if (stage == ShaderType::Vertex && specialization.ndc_minus_one_to_one) { const u32 position_index = out_indices.position.value(); @@ -2097,8 +2136,6 @@ private: UNIMPLEMENTED_IF_MSG(header.ps.omap.sample_mask != 0, "Sample mask write is unimplemented"); - // TODO(Rodrigo): Alpha testing - // Write the color outputs using the data in the shader registers, disabled // rendertargets/components are skipped in the register assignment. u32 current_reg = 0; @@ -2110,6 +2147,9 @@ private: } const Id pointer = AccessElement(t_out_float, frag_colors[rt], component); OpStore(pointer, SafeGetRegister(current_reg)); + if (rt == 0 && component == 3) { + AlphaTest(pointer); + } ++current_reg; } } diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.h b/src/video_core/renderer_vulkan/vk_shader_decompiler.h index 2b0e90396..cd3d0a415 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.h +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.h @@ -95,6 +95,8 @@ struct Specialization final { std::bitset<Maxwell::NumVertexAttributes> enabled_attributes; std::array<Maxwell::VertexAttribute::Type, Maxwell::NumVertexAttributes> attribute_types{}; bool ndc_minus_one_to_one{}; + float alpha_test_ref{}; + Maxwell::ComparisonOp alpha_test_func{}; }; // Old gcc versions don't consider this trivially copyable. // static_assert(std::is_trivially_copyable_v<Specialization>); diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp index 39cc3b869..6920afdf2 100644 --- a/src/video_core/shader/async_shaders.cpp +++ b/src/video_core/shader/async_shaders.cpp @@ -43,8 +43,8 @@ void AsyncShaders::AllocateWorkers() { // Create workers for (std::size_t i = 0; i < num_workers; i++) { context_list.push_back(emu_window.CreateSharedContext()); - worker_threads.push_back( - std::thread(&AsyncShaders::ShaderCompilerThread, this, context_list[i].get())); + worker_threads.emplace_back(&AsyncShaders::ShaderCompilerThread, this, + context_list[i].get()); } } @@ -106,8 +106,7 @@ std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() { std::vector<Result> results; { std::unique_lock lock{completed_mutex}; - results.assign(std::make_move_iterator(finished_work.begin()), - std::make_move_iterator(finished_work.end())); + results = std::move(finished_work); finished_work.clear(); } return results; @@ -116,11 +115,10 @@ std::vector<AsyncShaders::Result> AsyncShaders::GetCompletedWork() { void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, Tegra::Engines::ShaderType shader_type, u64 uid, std::vector<u64> code, std::vector<u64> code_b, - u32 main_offset, - VideoCommon::Shader::CompilerSettings compiler_settings, - const VideoCommon::Shader::Registry& registry, - VAddr cpu_addr) { - WorkerParams params{ + u32 main_offset, CompilerSettings compiler_settings, + const Registry& registry, VAddr cpu_addr) { + std::unique_lock lock(queue_mutex); + pending_queue.push({ .backend = device.UseAssemblyShaders() ? Backend::GLASM : Backend::OpenGL, .device = &device, .shader_type = shader_type, @@ -131,9 +129,7 @@ void AsyncShaders::QueueOpenGLShader(const OpenGL::Device& device, .compiler_settings = compiler_settings, .registry = registry, .cpu_address = cpu_addr, - }; - std::unique_lock lock(queue_mutex); - pending_queue.push(std::move(params)); + }); cv.notify_one(); } @@ -145,7 +141,8 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, std::vector<VkDescriptorSetLayoutBinding> bindings, Vulkan::SPIRVProgram program, Vulkan::GraphicsPipelineCacheKey key) { - WorkerParams params{ + std::unique_lock lock(queue_mutex); + pending_queue.push({ .backend = Backend::Vulkan, .pp_cache = pp_cache, .vk_device = &device, @@ -153,13 +150,10 @@ void AsyncShaders::QueueVulkanShader(Vulkan::VKPipelineCache* pp_cache, .descriptor_pool = &descriptor_pool, .update_descriptor_queue = &update_descriptor_queue, .renderpass_cache = &renderpass_cache, - .bindings = bindings, - .program = program, + .bindings = std::move(bindings), + .program = std::move(program), .key = key, - }; - - std::unique_lock lock(queue_mutex); - pending_queue.push(std::move(params)); + }); cv.notify_one(); } diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 618d309d2..1ed4212ee 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp @@ -212,10 +212,10 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { return 0; case TextureFormat::R8G24: if (component == 0) { - return 8; + return 24; } if (component == 1) { - return 24; + return 8; } return 0; case TextureFormat::R8G8: diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index 8ecfec770..6944478f3 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -72,40 +72,6 @@ bool IsControllerCompatible(Settings::ControllerType controller_type, } } -/// Maps the controller type combobox index to Controller Type enum -constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { - switch (index) { - case 0: - default: - return Settings::ControllerType::ProController; - case 1: - return Settings::ControllerType::DualJoyconDetached; - case 2: - return Settings::ControllerType::LeftJoycon; - case 3: - return Settings::ControllerType::RightJoycon; - case 4: - return Settings::ControllerType::Handheld; - } -} - -/// Maps the Controller Type enum to controller type combobox index -constexpr int GetIndexFromControllerType(Settings::ControllerType type) { - switch (type) { - case Settings::ControllerType::ProController: - default: - return 0; - case Settings::ControllerType::DualJoyconDetached: - return 1; - case Settings::ControllerType::LeftJoycon: - return 2; - case Settings::ControllerType::RightJoycon: - return 3; - case Settings::ControllerType::Handheld: - return 4; - } -} - } // namespace QtControllerSelectorDialog::QtControllerSelectorDialog( @@ -184,6 +150,11 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( // This avoids unintentionally changing the states of elements while loading them in. SetSupportedControllers(); DisableUnsupportedPlayers(); + + for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { + SetEmulatedControllers(player_index); + } + LoadConfiguration(); for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { @@ -223,8 +194,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( if (i == 0) { connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged), - [this](int index) { - UpdateDockedState(GetControllerTypeFromIndex(index) == + [this, i](int index) { + UpdateDockedState(GetControllerTypeFromIndex(index, i) == Settings::ControllerType::Handheld); }); } @@ -281,8 +252,8 @@ void QtControllerSelectorDialog::LoadConfiguration() { (index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected); player_groupboxes[index]->setChecked(connected); connected_controller_checkboxes[index]->setChecked(connected); - emulated_controllers[index]->setCurrentIndex( - GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type)); + emulated_controllers[index]->setCurrentIndex(GetIndexFromControllerType( + Settings::values.players.GetValue()[index].controller_type, index)); } UpdateDockedState(Settings::values.players.GetValue()[HANDHELD_INDEX].connected); @@ -338,7 +309,7 @@ bool QtControllerSelectorDialog::CheckIfParametersMet() { } const auto compatible = IsControllerCompatible( - GetControllerTypeFromIndex(emulated_controllers[index]->currentIndex()), + GetControllerTypeFromIndex(emulated_controllers[index]->currentIndex(), index), parameters); // If any controller is found to be incompatible, return false early. @@ -422,6 +393,63 @@ void QtControllerSelectorDialog::SetSupportedControllers() { } } +void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index) { + auto& pairs = index_controller_type_pairs[player_index]; + + pairs.clear(); + emulated_controllers[player_index]->clear(); + + pairs.emplace_back(emulated_controllers[player_index]->count(), + Settings::ControllerType::ProController); + emulated_controllers[player_index]->addItem(tr("Pro Controller")); + + pairs.emplace_back(emulated_controllers[player_index]->count(), + Settings::ControllerType::DualJoyconDetached); + emulated_controllers[player_index]->addItem(tr("Dual Joycons")); + + pairs.emplace_back(emulated_controllers[player_index]->count(), + Settings::ControllerType::LeftJoycon); + emulated_controllers[player_index]->addItem(tr("Left Joycon")); + + pairs.emplace_back(emulated_controllers[player_index]->count(), + Settings::ControllerType::RightJoycon); + emulated_controllers[player_index]->addItem(tr("Right Joycon")); + + if (player_index == 0) { + pairs.emplace_back(emulated_controllers[player_index]->count(), + Settings::ControllerType::Handheld); + emulated_controllers[player_index]->addItem(tr("Handheld")); + } +} + +Settings::ControllerType QtControllerSelectorDialog::GetControllerTypeFromIndex( + int index, std::size_t player_index) const { + const auto& pairs = index_controller_type_pairs[player_index]; + + const auto it = std::find_if(pairs.begin(), pairs.end(), + [index](const auto& pair) { return pair.first == index; }); + + if (it == pairs.end()) { + return Settings::ControllerType::ProController; + } + + return it->second; +} + +int QtControllerSelectorDialog::GetIndexFromControllerType(Settings::ControllerType type, + std::size_t player_index) const { + const auto& pairs = index_controller_type_pairs[player_index]; + + const auto it = std::find_if(pairs.begin(), pairs.end(), + [type](const auto& pair) { return pair.second == type; }); + + if (it == pairs.end()) { + return 0; + } + + return it->first; +} + void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) { if (!player_groupboxes[player_index]->isChecked()) { connected_controller_icons[player_index]->setStyleSheet(QString{}); @@ -430,7 +458,8 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) } const QString stylesheet = [this, player_index] { - switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex())) { + switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), + player_index)) { case Settings::ControllerType::ProController: return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); case Settings::ControllerType::DualJoyconDetached: @@ -446,6 +475,12 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) } }(); + if (stylesheet.isEmpty()) { + connected_controller_icons[player_index]->setStyleSheet(QString{}); + player_labels[player_index]->show(); + return; + } + const QString theme = [] { if (QIcon::themeName().contains(QStringLiteral("dark"))) { return QStringLiteral("_dark"); @@ -463,8 +498,8 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { auto& player = Settings::values.players.GetValue()[player_index]; - const auto controller_type = - GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); + const auto controller_type = GetControllerTypeFromIndex( + emulated_controllers[player_index]->currentIndex(), player_index); const auto player_connected = player_groupboxes[player_index]->isChecked() && controller_type != Settings::ControllerType::Handheld; @@ -507,8 +542,8 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { if (!player_groupboxes[player_index]->isChecked() || - GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()) == - Settings::ControllerType::Handheld) { + GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), + player_index) == Settings::ControllerType::Handheld) { led_patterns_boxes[player_index][0]->setChecked(false); led_patterns_boxes[player_index][1]->setChecked(false); led_patterns_boxes[player_index][2]->setChecked(false); diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 4344e1dd0..7a421d856 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h @@ -22,6 +22,10 @@ namespace InputCommon { class InputSubsystem; } +namespace Settings { +enum class ControllerType; +} + namespace Ui { class QtControllerSelectorDialog; } @@ -57,6 +61,15 @@ private: // Sets the controller icons for "Supported Controller Types". void SetSupportedControllers(); + // Sets the emulated controllers per player. + void SetEmulatedControllers(std::size_t player_index); + + // Gets the Controller Type for a given controller combobox index per player. + Settings::ControllerType GetControllerTypeFromIndex(int index, std::size_t player_index) const; + + // Gets the controller combobox index for a given Controller Type per player. + int GetIndexFromControllerType(Settings::ControllerType type, std::size_t player_index) const; + // Updates the controller icons per player. void UpdateControllerIcon(std::size_t player_index); @@ -114,6 +127,10 @@ private: // Comboboxes with a list of emulated controllers per player. std::array<QComboBox*, NUM_PLAYERS> emulated_controllers; + /// Pairs of emulated controller index and Controller Type enum per player. + std::array<std::vector<std::pair<int, Settings::ControllerType>>, NUM_PLAYERS> + index_controller_type_pairs; + // Labels representing the number of connected controllers // above the "Connected Controllers" checkboxes. std::array<QLabel*, NUM_PLAYERS> connected_controller_labels; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index d239ffbbd..489104d5f 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -302,13 +302,19 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_, this->setMouseTracking(true); connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &GMainWindow::OnLoadComplete); + connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &GMainWindow::OnExecuteProgram, + Qt::QueuedConnection); +} + +void GRenderWindow::ExecuteProgram(std::size_t program_index) { + emit ExecuteProgramSignal(program_index); } GRenderWindow::~GRenderWindow() { input_subsystem->Shutdown(); } -void GRenderWindow::PollEvents() { +void GRenderWindow::OnFrameDisplayed() { if (!first_frame) { first_frame = true; emit FirstFrameDisplayed(); diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index ca35cf831..a6d788d40 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -131,7 +131,7 @@ public: ~GRenderWindow() override; // EmuWindow implementation. - void PollEvents() override; + void OnFrameDisplayed() override; bool IsShown() const override; std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; @@ -166,6 +166,12 @@ public: std::pair<u32, u32> ScaleTouch(const QPointF& pos) const; + /** + * Instructs the window to re-launch the application using the specified program_index. + * @param program_index Specifies the index within the application of the program to launch. + */ + void ExecuteProgram(std::size_t program_index); + public slots: void OnEmulationStarting(EmuThread* emu_thread); void OnEmulationStopping(); @@ -175,6 +181,7 @@ signals: /// Emitted when the window is closed void Closed(); void FirstFrameDisplayed(); + void ExecuteProgramSignal(std::size_t program_index); private: void TouchBeginEvent(const QTouchEvent* event); diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 6fa842cd5..8be9e93c3 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -7,6 +7,7 @@ #include <QSettings> #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/hid/controllers/npad.h" #include "input_common/main.h" @@ -649,6 +650,8 @@ void Config::ReadDebuggingValues() { Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), false).toBool(); Settings::values.disable_macro_jit = ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); + Settings::values.extended_logging = + ReadSetting(QStringLiteral("extended_logging"), false).toBool(); qt_config->endGroup(); } @@ -1596,7 +1599,7 @@ void Config::Reload() { Settings::Sanitize(); // To apply default value changes SaveValues(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void Config::Save() { diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 2bfe2c306..027099ab7 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -41,6 +41,7 @@ void ConfigureDebug::SetConfiguration() { ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit); + ui->extended_logging->setChecked(Settings::values.extended_logging); } void ConfigureDebug::ApplyConfiguration() { @@ -53,6 +54,7 @@ void ConfigureDebug::ApplyConfiguration() { Settings::values.quest_flag = ui->quest_flag->isChecked(); Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); + Settings::values.extended_logging = ui->extended_logging->isChecked(); Debugger::ToggleConsole(); Log::Filter filter; filter.ParseFilterString(Settings::values.log_filter); diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 9d6feb9f7..6f94fe304 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -90,7 +90,7 @@ <item> <widget class="QCheckBox" name="toggle_console"> <property name="text"> - <string>Show Log Console (Windows Only)</string> + <string>Show Log in Console</string> </property> </widget> </item> @@ -103,6 +103,34 @@ </item> </layout> </item> + <item> + <widget class="QCheckBox" name="extended_logging"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="toolTip"> + <string>When checked, the max size of the log increases from 100 MB to 1 GB</string> + </property> + <property name="text"> + <string>Enable Extended Logging</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="font"> + <font> + <italic>true</italic> + </font> + </property> + <property name="text"> + <string>This will be reset automatically when yuzu closes.</string> + </property> + <property name="indent"> + <number>20</number> + </property> + </widget> + </item> </layout> </widget> </item> @@ -115,7 +143,7 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="label_4"> <property name="text"> <string>Arguments String</string> </property> @@ -140,8 +168,8 @@ <property name="enabled"> <bool>true</bool> </property> - <property name="whatsThis"> - <string>When checked, the graphics API enters in a slower debugging mode</string> + <property name="toolTip"> + <string>When checked, the graphics API enters a slower debugging mode</string> </property> <property name="text"> <string>Enable Graphics Debugging</string> @@ -153,8 +181,8 @@ <property name="enabled"> <bool>true</bool> </property> - <property name="whatsThis"> - <string>When checked, it disables the macro Just In Time compiler. Enabled this makes games run slower</string> + <property name="toolTip"> + <string>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</string> </property> <property name="text"> <string>Disable Macro JIT</string> @@ -169,7 +197,7 @@ <property name="title"> <string>Dump</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_6"> + <layout class="QVBoxLayout" name="verticalLayout_7"> <item> <widget class="QCheckBox" name="reporting_services"> <property name="text"> @@ -178,7 +206,7 @@ </widget> </item> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_5"> <property name="font"> <font> <italic>true</italic> @@ -200,7 +228,7 @@ <property name="title"> <string>Advanced</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_7"> + <layout class="QVBoxLayout" name="verticalLayout_8"> <item> <widget class="QCheckBox" name="quest_flag"> <property name="text"> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 5041e0bf8..b33f8437a 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -5,6 +5,7 @@ #include <QHash> #include <QListWidgetItem> #include <QSignalBlocker> +#include "core/core.h" #include "core/settings.h" #include "ui_configure.h" #include "yuzu/configuration/config.h" @@ -54,7 +55,7 @@ void ConfigureDialog::ApplyConfiguration() { ui->debugTab->ApplyConfiguration(); ui->webTab->ApplyConfiguration(); ui->serviceTab->ApplyConfiguration(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); Settings::LogSettings(); } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 87440a013..f9915fb7a 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -28,6 +28,8 @@ #include "yuzu/configuration/input_profiles.h" #include "yuzu/util/limitable_input_dialog.h" +using namespace Service::HID; + const std::array<std::string, ConfigureInputPlayer::ANALOG_SUB_BUTTONS_NUM> ConfigureInputPlayer::analog_sub_buttons{{ "up", @@ -48,48 +50,12 @@ void UpdateController(Settings::ControllerType controller_type, std::size_t npad } Service::SM::ServiceManager& sm = system.ServiceManager(); - auto& npad = - sm.GetService<Service::HID::Hid>("hid") - ->GetAppletResource() - ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); + auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>( + HidController::NPad); npad.UpdateControllerAt(npad.MapSettingsTypeToNPad(controller_type), npad_index, connected); } -/// Maps the controller type combobox index to Controller Type enum -constexpr Settings::ControllerType GetControllerTypeFromIndex(int index) { - switch (index) { - case 0: - default: - return Settings::ControllerType::ProController; - case 1: - return Settings::ControllerType::DualJoyconDetached; - case 2: - return Settings::ControllerType::LeftJoycon; - case 3: - return Settings::ControllerType::RightJoycon; - case 4: - return Settings::ControllerType::Handheld; - } -} - -/// Maps the Controller Type enum to controller type combobox index -constexpr int GetIndexFromControllerType(Settings::ControllerType type) { - switch (type) { - case Settings::ControllerType::ProController: - default: - return 0; - case Settings::ControllerType::DualJoyconDetached: - return 1; - case Settings::ControllerType::LeftJoycon: - return 2; - case Settings::ControllerType::RightJoycon: - return 3; - case Settings::ControllerType::Handheld: - return 4; - } -} - QString GetKeyName(int key_code) { switch (key_code) { case Qt::LeftButton: @@ -482,18 +448,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i connect(ui->groupConnectedController, &QGroupBox::toggled, [this](bool checked) { emit Connected(checked); }); - // Set up controller type. Only Player 1 can choose Handheld. - ui->comboControllerType->clear(); - - QStringList controller_types = { - tr("Pro Controller"), - tr("Dual Joycons"), - tr("Left Joycon"), - tr("Right Joycon"), - }; - if (player_index == 0) { - controller_types.append(tr("Handheld")); connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) { emit HandheldStateChanged(GetControllerTypeFromIndex(index) == @@ -509,12 +464,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (debug) { ui->buttonScreenshot->setEnabled(false); ui->buttonHome->setEnabled(false); - QStringList debug_controller_types = { - tr("Pro Controller"), - }; - ui->comboControllerType->addItems(debug_controller_types); + ui->comboControllerType->addItem(tr("Pro Controller")); } else { - ui->comboControllerType->addItems(controller_types); + SetConnectableControllers(); } UpdateControllerIcon(); @@ -724,7 +676,7 @@ void ConfigureInputPlayer::LoadConfiguration() { return; } - ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); + ui->comboControllerType->setCurrentIndex(GetIndexFromControllerType(player.controller_type)); ui->groupConnectedController->setChecked( player.connected || (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected)); @@ -899,6 +851,82 @@ void ConfigureInputPlayer::UpdateUI() { } } +void ConfigureInputPlayer::SetConnectableControllers() { + const auto add_controllers = [this](bool enable_all, + Controller_NPad::NpadStyleSet npad_style_set = {}) { + index_controller_type_pairs.clear(); + ui->comboControllerType->clear(); + + if (enable_all || npad_style_set.pro_controller == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Settings::ControllerType::ProController); + ui->comboControllerType->addItem(tr("Pro Controller")); + } + + if (enable_all || npad_style_set.joycon_dual == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Settings::ControllerType::DualJoyconDetached); + ui->comboControllerType->addItem(tr("Dual Joycons")); + } + + if (enable_all || npad_style_set.joycon_left == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Settings::ControllerType::LeftJoycon); + ui->comboControllerType->addItem(tr("Left Joycon")); + } + + if (enable_all || npad_style_set.joycon_right == 1) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Settings::ControllerType::RightJoycon); + ui->comboControllerType->addItem(tr("Right Joycon")); + } + + if (player_index == 0 && (enable_all || npad_style_set.handheld == 1)) { + index_controller_type_pairs.emplace_back(ui->comboControllerType->count(), + Settings::ControllerType::Handheld); + ui->comboControllerType->addItem(tr("Handheld")); + } + }; + + Core::System& system{Core::System::GetInstance()}; + + if (!system.IsPoweredOn()) { + add_controllers(true); + return; + } + + Service::SM::ServiceManager& sm = system.ServiceManager(); + + auto& npad = sm.GetService<Hid>("hid")->GetAppletResource()->GetController<Controller_NPad>( + HidController::NPad); + + add_controllers(false, npad.GetSupportedStyleSet()); +} + +Settings::ControllerType ConfigureInputPlayer::GetControllerTypeFromIndex(int index) const { + const auto it = + std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), + [index](const auto& pair) { return pair.first == index; }); + + if (it == index_controller_type_pairs.end()) { + return Settings::ControllerType::ProController; + } + + return it->second; +} + +int ConfigureInputPlayer::GetIndexFromControllerType(Settings::ControllerType type) const { + const auto it = + std::find_if(index_controller_type_pairs.begin(), index_controller_type_pairs.end(), + [type](const auto& pair) { return pair.second == type; }); + + if (it == index_controller_type_pairs.end()) { + return -1; + } + + return it->first; +} + void ConfigureInputPlayer::UpdateInputDevices() { input_devices = input_subsystem->GetInputDevices(); ui->comboDevices->clear(); @@ -1202,7 +1230,7 @@ void ConfigureInputPlayer::CreateProfile() { return; } - if (!profiles->IsProfileNameValid(profile_name.toStdString())) { + if (!InputProfiles::IsProfileNameValid(profile_name.toStdString())) { QMessageBox::critical(this, tr("Create Input Profile"), tr("The given profile name is not valid!")); return; diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 23cf6f958..9c30879a2 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -9,6 +9,7 @@ #include <memory> #include <optional> #include <string> +#include <vector> #include <QWidget> @@ -112,6 +113,15 @@ private: /// Update UI to reflect current configuration. void UpdateUI(); + /// Sets the available controllers. + void SetConnectableControllers(); + + /// Gets the Controller Type for a given controller combobox index. + Settings::ControllerType GetControllerTypeFromIndex(int index) const; + + /// Gets the controller combobox index for a given Controller Type. + int GetIndexFromControllerType(Settings::ControllerType type) const; + /// Update the available input devices. void UpdateInputDevices(); @@ -151,6 +161,9 @@ private: std::unique_ptr<QTimer> timeout_timer; std::unique_ptr<QTimer> poll_timer; + /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum. + std::vector<std::pair<int, Settings::ControllerType>> index_controller_type_pairs; + static constexpr int PLAYER_COUNT = 8; std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox; diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 81464dd37..f598513df 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -16,6 +16,7 @@ #include "common/common_paths.h" #include "common/file_util.h" +#include "core/core.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/xts_archive.h" @@ -56,7 +57,7 @@ void ConfigurePerGame::ApplyConfiguration() { ui->graphicsAdvancedTab->ApplyConfiguration(); ui->audioTab->ApplyConfiguration(); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); Settings::LogSettings(); game_config->Save(); @@ -89,9 +90,11 @@ void ConfigurePerGame::LoadConfiguration() { ui->display_title_id->setText( QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); - FileSys::PatchManager pm{title_id}; + auto& system = Core::System::GetInstance(); + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; const auto control = pm.GetControlMetadata(); - const auto loader = Loader::GetLoader(file); + const auto loader = Loader::GetLoader(system, file); if (control.first != nullptr) { ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp index 793fd8975..cdeeec01c 100644 --- a/src/yuzu/configuration/configure_per_game_addons.cpp +++ b/src/yuzu/configuration/configure_per_game_addons.cpp @@ -112,8 +112,10 @@ void ConfigurePerGameAddons::LoadConfiguration() { return; } - FileSys::PatchManager pm{title_id}; - const auto loader = Loader::GetLoader(file); + auto& system = Core::System::GetInstance(); + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; + const auto loader = Loader::GetLoader(system, file); FileSys::VirtualFile update_raw; loader->ReadUpdateRaw(update_raw); diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 6334c4c50..13d9a4757 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -180,7 +180,7 @@ void ConfigureProfileManager::ApplyConfiguration() { return; } - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void ConfigureProfileManager::SelectUser(const QModelIndex& index) { diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 59a58d92c..6cf2032da 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -105,16 +105,18 @@ void ConfigureSystem::SetConfiguration() { void ConfigureSystem::ReadSystemSettings() {} void ConfigureSystem::ApplyConfiguration() { - // Allow setting custom RTC even if system is powered on, to allow in-game time to be fast - // forwared + auto& system = Core::System::GetInstance(); + + // Allow setting custom RTC even if system is powered on, + // to allow in-game time to be fast forwarded if (Settings::values.custom_rtc.UsingGlobal()) { if (ui->custom_rtc_checkbox->isChecked()) { Settings::values.custom_rtc.SetValue( std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); - if (Core::System::GetInstance().IsPoweredOn()) { + if (system.IsPoweredOn()) { const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() + Service::Time::TimeManager::GetExternalTimeZoneOffset()}; - Core::System::GetInstance().GetTimeManager().UpdateLocalSystemClockTime(posix_time); + system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); } } else { Settings::values.custom_rtc.SetValue(std::nullopt); @@ -197,7 +199,7 @@ void ConfigureSystem::ApplyConfiguration() { } } - Settings::Apply(); + Settings::Apply(system); } void ConfigureSystem::RefreshConsoleID() { diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index dbe3f78c8..aed876008 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -9,6 +9,7 @@ #include <QDirIterator> #include "common/common_types.h" #include "common/file_util.h" +#include "core/core.h" #include "core/settings.h" #include "ui_configure_ui.h" #include "yuzu/configuration/configure_ui.h" @@ -84,7 +85,7 @@ void ConfigureUi::ApplyConfiguration() { UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); Common::FS::GetUserPath(Common::FS::UserPath::ScreenshotsDir, ui->screenshot_path_edit->text().toStdString()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } void ConfigureUi::RequestGameListUpdate() { diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index e0ce45fd9..23643aea2 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -235,12 +235,11 @@ GameListWorker::~GameListWorker() = default; void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { using namespace FileSys; - const auto& cache = - dynamic_cast<ContentProviderUnion&>(Core::System::GetInstance().GetContentProvider()); + auto& system = Core::System::GetInstance(); + const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider()); - std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> installed_games; - installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, - ContentRecordType::Program); + auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, + ContentRecordType::Program); if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) { installed_games = cache.ListEntriesFilterOrigin( @@ -254,23 +253,27 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { } for (const auto& [slot, game] : installed_games) { - if (slot == ContentProviderUnionSlot::FrontendManual) + if (slot == ContentProviderUnionSlot::FrontendManual) { continue; + } const auto file = cache.GetEntryUnparsed(game.title_id, game.type); - std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file); - if (!loader) + std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(system, file); + if (!loader) { continue; + } std::vector<u8> icon; std::string name; u64 program_id = 0; loader->ReadProgramId(program_id); - const PatchManager patch{program_id}; + const PatchManager patch{program_id, system.GetFileSystemController(), + system.GetContentProvider()}; const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control); - if (control != nullptr) + if (control != nullptr) { GetMetadataFromControlNCA(patch, *control, icon, name); + } emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id, compatibility_list, patch), @@ -280,9 +283,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, unsigned int recursion, GameListDir* parent_dir) { - const auto callback = [this, target, recursion, - parent_dir](u64* num_entries_out, const std::string& directory, - const std::string& virtual_name) -> bool { + auto& system = Core::System::GetInstance(); + + const auto callback = [this, target, recursion, parent_dir, + &system](u64* num_entries_out, const std::string& directory, + const std::string& virtual_name) -> bool { if (stop_processing) { // Breaks the callback loop. return false; @@ -293,7 +298,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa if (!is_dir && (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); - auto loader = Loader::GetLoader(file); + auto loader = Loader::GetLoader(system, file); if (!loader) { return true; } @@ -331,7 +336,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa std::string name = " "; [[maybe_unused]] const auto res3 = loader->ReadTitle(name); - const FileSys::PatchManager patch{program_id}; + const FileSys::PatchManager patch{program_id, system.GetFileSystemController(), + system.GetContentProvider()}; emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id, compatibility_list, patch), diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9dabd8889..871ff4ae4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -172,7 +172,7 @@ void GMainWindow::ShowTelemetryCallout() { "<br/><br/>Would you like to share your usage data with us?"); if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) != QMessageBox::Yes) { Settings::values.enable_telemetry = false; - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); } } @@ -302,7 +302,7 @@ void GMainWindow::ControllerSelectorReconfigureControllers( emit ControllerSelectorReconfigureFinished(); // Don't forget to apply settings. - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); config->Save(); UpdateStatusButtons(); @@ -571,11 +571,11 @@ void GMainWindow::InitializeWidgets() { if (emulation_running) { return; } - bool is_async = !Settings::values.use_asynchronous_gpu_emulation.GetValue() || - Settings::values.use_multi_core.GetValue(); + const bool is_async = !Settings::values.use_asynchronous_gpu_emulation.GetValue() || + Settings::values.use_multi_core.GetValue(); Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); async_status_button->setText(tr("ASYNC")); async_status_button->setCheckable(true); @@ -590,12 +590,12 @@ void GMainWindow::InitializeWidgets() { return; } Settings::values.use_multi_core.SetValue(!Settings::values.use_multi_core.GetValue()); - bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue() || - Settings::values.use_multi_core.GetValue(); + const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue() || + Settings::values.use_multi_core.GetValue(); Settings::values.use_asynchronous_gpu_emulation.SetValue(is_async); async_status_button->setChecked(Settings::values.use_asynchronous_gpu_emulation.GetValue()); multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); multicore_status_button->setText(tr("MULTICORE")); multicore_status_button->setCheckable(true); @@ -630,7 +630,7 @@ void GMainWindow::InitializeWidgets() { Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); } - Settings::Apply(); + Settings::Apply(Core::System::GetInstance()); }); #endif // HAS_VULKAN statusBar()->insertPermanentWidget(0, renderer_status_button); @@ -978,7 +978,7 @@ void GMainWindow::AllowOSSleep() { #endif } -bool GMainWindow::LoadROM(const QString& filename) { +bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) { // Shutdown previous session if the emu thread is still active... if (emu_thread != nullptr) ShutdownGame(); @@ -1003,7 +1003,8 @@ bool GMainWindow::LoadROM(const QString& filename) { system.RegisterHostThread(); - const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; + const Core::System::ResultStatus result{ + system.Load(*render_window, filename.toStdString(), program_index)}; const auto drd_callout = (UISettings::values.callout_flags & static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; @@ -1085,14 +1086,18 @@ void GMainWindow::SelectAndSetCurrentUser() { Settings::values.current_user = dialog.GetIndex(); } -void GMainWindow::BootGame(const QString& filename) { +void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { LOG_INFO(Frontend, "yuzu starting..."); StoreRecentFile(filename); // Put the filename on top of the list u64 title_id{0}; + last_filename_booted = filename; + + auto& system = Core::System::GetInstance(); const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); - const auto loader = Loader::GetLoader(v_file); + const auto loader = Loader::GetLoader(system, v_file, program_index); + if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { // Load per game settings Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig); @@ -1106,7 +1111,7 @@ void GMainWindow::BootGame(const QString& filename) { SelectAndSetCurrentUser(); } - if (!LoadROM(filename)) + if (!LoadROM(filename, program_index)) return; // Create and start the emulation thread @@ -1114,6 +1119,10 @@ void GMainWindow::BootGame(const QString& filename) { emit EmulationStarting(emu_thread.get()); emu_thread->start(); + // Register an ExecuteProgram callback such that Core can execute a sub-program + system.RegisterExecuteProgramCallback( + [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); + connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views // before the CPU continues @@ -1144,9 +1153,13 @@ void GMainWindow::BootGame(const QString& filename) { std::string title_name; std::string title_version; - const auto res = Core::System::GetInstance().GetGameName(title_name); + const auto res = system.GetGameName(title_name); - const auto metadata = FileSys::PatchManager(title_id).GetControlMetadata(); + const auto metadata = [&system, title_id] { + const FileSys::PatchManager pm(title_id, system.GetFileSystemController(), + system.GetContentProvider()); + return pm.GetControlMetadata(); + }(); if (metadata.first != nullptr) { title_version = metadata.first->GetVersionString(); title_name = metadata.first->GetApplicationName(); @@ -1157,7 +1170,7 @@ void GMainWindow::BootGame(const QString& filename) { LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); UpdateWindowTitle(title_name, title_version); - loading_screen->Prepare(Core::System::GetInstance().GetAppLoader()); + loading_screen->Prepare(system.GetAppLoader()); loading_screen->show(); emulation_running = true; @@ -1276,16 +1289,18 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target const std::string& game_path) { std::string path; QString open_target; + auto& system = Core::System::GetInstance(); - const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] { - FileSys::PatchManager pm{program_id}; + const auto [user_save_size, device_save_size] = [this, &game_path, &program_id, &system] { + const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), + system.GetContentProvider()}; const auto control = pm.GetControlMetadata().first; if (control != nullptr) { return std::make_pair(control->GetDefaultNormalSaveSize(), control->GetDeviceSaveDataSize()); } else { const auto file = Core::GetGameFileFromPath(vfs, game_path); - const auto loader = Loader::GetLoader(file); + const auto loader = Loader::GetLoader(system, file); FileSys::NACP nacp{}; loader->ReadControlData(nacp); @@ -1327,12 +1342,12 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target const auto user_id = manager.GetUser(static_cast<std::size_t>(index)); ASSERT(user_id); path = nand_dir + FileSys::SaveDataFactory::GetFullPath( - FileSys::SaveDataSpaceId::NandUser, + system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, program_id, user_id->uuid, 0); } else { // Device save data path = nand_dir + FileSys::SaveDataFactory::GetFullPath( - FileSys::SaveDataSpaceId::NandUser, + system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, program_id, {}, 0); } @@ -1612,7 +1627,8 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa "cancelled the operation.")); }; - const auto loader = Loader::GetLoader(vfs->OpenFile(game_path, FileSys::Mode::Read)); + auto& system = Core::System::GetInstance(); + const auto loader = Loader::GetLoader(system, vfs->OpenFile(game_path, FileSys::Mode::Read)); if (loader == nullptr) { failed(); return; @@ -1624,7 +1640,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa return; } - const auto& installed = Core::System::GetInstance().GetContentProvider(); + const auto& installed = system.GetContentProvider(); const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); if (!romfs_title_id) { @@ -1639,7 +1655,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa if (*romfs_title_id == program_id) { const u64 ivfc_offset = loader->ReadRomFSIVFCOffset(); - FileSys::PatchManager pm{program_id}; + const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), installed}; romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program); } else { romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); @@ -1756,7 +1772,8 @@ void GMainWindow::OnGameListShowList(bool show) { void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { u64 title_id{}; const auto v_file = Core::GetGameFileFromPath(vfs, file); - const auto loader = Loader::GetLoader(v_file); + const auto loader = Loader::GetLoader(Core::System::GetInstance(), v_file); + if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { QMessageBox::information(this, tr("Properties"), tr("The game properties could not be loaded.")); @@ -2113,14 +2130,14 @@ void GMainWindow::OnPauseGame() { } void GMainWindow::OnStopGame() { - Core::System& system{Core::System::GetInstance()}; + auto& system{Core::System::GetInstance()}; if (system.GetExitLock() && !ConfirmForceLockedExit()) { return; } ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(system.IsPoweredOn()); UpdateStatusButtons(); } @@ -2128,6 +2145,11 @@ void GMainWindow::OnLoadComplete() { loading_screen->OnLoadComplete(); } +void GMainWindow::OnExecuteProgram(std::size_t program_index) { + ShutdownGame(); + BootGame(last_filename_booted, program_index); +} + void GMainWindow::ErrorDisplayDisplayError(QString body) { QMessageBox::critical(this, tr("Error Display"), body); emit ErrorDisplayFinished(); @@ -2290,10 +2312,11 @@ void GMainWindow::OnConfigurePerGame() { void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { const auto v_file = Core::GetGameFileFromPath(vfs, file_name); + const auto& system = Core::System::GetInstance(); ConfigurePerGame dialog(this, title_id); dialog.LoadFromFile(v_file); - auto result = dialog.exec(); + const auto result = dialog.exec(); if (result == QDialog::Accepted) { dialog.ApplyConfiguration(); @@ -2303,13 +2326,14 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file } // Do not cause the global config to write local settings into the config file - Settings::RestoreGlobalState(); + const bool is_powered_on = system.IsPoweredOn(); + Settings::RestoreGlobalState(is_powered_on); - if (!Core::System::GetInstance().IsPoweredOn()) { + if (!is_powered_on) { config->Save(); } } else { - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(system.IsPoweredOn()); } } @@ -2580,7 +2604,7 @@ void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string det if (emu_thread) { ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(Core::System::GetInstance().IsPoweredOn()); UpdateStatusButtons(); } } else { @@ -2752,7 +2776,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { if (emu_thread != nullptr) { ShutdownGame(); - Settings::RestoreGlobalState(); + Settings::RestoreGlobalState(Core::System::GetInstance().IsPoweredOn()); UpdateStatusButtons(); } diff --git a/src/yuzu/main.h b/src/yuzu/main.h index b380a66f3..6242341d1 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -131,6 +131,7 @@ signals: public slots: void OnLoadComplete(); + void OnExecuteProgram(std::size_t program_index); void ControllerSelectorReconfigureControllers( const Core::Frontend::ControllerParameters& parameters); void ErrorDisplayDisplayError(QString body); @@ -154,8 +155,8 @@ private: void PreventOSSleep(); void AllowOSSleep(); - bool LoadROM(const QString& filename); - void BootGame(const QString& filename); + bool LoadROM(const QString& filename, std::size_t program_index); + void BootGame(const QString& filename, std::size_t program_index = 0); void ShutdownGame(); void ShowTelemetryCallout(); @@ -317,6 +318,9 @@ private: // Install progress dialog QProgressDialog* install_progress; + // Last game booted, used for multi-process apps + QString last_filename_booted; + protected: void dropEvent(QDropEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override; diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 72ec25c99..e32bed5e6 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -121,62 +121,64 @@ void EmuWindow_SDL2::Fullscreen() { SDL_MaximizeWindow(render_window); } -void EmuWindow_SDL2::PollEvents() { +void EmuWindow_SDL2::WaitEvent() { + // Called on main thread SDL_Event event; - // SDL_PollEvent returns 0 when there are no more events in the event queue - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_SIZE_CHANGED: - case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: - OnResize(); - break; - case SDL_WINDOWEVENT_MINIMIZED: - case SDL_WINDOWEVENT_EXPOSED: - is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED; - OnResize(); - break; - case SDL_WINDOWEVENT_CLOSE: - is_open = false; - break; - } - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state); - break; - case SDL_MOUSEMOTION: - // ignore if it came from touch - if (event.button.which != SDL_TOUCH_MOUSEID) - OnMouseMotion(event.motion.x, event.motion.y); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - // ignore if it came from touch - if (event.button.which != SDL_TOUCH_MOUSEID) { - OnMouseButton(event.button.button, event.button.state, event.button.x, - event.button.y); - } - break; - case SDL_FINGERDOWN: - OnFingerDown(event.tfinger.x, event.tfinger.y); - break; - case SDL_FINGERMOTION: - OnFingerMotion(event.tfinger.x, event.tfinger.y); + if (!SDL_WaitEvent(&event)) { + LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", SDL_GetError()); + exit(1); + } + + switch (event.type) { + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_SIZE_CHANGED: + case SDL_WINDOWEVENT_RESIZED: + case SDL_WINDOWEVENT_MAXIMIZED: + case SDL_WINDOWEVENT_RESTORED: + OnResize(); break; - case SDL_FINGERUP: - OnFingerUp(); + case SDL_WINDOWEVENT_MINIMIZED: + case SDL_WINDOWEVENT_EXPOSED: + is_shown = event.window.event == SDL_WINDOWEVENT_EXPOSED; + OnResize(); break; - case SDL_QUIT: + case SDL_WINDOWEVENT_CLOSE: is_open = false; break; - default: - break; } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + OnKeyEvent(static_cast<int>(event.key.keysym.scancode), event.key.state); + break; + case SDL_MOUSEMOTION: + // ignore if it came from touch + if (event.button.which != SDL_TOUCH_MOUSEID) + OnMouseMotion(event.motion.x, event.motion.y); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + // ignore if it came from touch + if (event.button.which != SDL_TOUCH_MOUSEID) { + OnMouseButton(event.button.button, event.button.state, event.button.x, event.button.y); + } + break; + case SDL_FINGERDOWN: + OnFingerDown(event.tfinger.x, event.tfinger.y); + break; + case SDL_FINGERMOTION: + OnFingerMotion(event.tfinger.x, event.tfinger.y); + break; + case SDL_FINGERUP: + OnFingerUp(); + break; + case SDL_QUIT: + is_open = false; + break; + default: + break; } const u32 current_time = SDL_GetTicks(); diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 53d756c3c..a93141240 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h @@ -23,38 +23,38 @@ public: explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem); ~EmuWindow_SDL2(); - /// Polls window events - void PollEvents() override; - /// Whether the window is still open, and a close request hasn't yet been sent bool IsOpen() const; /// Returns if window is shown (not minimized) bool IsShown() const override; + /// Wait for the next event on the main thread. + void WaitEvent(); + protected: - /// Called by PollEvents when a key is pressed or released. + /// Called by WaitEvent when a key is pressed or released. void OnKeyEvent(int key, u8 state); - /// Called by PollEvents when the mouse moves. + /// Called by WaitEvent when the mouse moves. void OnMouseMotion(s32 x, s32 y); - /// Called by PollEvents when a mouse button is pressed or released + /// Called by WaitEvent when a mouse button is pressed or released void OnMouseButton(u32 button, u8 state, s32 x, s32 y); /// Translates pixel position (0..1) to pixel positions std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const; - /// Called by PollEvents when a finger starts touching the touchscreen + /// Called by WaitEvent when a finger starts touching the touchscreen void OnFingerDown(float x, float y); - /// Called by PollEvents when a finger moves while touching the touchscreen + /// Called by WaitEvent when a finger moves while touching the touchscreen void OnFingerMotion(float x, float y); - /// Called by PollEvents when a finger stops touching the touchscreen + /// Called by WaitEvent when a finger stops touching the touchscreen void OnFingerUp(); - /// Called by PollEvents when any event that may cause the window to be resized occurs + /// Called by WaitEvent when any event that may cause the window to be resized occurs void OnResize(); /// Called when user passes the fullscreen parameter flag diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 3a76c785f..c2efe1ee6 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -25,7 +25,6 @@ #include "core/crypto/key_manager.h" #include "core/file_sys/registered_cache.h" #include "core/file_sys/vfs_real.h" -#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/loader/loader.h" @@ -174,13 +173,13 @@ int main(int argc, char** argv) { return -1; } + auto& system{Core::System::GetInstance()}; + InputCommon::InputSubsystem input_subsystem; + // Apply the command line arguments Settings::values.gdbstub_port = gdb_port; Settings::values.use_gdbstub = use_gdbstub; - Settings::Apply(); - - Core::System& system{Core::System::GetInstance()}; - InputCommon::InputSubsystem input_subsystem; + Settings::Apply(system); std::unique_ptr<EmuWindow_SDL2> emu_window; switch (Settings::values.renderer_backend.GetValue()) { @@ -240,11 +239,11 @@ int main(int argc, char** argv) { system.CurrentProcess()->GetTitleID(), false, [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); - system.Run(); + void(system.Run()); while (emu_window->IsOpen()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + emu_window->WaitEvent(); } - system.Pause(); + void(system.Pause()); system.Shutdown(); detached_tasks.WaitForAllTasks(); diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp index 78f75fb38..358e03870 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.cpp @@ -109,8 +109,6 @@ EmuWindow_SDL2_Hide::~EmuWindow_SDL2_Hide() { SDL_Quit(); } -void EmuWindow_SDL2_Hide::PollEvents() {} - bool EmuWindow_SDL2_Hide::IsShown() const { return false; } diff --git a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h index a553b4b95..adccdf35e 100644 --- a/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h +++ b/src/yuzu_tester/emu_window/emu_window_sdl2_hide.h @@ -17,9 +17,6 @@ public: explicit EmuWindow_SDL2_Hide(); ~EmuWindow_SDL2_Hide(); - /// Polls window events - void PollEvents() override; - /// Whether the screen is being shown or not. bool IsShown() const override; diff --git a/src/yuzu_tester/service/yuzutest.cpp b/src/yuzu_tester/service/yuzutest.cpp index 2d3f6e3a7..e257fae25 100644 --- a/src/yuzu_tester/service/yuzutest.cpp +++ b/src/yuzu_tester/service/yuzutest.cpp @@ -4,6 +4,7 @@ #include <memory> #include "common/string_util.h" +#include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -15,10 +16,10 @@ constexpr u64 SERVICE_VERSION = 0x00000002; class YuzuTest final : public ServiceFramework<YuzuTest> { public: - explicit YuzuTest(std::string data, - std::function<void(std::vector<TestResult>)> finish_callback) - : ServiceFramework{"yuzutest"}, data(std::move(data)), - finish_callback(std::move(finish_callback)) { + explicit YuzuTest(Core::System& system_, std::string data_, + std::function<void(std::vector<TestResult>)> finish_callback_) + : ServiceFramework{system_, "yuzutest"}, data{std::move(data_)}, finish_callback{std::move( + finish_callback_)} { static const FunctionInfo functions[] = { {0, &YuzuTest::Initialize, "Initialize"}, {1, &YuzuTest::GetServiceVersion, "GetServiceVersion"}, @@ -104,9 +105,11 @@ private: std::function<void(std::vector<TestResult>)> finish_callback; }; -void InstallInterfaces(SM::ServiceManager& sm, std::string data, +void InstallInterfaces(Core::System& system, std::string data, std::function<void(std::vector<TestResult>)> finish_callback) { - std::make_shared<YuzuTest>(data, finish_callback)->InstallAsService(sm); + auto& sm = system.ServiceManager(); + std::make_shared<YuzuTest>(system, std::move(data), std::move(finish_callback)) + ->InstallAsService(sm); } } // namespace Service::Yuzu diff --git a/src/yuzu_tester/service/yuzutest.h b/src/yuzu_tester/service/yuzutest.h index eca129c8c..7794814fa 100644 --- a/src/yuzu_tester/service/yuzutest.h +++ b/src/yuzu_tester/service/yuzutest.h @@ -7,8 +7,8 @@ #include <functional> #include <string> -namespace Service::SM { -class ServiceManager; +namespace Core { +class System; } namespace Service::Yuzu { @@ -19,7 +19,7 @@ struct TestResult { std::string name; }; -void InstallInterfaces(SM::ServiceManager& sm, std::string data, +void InstallInterfaces(Core::System& system, std::string data, std::function<void(std::vector<TestResult>)> finish_callback); } // namespace Service::Yuzu diff --git a/src/yuzu_tester/yuzu.cpp b/src/yuzu_tester/yuzu.cpp index 5798ce43a..50bd7ae41 100644 --- a/src/yuzu_tester/yuzu.cpp +++ b/src/yuzu_tester/yuzu.cpp @@ -160,10 +160,12 @@ int main(int argc, char** argv) { return -1; } + Core::System& system{Core::System::GetInstance()}; + Settings::values.use_gdbstub = false; - Settings::Apply(); + Settings::Apply(system); - std::unique_ptr<EmuWindow_SDL2_Hide> emu_window{std::make_unique<EmuWindow_SDL2_Hide>()}; + const auto emu_window{std::make_unique<EmuWindow_SDL2_Hide>()}; bool finished = false; int return_value = 0; @@ -212,7 +214,6 @@ int main(int argc, char** argv) { return_value = -1; }; - Core::System& system{Core::System::GetInstance()}; system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>()); system.GetFileSystemController().CreateFactories(*system.GetFilesystem()); @@ -247,20 +248,21 @@ int main(int argc, char** argv) { "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}", loader_id, error_id, static_cast<Loader::ResultStatus>(error_id)); } + break; } - Service::Yuzu::InstallInterfaces(system.ServiceManager(), datastring, callback); + Service::Yuzu::InstallInterfaces(system, datastring, callback); system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDLHideTester"); system.GPU().Start(); - system.Run(); + void(system.Run()); while (!finished) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - system.Pause(); + void(system.Pause()); detached_tasks.WaitForAllTasks(); return return_value; |