diff options
Diffstat (limited to 'src')
58 files changed, 1362 insertions, 167 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index f00a55994..81121167d 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt | |||
| @@ -2,10 +2,22 @@ add_library(audio_core STATIC | |||
| 2 | audio_out.cpp | 2 | audio_out.cpp |
| 3 | audio_out.h | 3 | audio_out.h |
| 4 | buffer.h | 4 | buffer.h |
| 5 | cubeb_sink.cpp | ||
| 6 | cubeb_sink.h | ||
| 7 | null_sink.h | ||
| 5 | stream.cpp | 8 | stream.cpp |
| 6 | stream.h | 9 | stream.h |
| 10 | sink.h | ||
| 11 | sink_details.cpp | ||
| 12 | sink_details.h | ||
| 13 | sink_stream.h | ||
| 7 | ) | 14 | ) |
| 8 | 15 | ||
| 9 | create_target_directory_groups(audio_core) | 16 | create_target_directory_groups(audio_core) |
| 10 | 17 | ||
| 11 | target_link_libraries(audio_core PUBLIC common core) | 18 | target_link_libraries(audio_core PUBLIC common core) |
| 19 | |||
| 20 | if(ENABLE_CUBEB) | ||
| 21 | target_link_libraries(audio_core PRIVATE cubeb) | ||
| 22 | target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) | ||
| 23 | endif() | ||
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 6d418a05b..77cedb6ba 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp | |||
| @@ -3,13 +3,15 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "audio_core/audio_out.h" | 5 | #include "audio_core/audio_out.h" |
| 6 | #include "audio_core/sink.h" | ||
| 7 | #include "audio_core/sink_details.h" | ||
| 6 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 8 | 10 | ||
| 9 | namespace AudioCore { | 11 | namespace AudioCore { |
| 10 | 12 | ||
| 11 | /// Returns the stream format from the specified number of channels | 13 | /// Returns the stream format from the specified number of channels |
| 12 | static Stream::Format ChannelsToStreamFormat(int num_channels) { | 14 | static Stream::Format ChannelsToStreamFormat(u32 num_channels) { |
| 13 | switch (num_channels) { | 15 | switch (num_channels) { |
| 14 | case 1: | 16 | case 1: |
| 15 | return Stream::Format::Mono16; | 17 | return Stream::Format::Mono16; |
| @@ -24,11 +26,16 @@ static Stream::Format ChannelsToStreamFormat(int num_channels) { | |||
| 24 | return {}; | 26 | return {}; |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | StreamPtr AudioOut::OpenStream(int sample_rate, int num_channels, | 29 | StreamPtr AudioOut::OpenStream(u32 sample_rate, u32 num_channels, |
| 28 | Stream::ReleaseCallback&& release_callback) { | 30 | Stream::ReleaseCallback&& release_callback) { |
| 29 | streams.push_back(std::make_shared<Stream>(sample_rate, ChannelsToStreamFormat(num_channels), | 31 | if (!sink) { |
| 30 | std::move(release_callback))); | 32 | const SinkDetails& sink_details = GetSinkDetails("auto"); |
| 31 | return streams.back(); | 33 | sink = sink_details.factory(""); |
| 34 | } | ||
| 35 | |||
| 36 | return std::make_shared<Stream>(sample_rate, ChannelsToStreamFormat(num_channels), | ||
| 37 | std::move(release_callback), | ||
| 38 | sink->AcquireSinkStream(sample_rate, num_channels)); | ||
| 32 | } | 39 | } |
| 33 | 40 | ||
| 34 | std::vector<u64> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) { | 41 | std::vector<u64> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) { |
diff --git a/src/audio_core/audio_out.h b/src/audio_core/audio_out.h index a86499d10..8d9b695d4 100644 --- a/src/audio_core/audio_out.h +++ b/src/audio_core/audio_out.h | |||
| @@ -8,20 +8,19 @@ | |||
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "audio_core/buffer.h" | 10 | #include "audio_core/buffer.h" |
| 11 | #include "audio_core/sink.h" | ||
| 11 | #include "audio_core/stream.h" | 12 | #include "audio_core/stream.h" |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | 14 | ||
| 14 | namespace AudioCore { | 15 | namespace AudioCore { |
| 15 | 16 | ||
| 16 | using StreamPtr = std::shared_ptr<Stream>; | ||
| 17 | |||
| 18 | /** | 17 | /** |
| 19 | * Represents an audio playback interface, used to open and play audio streams | 18 | * Represents an audio playback interface, used to open and play audio streams |
| 20 | */ | 19 | */ |
| 21 | class AudioOut { | 20 | class AudioOut { |
| 22 | public: | 21 | public: |
| 23 | /// Opens a new audio stream | 22 | /// Opens a new audio stream |
| 24 | StreamPtr OpenStream(int sample_rate, int num_channels, | 23 | StreamPtr OpenStream(u32 sample_rate, u32 num_channels, |
| 25 | Stream::ReleaseCallback&& release_callback); | 24 | Stream::ReleaseCallback&& release_callback); |
| 26 | 25 | ||
| 27 | /// Returns a vector of recently released buffers specified by tag for the specified stream | 26 | /// Returns a vector of recently released buffers specified by tag for the specified stream |
| @@ -37,8 +36,7 @@ public: | |||
| 37 | bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data); | 36 | bool QueueBuffer(StreamPtr stream, Buffer::Tag tag, std::vector<u8>&& data); |
| 38 | 37 | ||
| 39 | private: | 38 | private: |
| 40 | /// Active audio streams on the interface | 39 | SinkPtr sink; |
| 41 | std::vector<StreamPtr> streams; | ||
| 42 | }; | 40 | }; |
| 43 | 41 | ||
| 44 | } // namespace AudioCore | 42 | } // namespace AudioCore |
diff --git a/src/audio_core/buffer.h b/src/audio_core/buffer.h index 874ec787e..4bf5fd58a 100644 --- a/src/audio_core/buffer.h +++ b/src/audio_core/buffer.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -34,4 +35,6 @@ private: | |||
| 34 | std::vector<u8> data; | 35 | std::vector<u8> data; |
| 35 | }; | 36 | }; |
| 36 | 37 | ||
| 38 | using BufferPtr = std::shared_ptr<Buffer>; | ||
| 39 | |||
| 37 | } // namespace AudioCore | 40 | } // namespace AudioCore |
diff --git a/src/audio_core/cubeb_sink.cpp b/src/audio_core/cubeb_sink.cpp new file mode 100644 index 000000000..34ae5b062 --- /dev/null +++ b/src/audio_core/cubeb_sink.cpp | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cstring> | ||
| 7 | |||
| 8 | #include "audio_core/cubeb_sink.h" | ||
| 9 | #include "audio_core/stream.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | |||
| 12 | namespace AudioCore { | ||
| 13 | |||
| 14 | class SinkStreamImpl final : public SinkStream { | ||
| 15 | public: | ||
| 16 | SinkStreamImpl(cubeb* ctx, cubeb_devid output_device) : ctx{ctx} { | ||
| 17 | cubeb_stream_params params; | ||
| 18 | params.rate = 48000; | ||
| 19 | params.channels = GetNumChannels(); | ||
| 20 | params.format = CUBEB_SAMPLE_S16NE; | ||
| 21 | params.layout = CUBEB_LAYOUT_STEREO; | ||
| 22 | |||
| 23 | u32 minimum_latency = 0; | ||
| 24 | if (cubeb_get_min_latency(ctx, ¶ms, &minimum_latency) != CUBEB_OK) { | ||
| 25 | LOG_CRITICAL(Audio_Sink, "Error getting minimum latency"); | ||
| 26 | } | ||
| 27 | |||
| 28 | if (cubeb_stream_init(ctx, &stream_backend, "yuzu Audio Output", nullptr, nullptr, | ||
| 29 | output_device, ¶ms, std::max(512u, minimum_latency), | ||
| 30 | &SinkStreamImpl::DataCallback, &SinkStreamImpl::StateCallback, | ||
| 31 | this) != CUBEB_OK) { | ||
| 32 | LOG_CRITICAL(Audio_Sink, "Error initializing cubeb stream"); | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | |||
| 36 | if (cubeb_stream_start(stream_backend) != CUBEB_OK) { | ||
| 37 | LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream"); | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | ~SinkStreamImpl() { | ||
| 43 | if (!ctx) { | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | |||
| 47 | if (cubeb_stream_stop(stream_backend) != CUBEB_OK) { | ||
| 48 | LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream"); | ||
| 49 | } | ||
| 50 | |||
| 51 | cubeb_stream_destroy(stream_backend); | ||
| 52 | } | ||
| 53 | |||
| 54 | void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) override { | ||
| 55 | if (!ctx) { | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | queue.reserve(queue.size() + sample_count * GetNumChannels()); | ||
| 60 | |||
| 61 | if (num_channels == 2) { | ||
| 62 | // Copy as-is | ||
| 63 | std::copy(samples, samples + sample_count * GetNumChannels(), | ||
| 64 | std::back_inserter(queue)); | ||
| 65 | } else if (num_channels == 6) { | ||
| 66 | // Downsample 6 channels to 2 | ||
| 67 | const size_t sample_count_copy_size = sample_count * num_channels * 2; | ||
| 68 | queue.reserve(sample_count_copy_size); | ||
| 69 | for (size_t i = 0; i < sample_count * num_channels; i += num_channels) { | ||
| 70 | queue.push_back(samples[i]); | ||
| 71 | queue.push_back(samples[i + 1]); | ||
| 72 | } | ||
| 73 | } else { | ||
| 74 | ASSERT_MSG(false, "Unimplemented"); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | u32 GetNumChannels() const { | ||
| 79 | // Only support 2-channel stereo output for now | ||
| 80 | return 2; | ||
| 81 | } | ||
| 82 | |||
| 83 | private: | ||
| 84 | std::vector<std::string> device_list; | ||
| 85 | |||
| 86 | cubeb* ctx{}; | ||
| 87 | cubeb_stream* stream_backend{}; | ||
| 88 | |||
| 89 | std::vector<s16> queue; | ||
| 90 | |||
| 91 | static long DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||
| 92 | void* output_buffer, long num_frames); | ||
| 93 | static void StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state); | ||
| 94 | }; | ||
| 95 | |||
| 96 | CubebSink::CubebSink(std::string target_device_name) { | ||
| 97 | if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) { | ||
| 98 | LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (target_device_name != auto_device_name && !target_device_name.empty()) { | ||
| 103 | cubeb_device_collection collection; | ||
| 104 | if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { | ||
| 105 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | ||
| 106 | } else { | ||
| 107 | const auto collection_end{collection.device + collection.count}; | ||
| 108 | const auto device{std::find_if(collection.device, collection_end, | ||
| 109 | [&](const cubeb_device_info& device) { | ||
| 110 | return target_device_name == device.friendly_name; | ||
| 111 | })}; | ||
| 112 | if (device != collection_end) { | ||
| 113 | output_device = device->devid; | ||
| 114 | } | ||
| 115 | cubeb_device_collection_destroy(ctx, &collection); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | CubebSink::~CubebSink() { | ||
| 121 | if (!ctx) { | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | |||
| 125 | for (auto& sink_stream : sink_streams) { | ||
| 126 | sink_stream.reset(); | ||
| 127 | } | ||
| 128 | |||
| 129 | cubeb_destroy(ctx); | ||
| 130 | } | ||
| 131 | |||
| 132 | SinkStream& CubebSink::AcquireSinkStream(u32 sample_rate, u32 num_channels) { | ||
| 133 | sink_streams.push_back(std::make_unique<SinkStreamImpl>(ctx, output_device)); | ||
| 134 | return *sink_streams.back(); | ||
| 135 | } | ||
| 136 | |||
| 137 | long SinkStreamImpl::DataCallback(cubeb_stream* stream, void* user_data, const void* input_buffer, | ||
| 138 | void* output_buffer, long num_frames) { | ||
| 139 | SinkStreamImpl* impl = static_cast<SinkStreamImpl*>(user_data); | ||
| 140 | u8* buffer = reinterpret_cast<u8*>(output_buffer); | ||
| 141 | |||
| 142 | if (!impl) { | ||
| 143 | return {}; | ||
| 144 | } | ||
| 145 | |||
| 146 | const size_t frames_to_write{ | ||
| 147 | std::min(impl->queue.size() / impl->GetNumChannels(), static_cast<size_t>(num_frames))}; | ||
| 148 | |||
| 149 | memcpy(buffer, impl->queue.data(), frames_to_write * sizeof(s16) * impl->GetNumChannels()); | ||
| 150 | impl->queue.erase(impl->queue.begin(), | ||
| 151 | impl->queue.begin() + frames_to_write * impl->GetNumChannels()); | ||
| 152 | |||
| 153 | if (frames_to_write < num_frames) { | ||
| 154 | // Fill the rest of the frames with silence | ||
| 155 | memset(buffer + frames_to_write * sizeof(s16) * impl->GetNumChannels(), 0, | ||
| 156 | (num_frames - frames_to_write) * sizeof(s16) * impl->GetNumChannels()); | ||
| 157 | } | ||
| 158 | |||
| 159 | return num_frames; | ||
| 160 | } | ||
| 161 | |||
| 162 | void SinkStreamImpl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {} | ||
| 163 | |||
| 164 | std::vector<std::string> ListCubebSinkDevices() { | ||
| 165 | std::vector<std::string> device_list; | ||
| 166 | cubeb* ctx; | ||
| 167 | |||
| 168 | if (cubeb_init(&ctx, "Citra Device Enumerator", nullptr) != CUBEB_OK) { | ||
| 169 | LOG_CRITICAL(Audio_Sink, "cubeb_init failed"); | ||
| 170 | return {}; | ||
| 171 | } | ||
| 172 | |||
| 173 | cubeb_device_collection collection; | ||
| 174 | if (cubeb_enumerate_devices(ctx, CUBEB_DEVICE_TYPE_OUTPUT, &collection) != CUBEB_OK) { | ||
| 175 | LOG_WARNING(Audio_Sink, "Audio output device enumeration not supported"); | ||
| 176 | } else { | ||
| 177 | for (size_t i = 0; i < collection.count; i++) { | ||
| 178 | const cubeb_device_info& device = collection.device[i]; | ||
| 179 | if (device.friendly_name) { | ||
| 180 | device_list.emplace_back(device.friendly_name); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | cubeb_device_collection_destroy(ctx, &collection); | ||
| 184 | } | ||
| 185 | |||
| 186 | cubeb_destroy(ctx); | ||
| 187 | return device_list; | ||
| 188 | } | ||
| 189 | |||
| 190 | } // namespace AudioCore | ||
diff --git a/src/audio_core/cubeb_sink.h b/src/audio_core/cubeb_sink.h new file mode 100644 index 000000000..d07113f1f --- /dev/null +++ b/src/audio_core/cubeb_sink.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include <cubeb/cubeb.h> | ||
| 11 | |||
| 12 | #include "audio_core/sink.h" | ||
| 13 | |||
| 14 | namespace AudioCore { | ||
| 15 | |||
| 16 | class CubebSink final : public Sink { | ||
| 17 | public: | ||
| 18 | explicit CubebSink(std::string device_id); | ||
| 19 | ~CubebSink() override; | ||
| 20 | |||
| 21 | SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) override; | ||
| 22 | |||
| 23 | private: | ||
| 24 | cubeb* ctx{}; | ||
| 25 | cubeb_devid output_device{}; | ||
| 26 | std::vector<SinkStreamPtr> sink_streams; | ||
| 27 | }; | ||
| 28 | |||
| 29 | std::vector<std::string> ListCubebSinkDevices(); | ||
| 30 | |||
| 31 | } // namespace AudioCore | ||
diff --git a/src/audio_core/null_sink.h b/src/audio_core/null_sink.h new file mode 100644 index 000000000..2e04438f7 --- /dev/null +++ b/src/audio_core/null_sink.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "audio_core/sink.h" | ||
| 8 | |||
| 9 | namespace AudioCore { | ||
| 10 | |||
| 11 | class NullSink final : public Sink { | ||
| 12 | public: | ||
| 13 | explicit NullSink(std::string){}; | ||
| 14 | ~NullSink() override = default; | ||
| 15 | |||
| 16 | SinkStream& AcquireSinkStream(u32 /*sample_rate*/, u32 /*num_channels*/) override { | ||
| 17 | return null_sink_stream; | ||
| 18 | } | ||
| 19 | |||
| 20 | private: | ||
| 21 | struct NullSinkStreamImpl final : SinkStream { | ||
| 22 | void EnqueueSamples(u32 /*num_channels*/, const s16* /*samples*/, | ||
| 23 | size_t /*sample_count*/) override {} | ||
| 24 | } null_sink_stream; | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // namespace AudioCore | ||
diff --git a/src/audio_core/sink.h b/src/audio_core/sink.h new file mode 100644 index 000000000..d1bb98c3d --- /dev/null +++ b/src/audio_core/sink.h | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "audio_core/sink_stream.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace AudioCore { | ||
| 13 | |||
| 14 | constexpr char auto_device_name[] = "auto"; | ||
| 15 | |||
| 16 | /** | ||
| 17 | * This class is an interface for an audio sink. An audio sink accepts samples in stereo signed | ||
| 18 | * PCM16 format to be output. Sinks *do not* handle resampling and expect the correct sample rate. | ||
| 19 | * They are dumb outputs. | ||
| 20 | */ | ||
| 21 | class Sink { | ||
| 22 | public: | ||
| 23 | virtual ~Sink() = default; | ||
| 24 | virtual SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) = 0; | ||
| 25 | }; | ||
| 26 | |||
| 27 | using SinkPtr = std::unique_ptr<Sink>; | ||
| 28 | |||
| 29 | } // namespace AudioCore | ||
diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp new file mode 100644 index 000000000..955ba20fb --- /dev/null +++ b/src/audio_core/sink_details.cpp | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <memory> | ||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | #include "audio_core/null_sink.h" | ||
| 10 | #include "audio_core/sink_details.h" | ||
| 11 | #ifdef HAVE_CUBEB | ||
| 12 | #include "audio_core/cubeb_sink.h" | ||
| 13 | #endif | ||
| 14 | #include "common/logging/log.h" | ||
| 15 | |||
| 16 | namespace AudioCore { | ||
| 17 | |||
| 18 | // g_sink_details is ordered in terms of desirability, with the best choice at the top. | ||
| 19 | const std::vector<SinkDetails> g_sink_details = { | ||
| 20 | #ifdef HAVE_CUBEB | ||
| 21 | SinkDetails{"cubeb", &std::make_unique<CubebSink, std::string>, &ListCubebSinkDevices}, | ||
| 22 | #endif | ||
| 23 | SinkDetails{"null", &std::make_unique<NullSink, std::string>, | ||
| 24 | [] { return std::vector<std::string>{"null"}; }}, | ||
| 25 | }; | ||
| 26 | |||
| 27 | const SinkDetails& GetSinkDetails(std::string sink_id) { | ||
| 28 | auto iter = | ||
| 29 | std::find_if(g_sink_details.begin(), g_sink_details.end(), | ||
| 30 | [sink_id](const auto& sink_detail) { return sink_detail.id == sink_id; }); | ||
| 31 | |||
| 32 | if (sink_id == "auto" || iter == g_sink_details.end()) { | ||
| 33 | if (sink_id != "auto") { | ||
| 34 | LOG_ERROR(Audio, "AudioCore::SelectSink given invalid sink_id {}", sink_id); | ||
| 35 | } | ||
| 36 | // Auto-select. | ||
| 37 | // g_sink_details is ordered in terms of desirability, with the best choice at the front. | ||
| 38 | iter = g_sink_details.begin(); | ||
| 39 | } | ||
| 40 | |||
| 41 | return *iter; | ||
| 42 | } | ||
| 43 | |||
| 44 | } // namespace AudioCore | ||
diff --git a/src/audio_core/sink_details.h b/src/audio_core/sink_details.h new file mode 100644 index 000000000..aa8aae1a9 --- /dev/null +++ b/src/audio_core/sink_details.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <functional> | ||
| 8 | #include <memory> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | namespace AudioCore { | ||
| 12 | |||
| 13 | class Sink; | ||
| 14 | |||
| 15 | struct SinkDetails { | ||
| 16 | SinkDetails(const char* id_, std::function<std::unique_ptr<Sink>(std::string)> factory_, | ||
| 17 | std::function<std::vector<std::string>()> list_devices_) | ||
| 18 | : id(id_), factory(factory_), list_devices(list_devices_) {} | ||
| 19 | |||
| 20 | /// Name for this sink. | ||
| 21 | const char* id; | ||
| 22 | /// A method to call to construct an instance of this type of sink. | ||
| 23 | std::function<std::unique_ptr<Sink>(std::string device_id)> factory; | ||
| 24 | /// A method to call to list available devices. | ||
| 25 | std::function<std::vector<std::string>()> list_devices; | ||
| 26 | }; | ||
| 27 | |||
| 28 | extern const std::vector<SinkDetails> g_sink_details; | ||
| 29 | |||
| 30 | const SinkDetails& GetSinkDetails(std::string sink_id); | ||
| 31 | |||
| 32 | } // namespace AudioCore | ||
diff --git a/src/audio_core/sink_stream.h b/src/audio_core/sink_stream.h new file mode 100644 index 000000000..e7a3f01b0 --- /dev/null +++ b/src/audio_core/sink_stream.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | |||
| 11 | namespace AudioCore { | ||
| 12 | |||
| 13 | /** | ||
| 14 | * Accepts samples in stereo signed PCM16 format to be output. Sinks *do not* handle resampling and | ||
| 15 | * expect the correct sample rate. They are dumb outputs. | ||
| 16 | */ | ||
| 17 | class SinkStream { | ||
| 18 | public: | ||
| 19 | virtual ~SinkStream() = default; | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Feed stereo samples to sink. | ||
| 23 | * @param num_channels Number of channels used. | ||
| 24 | * @param samples Samples in interleaved stereo PCM16 format. | ||
| 25 | * @param sample_count Number of samples. | ||
| 26 | */ | ||
| 27 | virtual void EnqueueSamples(u32 num_channels, const s16* samples, size_t sample_count) = 0; | ||
| 28 | }; | ||
| 29 | |||
| 30 | using SinkStreamPtr = std::unique_ptr<SinkStream>; | ||
| 31 | |||
| 32 | } // namespace AudioCore | ||
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 82bff4b9e..689f51a1d 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -7,30 +7,37 @@ | |||
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/core_timing_util.h" | 8 | #include "core/core_timing_util.h" |
| 9 | 9 | ||
| 10 | #include "audio_core/sink.h" | ||
| 11 | #include "audio_core/sink_details.h" | ||
| 10 | #include "audio_core/stream.h" | 12 | #include "audio_core/stream.h" |
| 11 | 13 | ||
| 12 | namespace AudioCore { | 14 | namespace AudioCore { |
| 13 | 15 | ||
| 14 | constexpr size_t MaxAudioBufferCount{32}; | 16 | constexpr size_t MaxAudioBufferCount{32}; |
| 15 | 17 | ||
| 16 | /// Returns the sample size for the specified audio stream format | 18 | u32 Stream::GetNumChannels() const { |
| 17 | static size_t SampleSizeFromFormat(Stream::Format format) { | ||
| 18 | switch (format) { | 19 | switch (format) { |
| 19 | case Stream::Format::Mono16: | 20 | case Format::Mono16: |
| 21 | return 1; | ||
| 22 | case Format::Stereo16: | ||
| 20 | return 2; | 23 | return 2; |
| 21 | case Stream::Format::Stereo16: | 24 | case Format::Multi51Channel16: |
| 22 | return 4; | 25 | return 6; |
| 23 | case Stream::Format::Multi51Channel16: | 26 | } |
| 24 | return 12; | ||
| 25 | }; | ||
| 26 | |||
| 27 | LOG_CRITICAL(Audio, "Unimplemented format={}", static_cast<u32>(format)); | 27 | LOG_CRITICAL(Audio, "Unimplemented format={}", static_cast<u32>(format)); |
| 28 | UNREACHABLE(); | 28 | UNREACHABLE(); |
| 29 | return {}; | 29 | return {}; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | Stream::Stream(int sample_rate, Format format, ReleaseCallback&& release_callback) | 32 | u32 Stream::GetSampleSize() const { |
| 33 | : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)} { | 33 | return GetNumChannels() * 2; |
| 34 | } | ||
| 35 | |||
| 36 | Stream::Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback, | ||
| 37 | SinkStream& sink_stream) | ||
| 38 | : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)}, | ||
| 39 | sink_stream{sink_stream} { | ||
| 40 | |||
| 34 | release_event = CoreTiming::RegisterEvent( | 41 | release_event = CoreTiming::RegisterEvent( |
| 35 | "Stream::Release", [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); }); | 42 | "Stream::Release", [this](u64 userdata, int cycles_late) { ReleaseActiveBuffer(); }); |
| 36 | } | 43 | } |
| @@ -45,7 +52,7 @@ void Stream::Stop() { | |||
| 45 | } | 52 | } |
| 46 | 53 | ||
| 47 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { | 54 | s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { |
| 48 | const size_t num_samples{buffer.GetData().size() / SampleSizeFromFormat(format)}; | 55 | const size_t num_samples{buffer.GetData().size() / GetSampleSize()}; |
| 49 | return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); | 56 | return CoreTiming::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); |
| 50 | } | 57 | } |
| 51 | 58 | ||
| @@ -68,6 +75,10 @@ void Stream::PlayNextBuffer() { | |||
| 68 | active_buffer = queued_buffers.front(); | 75 | active_buffer = queued_buffers.front(); |
| 69 | queued_buffers.pop(); | 76 | queued_buffers.pop(); |
| 70 | 77 | ||
| 78 | sink_stream.EnqueueSamples(GetNumChannels(), | ||
| 79 | reinterpret_cast<const s16*>(active_buffer->GetData().data()), | ||
| 80 | active_buffer->GetData().size() / GetSampleSize()); | ||
| 81 | |||
| 71 | CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {}); | 82 | CoreTiming::ScheduleEventThreadsafe(GetBufferReleaseCycles(*active_buffer), release_event, {}); |
| 72 | } | 83 | } |
| 73 | 84 | ||
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 5f43b0798..35253920e 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h | |||
| @@ -10,14 +10,13 @@ | |||
| 10 | #include <queue> | 10 | #include <queue> |
| 11 | 11 | ||
| 12 | #include "audio_core/buffer.h" | 12 | #include "audio_core/buffer.h" |
| 13 | #include "audio_core/sink_stream.h" | ||
| 13 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| 14 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 15 | #include "core/core_timing.h" | 16 | #include "core/core_timing.h" |
| 16 | 17 | ||
| 17 | namespace AudioCore { | 18 | namespace AudioCore { |
| 18 | 19 | ||
| 19 | using BufferPtr = std::shared_ptr<Buffer>; | ||
| 20 | |||
| 21 | /** | 20 | /** |
| 22 | * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut | 21 | * Represents an audio stream, which is a sequence of queued buffers, to be outputed by AudioOut |
| 23 | */ | 22 | */ |
| @@ -33,7 +32,8 @@ public: | |||
| 33 | /// Callback function type, used to change guest state on a buffer being released | 32 | /// Callback function type, used to change guest state on a buffer being released |
| 34 | using ReleaseCallback = std::function<void()>; | 33 | using ReleaseCallback = std::function<void()>; |
| 35 | 34 | ||
| 36 | Stream(int sample_rate, Format format, ReleaseCallback&& release_callback); | 35 | Stream(u32 sample_rate, Format format, ReleaseCallback&& release_callback, |
| 36 | SinkStream& sink_stream); | ||
| 37 | 37 | ||
| 38 | /// Plays the audio stream | 38 | /// Plays the audio stream |
| 39 | void Play(); | 39 | void Play(); |
| @@ -60,6 +60,17 @@ public: | |||
| 60 | return queued_buffers.size(); | 60 | return queued_buffers.size(); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | /// Gets the sample rate | ||
| 64 | u32 GetSampleRate() const { | ||
| 65 | return sample_rate; | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Gets the number of channels | ||
| 69 | u32 GetNumChannels() const; | ||
| 70 | |||
| 71 | /// Gets the sample size in bytes | ||
| 72 | u32 GetSampleSize() const; | ||
| 73 | |||
| 63 | private: | 74 | private: |
| 64 | /// Current state of the stream | 75 | /// Current state of the stream |
| 65 | enum class State { | 76 | enum class State { |
| @@ -76,7 +87,7 @@ private: | |||
| 76 | /// Gets the number of core cycles when the specified buffer will be released | 87 | /// Gets the number of core cycles when the specified buffer will be released |
| 77 | s64 GetBufferReleaseCycles(const Buffer& buffer) const; | 88 | s64 GetBufferReleaseCycles(const Buffer& buffer) const; |
| 78 | 89 | ||
| 79 | int sample_rate; ///< Sample rate of the stream | 90 | u32 sample_rate; ///< Sample rate of the stream |
| 80 | Format format; ///< Format of the stream | 91 | Format format; ///< Format of the stream |
| 81 | ReleaseCallback release_callback; ///< Buffer release callback for the stream | 92 | ReleaseCallback release_callback; ///< Buffer release callback for the stream |
| 82 | State state{State::Stopped}; ///< Playback state of the stream | 93 | State state{State::Stopped}; ///< Playback state of the stream |
| @@ -84,6 +95,9 @@ private: | |||
| 84 | BufferPtr active_buffer; ///< Actively playing buffer in the stream | 95 | BufferPtr active_buffer; ///< Actively playing buffer in the stream |
| 85 | std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream | 96 | std::queue<BufferPtr> queued_buffers; ///< Buffers queued to be played in the stream |
| 86 | std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream | 97 | std::queue<BufferPtr> released_buffers; ///< Buffers recently released from the stream |
| 98 | SinkStream& sink_stream; ///< Output sink for the stream | ||
| 87 | }; | 99 | }; |
| 88 | 100 | ||
| 101 | using StreamPtr = std::shared_ptr<Stream>; | ||
| 102 | |||
| 89 | } // namespace AudioCore | 103 | } // namespace AudioCore |
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 93f1c0044..8b0d34da6 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <string> | 7 | #include <string> |
| 8 | 8 | ||
| 9 | #if !defined(ARCHITECTURE_x86_64) && !defined(ARCHITECTURE_ARM) | 9 | #if !defined(ARCHITECTURE_x86_64) |
| 10 | #include <cstdlib> // for exit | 10 | #include <cstdlib> // for exit |
| 11 | #endif | 11 | #endif |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| @@ -32,8 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | #ifdef ARCHITECTURE_x86_64 | 33 | #ifdef ARCHITECTURE_x86_64 |
| 34 | #define Crash() __asm__ __volatile__("int $3") | 34 | #define Crash() __asm__ __volatile__("int $3") |
| 35 | #elif defined(ARCHITECTURE_ARM) | ||
| 36 | #define Crash() __asm__ __volatile__("trap") | ||
| 37 | #else | 35 | #else |
| 38 | #define Crash() exit(1) | 36 | #define Crash() exit(1) |
| 39 | #endif | 37 | #endif |
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 38cc85e23..d86c40d26 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -169,7 +169,9 @@ void FileBackend::Write(const Entry& entry) { | |||
| 169 | SUB(Service, AOC) \ | 169 | SUB(Service, AOC) \ |
| 170 | SUB(Service, APM) \ | 170 | SUB(Service, APM) \ |
| 171 | SUB(Service, BCAT) \ | 171 | SUB(Service, BCAT) \ |
| 172 | SUB(Service, BTM) \ | ||
| 172 | SUB(Service, Fatal) \ | 173 | SUB(Service, Fatal) \ |
| 174 | SUB(Service, FGM) \ | ||
| 173 | SUB(Service, Friend) \ | 175 | SUB(Service, Friend) \ |
| 174 | SUB(Service, FS) \ | 176 | SUB(Service, FS) \ |
| 175 | SUB(Service, HID) \ | 177 | SUB(Service, HID) \ |
| @@ -184,6 +186,7 @@ void FileBackend::Write(const Entry& entry) { | |||
| 184 | SUB(Service, NIFM) \ | 186 | SUB(Service, NIFM) \ |
| 185 | SUB(Service, NS) \ | 187 | SUB(Service, NS) \ |
| 186 | SUB(Service, NVDRV) \ | 188 | SUB(Service, NVDRV) \ |
| 189 | SUB(Service, PCIE) \ | ||
| 187 | SUB(Service, PCTL) \ | 190 | SUB(Service, PCTL) \ |
| 188 | SUB(Service, PREPO) \ | 191 | SUB(Service, PREPO) \ |
| 189 | SUB(Service, SET) \ | 192 | SUB(Service, SET) \ |
| @@ -192,6 +195,7 @@ void FileBackend::Write(const Entry& entry) { | |||
| 192 | SUB(Service, SSL) \ | 195 | SUB(Service, SSL) \ |
| 193 | SUB(Service, Time) \ | 196 | SUB(Service, Time) \ |
| 194 | SUB(Service, VI) \ | 197 | SUB(Service, VI) \ |
| 198 | SUB(Service, WLAN) \ | ||
| 195 | CLS(HW) \ | 199 | CLS(HW) \ |
| 196 | SUB(HW, Memory) \ | 200 | SUB(HW, Memory) \ |
| 197 | SUB(HW, LCD) \ | 201 | SUB(HW, LCD) \ |
diff --git a/src/common/logging/log.h b/src/common/logging/log.h index db4a80d0a..140cd8e47 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h | |||
| @@ -56,7 +56,9 @@ enum class Class : ClassType { | |||
| 56 | Service_APM, ///< The APM (Performance) service | 56 | Service_APM, ///< The APM (Performance) service |
| 57 | Service_Audio, ///< The Audio (Audio control) service | 57 | Service_Audio, ///< The Audio (Audio control) service |
| 58 | Service_BCAT, ///< The BCAT service | 58 | Service_BCAT, ///< The BCAT service |
| 59 | Service_BTM, ///< The BTM service | ||
| 59 | Service_Fatal, ///< The Fatal service | 60 | Service_Fatal, ///< The Fatal service |
| 61 | Service_FGM, ///< The FGM service | ||
| 60 | Service_Friend, ///< The friend service | 62 | Service_Friend, ///< The friend service |
| 61 | Service_FS, ///< The FS (Filesystem) service | 63 | Service_FS, ///< The FS (Filesystem) service |
| 62 | Service_HID, ///< The HID (Human interface device) service | 64 | Service_HID, ///< The HID (Human interface device) service |
| @@ -71,6 +73,7 @@ enum class Class : ClassType { | |||
| 71 | Service_NIFM, ///< The NIFM (Network interface) service | 73 | Service_NIFM, ///< The NIFM (Network interface) service |
| 72 | Service_NS, ///< The NS services | 74 | Service_NS, ///< The NS services |
| 73 | Service_NVDRV, ///< The NVDRV (Nvidia driver) service | 75 | Service_NVDRV, ///< The NVDRV (Nvidia driver) service |
| 76 | Service_PCIE, ///< The PCIe service | ||
| 74 | Service_PCTL, ///< The PCTL (Parental control) service | 77 | Service_PCTL, ///< The PCTL (Parental control) service |
| 75 | Service_PREPO, ///< The PREPO (Play report) service | 78 | Service_PREPO, ///< The PREPO (Play report) service |
| 76 | Service_SET, ///< The SET (Settings) service | 79 | Service_SET, ///< The SET (Settings) service |
| @@ -79,6 +82,7 @@ enum class Class : ClassType { | |||
| 79 | Service_SSL, ///< The SSL service | 82 | Service_SSL, ///< The SSL service |
| 80 | Service_Time, ///< The time service | 83 | Service_Time, ///< The time service |
| 81 | Service_VI, ///< The VI (Video interface) service | 84 | Service_VI, ///< The VI (Video interface) service |
| 85 | Service_WLAN, ///< The WLAN (Wireless local area network) service | ||
| 82 | HW, ///< Low-level hardware emulation | 86 | HW, ///< Low-level hardware emulation |
| 83 | HW_Memory, ///< Memory-map and address translation | 87 | HW_Memory, ///< Memory-map and address translation |
| 84 | HW_LCD, ///< LCD register emulation | 88 | HW_LCD, ///< LCD register emulation |
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h index c587faefb..9609cec7c 100644 --- a/src/common/logging/text_formatter.h +++ b/src/common/logging/text_formatter.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | 7 | #include <cstddef> |
| 8 | #include <string> | ||
| 8 | 9 | ||
| 9 | namespace Log { | 10 | namespace Log { |
| 10 | 11 | ||
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 1f0456aee..0ca663032 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <cctype> | 6 | #include <cctype> |
| 6 | #include <cerrno> | 7 | #include <cerrno> |
| 7 | #include <cstdio> | 8 | #include <cstdio> |
| 8 | #include <cstdlib> | 9 | #include <cstdlib> |
| 9 | #include <cstring> | 10 | #include <cstring> |
| 10 | #include <boost/range/algorithm/transform.hpp> | ||
| 11 | #include "common/common_paths.h" | 11 | #include "common/common_paths.h" |
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/string_util.h" | 13 | #include "common/string_util.h" |
| @@ -24,13 +24,15 @@ namespace Common { | |||
| 24 | 24 | ||
| 25 | /// Make a string lowercase | 25 | /// Make a string lowercase |
| 26 | std::string ToLower(std::string str) { | 26 | std::string ToLower(std::string str) { |
| 27 | boost::transform(str, str.begin(), ::tolower); | 27 | std::transform(str.begin(), str.end(), str.begin(), |
| 28 | [](unsigned char c) { return std::tolower(c); }); | ||
| 28 | return str; | 29 | return str; |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | /// Make a string uppercase | 32 | /// Make a string uppercase |
| 32 | std::string ToUpper(std::string str) { | 33 | std::string ToUpper(std::string str) { |
| 33 | boost::transform(str, str.begin(), ::toupper); | 34 | std::transform(str.begin(), str.end(), str.begin(), |
| 35 | [](unsigned char c) { return std::toupper(c); }); | ||
| 34 | return str; | 36 | return str; |
| 35 | } | 37 | } |
| 36 | 38 | ||
diff --git a/src/common/swap.h b/src/common/swap.h index fc7af4280..32af0b6ac 100644 --- a/src/common/swap.h +++ b/src/common/swap.h | |||
| @@ -69,7 +69,7 @@ inline u32 swap32(u32 _data) { | |||
| 69 | inline u64 swap64(u64 _data) { | 69 | inline u64 swap64(u64 _data) { |
| 70 | return _byteswap_uint64(_data); | 70 | return _byteswap_uint64(_data); |
| 71 | } | 71 | } |
| 72 | #elif ARCHITECTURE_ARM | 72 | #elif defined(ARCHITECTURE_ARM) && (__ARM_ARCH >= 6) |
| 73 | inline u16 swap16(u16 _data) { | 73 | inline u16 swap16(u16 _data) { |
| 74 | u32 data = _data; | 74 | u32 data = _data; |
| 75 | __asm__("rev16 %0, %1\n" : "=l"(data) : "l"(data)); | 75 | __asm__("rev16 %0, %1\n" : "=l"(data) : "l"(data)); |
diff --git a/src/common/timer.cpp b/src/common/timer.cpp index f0c5b1a43..2dc15e434 100644 --- a/src/common/timer.cpp +++ b/src/common/timer.cpp | |||
| @@ -3,31 +3,16 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <ctime> | 5 | #include <ctime> |
| 6 | |||
| 7 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 8 | |||
| 9 | #ifdef _WIN32 | ||
| 10 | #include <windows.h> | ||
| 11 | // windows.h needs to be included before other windows headers | ||
| 12 | #include <mmsystem.h> | ||
| 13 | #include <sys/timeb.h> | ||
| 14 | #else | ||
| 15 | #include <sys/time.h> | ||
| 16 | #endif | ||
| 17 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 18 | #include "common/string_util.h" | 8 | #include "common/string_util.h" |
| 19 | #include "common/timer.h" | 9 | #include "common/timer.h" |
| 20 | 10 | ||
| 21 | namespace Common { | 11 | namespace Common { |
| 22 | 12 | ||
| 23 | u32 Timer::GetTimeMs() { | 13 | std::chrono::milliseconds Timer::GetTimeMs() { |
| 24 | #ifdef _WIN32 | 14 | return std::chrono::duration_cast<std::chrono::milliseconds>( |
| 25 | return timeGetTime(); | 15 | std::chrono::system_clock::now().time_since_epoch()); |
| 26 | #else | ||
| 27 | struct timeval t; | ||
| 28 | (void)gettimeofday(&t, nullptr); | ||
| 29 | return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000)); | ||
| 30 | #endif | ||
| 31 | } | 16 | } |
| 32 | 17 | ||
| 33 | // -------------------------------------------- | 18 | // -------------------------------------------- |
| @@ -63,7 +48,7 @@ void Timer::Update() { | |||
| 63 | // ------------------------------------- | 48 | // ------------------------------------- |
| 64 | 49 | ||
| 65 | // Get the number of milliseconds since the last Update() | 50 | // Get the number of milliseconds since the last Update() |
| 66 | u64 Timer::GetTimeDifference() { | 51 | std::chrono::milliseconds Timer::GetTimeDifference() { |
| 67 | return GetTimeMs() - m_LastTime; | 52 | return GetTimeMs() - m_LastTime; |
| 68 | } | 53 | } |
| 69 | 54 | ||
| @@ -74,11 +59,11 @@ void Timer::AddTimeDifference() { | |||
| 74 | } | 59 | } |
| 75 | 60 | ||
| 76 | // Get the time elapsed since the Start() | 61 | // Get the time elapsed since the Start() |
| 77 | u64 Timer::GetTimeElapsed() { | 62 | std::chrono::milliseconds Timer::GetTimeElapsed() { |
| 78 | // If we have not started yet, return 1 (because then I don't | 63 | // If we have not started yet, return 1 (because then I don't |
| 79 | // have to change the FPS calculation in CoreRerecording.cpp . | 64 | // have to change the FPS calculation in CoreRerecording.cpp . |
| 80 | if (m_StartTime == 0) | 65 | if (m_StartTime.count() == 0) |
| 81 | return 1; | 66 | return std::chrono::milliseconds(1); |
| 82 | 67 | ||
| 83 | // Return the final timer time if the timer is stopped | 68 | // Return the final timer time if the timer is stopped |
| 84 | if (!m_Running) | 69 | if (!m_Running) |
| @@ -90,49 +75,34 @@ u64 Timer::GetTimeElapsed() { | |||
| 90 | // Get the formatted time elapsed since the Start() | 75 | // Get the formatted time elapsed since the Start() |
| 91 | std::string Timer::GetTimeElapsedFormatted() const { | 76 | std::string Timer::GetTimeElapsedFormatted() const { |
| 92 | // If we have not started yet, return zero | 77 | // If we have not started yet, return zero |
| 93 | if (m_StartTime == 0) | 78 | if (m_StartTime.count() == 0) |
| 94 | return "00:00:00:000"; | 79 | return "00:00:00:000"; |
| 95 | 80 | ||
| 96 | // The number of milliseconds since the start. | 81 | // The number of milliseconds since the start. |
| 97 | // Use a different value if the timer is stopped. | 82 | // Use a different value if the timer is stopped. |
| 98 | u64 Milliseconds; | 83 | std::chrono::milliseconds Milliseconds; |
| 99 | if (m_Running) | 84 | if (m_Running) |
| 100 | Milliseconds = GetTimeMs() - m_StartTime; | 85 | Milliseconds = GetTimeMs() - m_StartTime; |
| 101 | else | 86 | else |
| 102 | Milliseconds = m_LastTime - m_StartTime; | 87 | Milliseconds = m_LastTime - m_StartTime; |
| 103 | // Seconds | 88 | // Seconds |
| 104 | u32 Seconds = (u32)(Milliseconds / 1000); | 89 | std::chrono::seconds Seconds = std::chrono::duration_cast<std::chrono::seconds>(Milliseconds); |
| 105 | // Minutes | 90 | // Minutes |
| 106 | u32 Minutes = Seconds / 60; | 91 | std::chrono::minutes Minutes = std::chrono::duration_cast<std::chrono::minutes>(Milliseconds); |
| 107 | // Hours | 92 | // Hours |
| 108 | u32 Hours = Minutes / 60; | 93 | std::chrono::hours Hours = std::chrono::duration_cast<std::chrono::hours>(Milliseconds); |
| 109 | 94 | ||
| 110 | std::string TmpStr = fmt::format("{:02}:{:02}:{:02}:{:03}", Hours, Minutes % 60, Seconds % 60, | 95 | std::string TmpStr = fmt::format("{:02}:{:02}:{:02}:{:03}", Hours.count(), Minutes.count() % 60, |
| 111 | Milliseconds % 1000); | 96 | Seconds.count() % 60, Milliseconds.count() % 1000); |
| 112 | return TmpStr; | 97 | return TmpStr; |
| 113 | } | 98 | } |
| 114 | 99 | ||
| 115 | // Get current time | ||
| 116 | void Timer::IncreaseResolution() { | ||
| 117 | #ifdef _WIN32 | ||
| 118 | timeBeginPeriod(1); | ||
| 119 | #endif | ||
| 120 | } | ||
| 121 | |||
| 122 | void Timer::RestoreResolution() { | ||
| 123 | #ifdef _WIN32 | ||
| 124 | timeEndPeriod(1); | ||
| 125 | #endif | ||
| 126 | } | ||
| 127 | |||
| 128 | // Get the number of seconds since January 1 1970 | 100 | // Get the number of seconds since January 1 1970 |
| 129 | u64 Timer::GetTimeSinceJan1970() { | 101 | std::chrono::seconds Timer::GetTimeSinceJan1970() { |
| 130 | time_t ltime; | 102 | return std::chrono::duration_cast<std::chrono::seconds>(GetTimeMs()); |
| 131 | time(<ime); | ||
| 132 | return ((u64)ltime); | ||
| 133 | } | 103 | } |
| 134 | 104 | ||
| 135 | u64 Timer::GetLocalTimeSinceJan1970() { | 105 | std::chrono::seconds Timer::GetLocalTimeSinceJan1970() { |
| 136 | time_t sysTime, tzDiff, tzDST; | 106 | time_t sysTime, tzDiff, tzDST; |
| 137 | struct tm* gmTime; | 107 | struct tm* gmTime; |
| 138 | 108 | ||
| @@ -149,7 +119,7 @@ u64 Timer::GetLocalTimeSinceJan1970() { | |||
| 149 | gmTime = gmtime(&sysTime); | 119 | gmTime = gmtime(&sysTime); |
| 150 | tzDiff = sysTime - mktime(gmTime); | 120 | tzDiff = sysTime - mktime(gmTime); |
| 151 | 121 | ||
| 152 | return (u64)(sysTime + tzDiff + tzDST); | 122 | return std::chrono::seconds(sysTime + tzDiff + tzDST); |
| 153 | } | 123 | } |
| 154 | 124 | ||
| 155 | // Return the current time formatted as Minutes:Seconds:Milliseconds | 125 | // Return the current time formatted as Minutes:Seconds:Milliseconds |
| @@ -164,30 +134,16 @@ std::string Timer::GetTimeFormatted() { | |||
| 164 | 134 | ||
| 165 | strftime(tmp, 6, "%M:%S", gmTime); | 135 | strftime(tmp, 6, "%M:%S", gmTime); |
| 166 | 136 | ||
| 167 | // Now tack on the milliseconds | 137 | u64 milliseconds = static_cast<u64>(GetTimeMs().count()) % 1000; |
| 168 | #ifdef _WIN32 | 138 | return fmt::format("{}:{:03}", tmp, milliseconds); |
| 169 | struct timeb tp; | ||
| 170 | (void)::ftime(&tp); | ||
| 171 | return fmt::format("{}:{:03}", tmp, tp.millitm); | ||
| 172 | #else | ||
| 173 | struct timeval t; | ||
| 174 | (void)gettimeofday(&t, nullptr); | ||
| 175 | return fmt::format("{}:{:03}", tmp, static_cast<int>(t.tv_usec / 1000)); | ||
| 176 | #endif | ||
| 177 | } | 139 | } |
| 178 | 140 | ||
| 179 | // Returns a timestamp with decimals for precise time comparisons | 141 | // Returns a timestamp with decimals for precise time comparisons |
| 180 | // ---------------- | 142 | // ---------------- |
| 181 | double Timer::GetDoubleTime() { | 143 | double Timer::GetDoubleTime() { |
| 182 | #ifdef _WIN32 | ||
| 183 | struct timeb tp; | ||
| 184 | (void)::ftime(&tp); | ||
| 185 | #else | ||
| 186 | struct timeval t; | ||
| 187 | (void)gettimeofday(&t, nullptr); | ||
| 188 | #endif | ||
| 189 | // Get continuous timestamp | 144 | // Get continuous timestamp |
| 190 | u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); | 145 | u64 TmpSeconds = static_cast<u64>(Common::Timer::GetTimeSinceJan1970().count()); |
| 146 | double ms = static_cast<u64>(GetTimeMs().count()) % 1000; | ||
| 191 | 147 | ||
| 192 | // Remove a few years. We only really want enough seconds to make | 148 | // Remove a few years. We only really want enough seconds to make |
| 193 | // sure that we are detecting actual actions, perhaps 60 seconds is | 149 | // sure that we are detecting actual actions, perhaps 60 seconds is |
| @@ -196,12 +152,7 @@ double Timer::GetDoubleTime() { | |||
| 196 | TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60); | 152 | TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60); |
| 197 | 153 | ||
| 198 | // Make a smaller integer that fits in the double | 154 | // Make a smaller integer that fits in the double |
| 199 | u32 Seconds = (u32)TmpSeconds; | 155 | u32 Seconds = static_cast<u32>(TmpSeconds); |
| 200 | #ifdef _WIN32 | ||
| 201 | double ms = tp.millitm / 1000.0 / 1000.0; | ||
| 202 | #else | ||
| 203 | double ms = t.tv_usec / 1000000.0; | ||
| 204 | #endif | ||
| 205 | double TmpTime = Seconds + ms; | 156 | double TmpTime = Seconds + ms; |
| 206 | 157 | ||
| 207 | return TmpTime; | 158 | return TmpTime; |
diff --git a/src/common/timer.h b/src/common/timer.h index 78d37426b..27b521baa 100644 --- a/src/common/timer.h +++ b/src/common/timer.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <chrono> | ||
| 7 | #include <string> | 8 | #include <string> |
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | 10 | ||
| @@ -18,24 +19,22 @@ public: | |||
| 18 | 19 | ||
| 19 | // The time difference is always returned in milliseconds, regardless of alternative internal | 20 | // The time difference is always returned in milliseconds, regardless of alternative internal |
| 20 | // representation | 21 | // representation |
| 21 | u64 GetTimeDifference(); | 22 | std::chrono::milliseconds GetTimeDifference(); |
| 22 | void AddTimeDifference(); | 23 | void AddTimeDifference(); |
| 23 | 24 | ||
| 24 | static void IncreaseResolution(); | 25 | static std::chrono::seconds GetTimeSinceJan1970(); |
| 25 | static void RestoreResolution(); | 26 | static std::chrono::seconds GetLocalTimeSinceJan1970(); |
| 26 | static u64 GetTimeSinceJan1970(); | ||
| 27 | static u64 GetLocalTimeSinceJan1970(); | ||
| 28 | static double GetDoubleTime(); | 27 | static double GetDoubleTime(); |
| 29 | 28 | ||
| 30 | static std::string GetTimeFormatted(); | 29 | static std::string GetTimeFormatted(); |
| 31 | std::string GetTimeElapsedFormatted() const; | 30 | std::string GetTimeElapsedFormatted() const; |
| 32 | u64 GetTimeElapsed(); | 31 | std::chrono::milliseconds GetTimeElapsed(); |
| 33 | 32 | ||
| 34 | static u32 GetTimeMs(); | 33 | static std::chrono::milliseconds GetTimeMs(); |
| 35 | 34 | ||
| 36 | private: | 35 | private: |
| 37 | u64 m_LastTime; | 36 | std::chrono::milliseconds m_LastTime; |
| 38 | u64 m_StartTime; | 37 | std::chrono::milliseconds m_StartTime; |
| 39 | bool m_Running; | 38 | bool m_Running; |
| 40 | }; | 39 | }; |
| 41 | 40 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f1e7e2593..3e13fc25b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -114,6 +114,12 @@ add_library(core STATIC | |||
| 114 | hle/service/am/applet_ae.h | 114 | hle/service/am/applet_ae.h |
| 115 | hle/service/am/applet_oe.cpp | 115 | hle/service/am/applet_oe.cpp |
| 116 | hle/service/am/applet_oe.h | 116 | hle/service/am/applet_oe.h |
| 117 | hle/service/am/idle.cpp | ||
| 118 | hle/service/am/idle.h | ||
| 119 | hle/service/am/omm.cpp | ||
| 120 | hle/service/am/omm.h | ||
| 121 | hle/service/am/spsm.cpp | ||
| 122 | hle/service/am/spsm.h | ||
| 117 | hle/service/aoc/aoc_u.cpp | 123 | hle/service/aoc/aoc_u.cpp |
| 118 | hle/service/aoc/aoc_u.h | 124 | hle/service/aoc/aoc_u.h |
| 119 | hle/service/apm/apm.cpp | 125 | hle/service/apm/apm.cpp |
| @@ -142,6 +148,8 @@ add_library(core STATIC | |||
| 142 | hle/service/bcat/module.h | 148 | hle/service/bcat/module.h |
| 143 | hle/service/btdrv/btdrv.cpp | 149 | hle/service/btdrv/btdrv.cpp |
| 144 | hle/service/btdrv/btdrv.h | 150 | hle/service/btdrv/btdrv.h |
| 151 | hle/service/btm/btm.cpp | ||
| 152 | hle/service/btm/btm.h | ||
| 145 | hle/service/erpt/erpt.cpp | 153 | hle/service/erpt/erpt.cpp |
| 146 | hle/service/erpt/erpt.h | 154 | hle/service/erpt/erpt.h |
| 147 | hle/service/es/es.cpp | 155 | hle/service/es/es.cpp |
| @@ -158,6 +166,8 @@ add_library(core STATIC | |||
| 158 | hle/service/filesystem/filesystem.h | 166 | hle/service/filesystem/filesystem.h |
| 159 | hle/service/filesystem/fsp_srv.cpp | 167 | hle/service/filesystem/fsp_srv.cpp |
| 160 | hle/service/filesystem/fsp_srv.h | 168 | hle/service/filesystem/fsp_srv.h |
| 169 | hle/service/fgm/fgm.cpp | ||
| 170 | hle/service/fgm/fgm.h | ||
| 161 | hle/service/friend/friend.cpp | 171 | hle/service/friend/friend.cpp |
| 162 | hle/service/friend/friend.h | 172 | hle/service/friend/friend.h |
| 163 | hle/service/friend/interface.cpp | 173 | hle/service/friend/interface.cpp |
| @@ -223,6 +233,8 @@ add_library(core STATIC | |||
| 223 | hle/service/nvflinger/buffer_queue.h | 233 | hle/service/nvflinger/buffer_queue.h |
| 224 | hle/service/nvflinger/nvflinger.cpp | 234 | hle/service/nvflinger/nvflinger.cpp |
| 225 | hle/service/nvflinger/nvflinger.h | 235 | hle/service/nvflinger/nvflinger.h |
| 236 | hle/service/pcie/pcie.cpp | ||
| 237 | hle/service/pcie/pcie.h | ||
| 226 | hle/service/pctl/module.cpp | 238 | hle/service/pctl/module.cpp |
| 227 | hle/service/pctl/module.h | 239 | hle/service/pctl/module.h |
| 228 | hle/service/pctl/pctl.cpp | 240 | hle/service/pctl/pctl.cpp |
| @@ -277,6 +289,8 @@ add_library(core STATIC | |||
| 277 | hle/service/vi/vi_s.h | 289 | hle/service/vi/vi_s.h |
| 278 | hle/service/vi/vi_u.cpp | 290 | hle/service/vi/vi_u.cpp |
| 279 | hle/service/vi/vi_u.h | 291 | hle/service/vi/vi_u.h |
| 292 | hle/service/wlan/wlan.cpp | ||
| 293 | hle/service/wlan/wlan.h | ||
| 280 | hw/hw.cpp | 294 | hw/hw.cpp |
| 281 | hw/hw.h | 295 | hw/hw.h |
| 282 | hw/lcd.cpp | 296 | hw/lcd.cpp |
| @@ -314,7 +328,7 @@ add_library(core STATIC | |||
| 314 | create_target_directory_groups(core) | 328 | create_target_directory_groups(core) |
| 315 | 329 | ||
| 316 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) | 330 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) |
| 317 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static unicorn) | 331 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static opus unicorn) |
| 318 | 332 | ||
| 319 | if (ARCHITECTURE_x86_64) | 333 | if (ARCHITECTURE_x86_64) |
| 320 | target_sources(core PRIVATE | 334 | target_sources(core PRIVATE |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 57b8634b9..1d8c15d97 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -139,14 +139,12 @@ void ARM_Dynarmic::Step() { | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index) | 141 | ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index) |
| 142 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), | 142 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), core_index{core_index}, |
| 143 | jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>( | 143 | exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(exclusive_monitor)} { |
| 144 | exclusive_monitor)}, | 144 | ThreadContext ctx; |
| 145 | core_index{core_index} { | ||
| 146 | ARM_Interface::ThreadContext ctx; | ||
| 147 | inner_unicorn.SaveContext(ctx); | 145 | inner_unicorn.SaveContext(ctx); |
| 148 | LoadContext(ctx); | ||
| 149 | PageTableChanged(); | 146 | PageTableChanged(); |
| 147 | LoadContext(ctx); | ||
| 150 | } | 148 | } |
| 151 | 149 | ||
| 152 | ARM_Dynarmic::~ARM_Dynarmic() = default; | 150 | ARM_Dynarmic::~ARM_Dynarmic() = default; |
| @@ -205,7 +203,7 @@ u64 ARM_Dynarmic::GetTlsAddress() const { | |||
| 205 | return cb->tpidrro_el0; | 203 | return cb->tpidrro_el0; |
| 206 | } | 204 | } |
| 207 | 205 | ||
| 208 | void ARM_Dynarmic::SetTlsAddress(u64 address) { | 206 | void ARM_Dynarmic::SetTlsAddress(VAddr address) { |
| 209 | cb->tpidrro_el0 = address; | 207 | cb->tpidrro_el0 = address; |
| 210 | } | 208 | } |
| 211 | 209 | ||
| @@ -217,7 +215,7 @@ void ARM_Dynarmic::SetTPIDR_EL0(u64 value) { | |||
| 217 | cb->tpidr_el0 = value; | 215 | cb->tpidr_el0 = value; |
| 218 | } | 216 | } |
| 219 | 217 | ||
| 220 | void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { | 218 | void ARM_Dynarmic::SaveContext(ThreadContext& ctx) { |
| 221 | ctx.cpu_registers = jit->GetRegisters(); | 219 | ctx.cpu_registers = jit->GetRegisters(); |
| 222 | ctx.sp = jit->GetSP(); | 220 | ctx.sp = jit->GetSP(); |
| 223 | ctx.pc = jit->GetPC(); | 221 | ctx.pc = jit->GetPC(); |
| @@ -226,7 +224,7 @@ void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { | |||
| 226 | ctx.fpscr = jit->GetFpcr(); | 224 | ctx.fpscr = jit->GetFpcr(); |
| 227 | } | 225 | } |
| 228 | 226 | ||
| 229 | void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) { | 227 | void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) { |
| 230 | jit->SetRegisters(ctx.cpu_registers); | 228 | jit->SetRegisters(ctx.cpu_registers); |
| 231 | jit->SetSP(ctx.sp); | 229 | jit->SetSP(ctx.sp); |
| 232 | jit->SetPC(ctx.pc); | 230 | jit->SetPC(ctx.pc); |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 186fa46df..b7f4b4532 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -177,7 +177,6 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) { | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | gpu_core = std::make_unique<Tegra::GPU>(); | 179 | gpu_core = std::make_unique<Tegra::GPU>(); |
| 180 | audio_core = std::make_unique<AudioCore::AudioOut>(); | ||
| 181 | telemetry_session = std::make_unique<Core::TelemetrySession>(); | 180 | telemetry_session = std::make_unique<Core::TelemetrySession>(); |
| 182 | service_manager = std::make_shared<Service::SM::ServiceManager>(); | 181 | service_manager = std::make_shared<Service::SM::ServiceManager>(); |
| 183 | 182 | ||
| @@ -229,7 +228,6 @@ void System::Shutdown() { | |||
| 229 | service_manager.reset(); | 228 | service_manager.reset(); |
| 230 | telemetry_session.reset(); | 229 | telemetry_session.reset(); |
| 231 | gpu_core.reset(); | 230 | gpu_core.reset(); |
| 232 | audio_core.reset(); | ||
| 233 | 231 | ||
| 234 | // Close all CPU/threading state | 232 | // Close all CPU/threading state |
| 235 | cpu_barrier->NotifyEnd(); | 233 | cpu_barrier->NotifyEnd(); |
diff --git a/src/core/core.h b/src/core/core.h index 6f4df775f..c123fe401 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <string> | 9 | #include <string> |
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | #include "audio_core/audio_out.h" | ||
| 12 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 13 | #include "core/arm/exclusive_monitor.h" | 12 | #include "core/arm/exclusive_monitor.h" |
| 14 | #include "core/core_cpu.h" | 13 | #include "core/core_cpu.h" |
| @@ -132,11 +131,6 @@ public: | |||
| 132 | return *gpu_core; | 131 | return *gpu_core; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | /// Gets the AudioCore interface | ||
| 136 | AudioCore::AudioOut& AudioCore() { | ||
| 137 | return *audio_core; | ||
| 138 | } | ||
| 139 | |||
| 140 | /// Gets the scheduler for the CPU core that is currently running | 134 | /// Gets the scheduler for the CPU core that is currently running |
| 141 | Kernel::Scheduler& CurrentScheduler() { | 135 | Kernel::Scheduler& CurrentScheduler() { |
| 142 | return *CurrentCpuCore().Scheduler(); | 136 | return *CurrentCpuCore().Scheduler(); |
| @@ -201,7 +195,6 @@ private: | |||
| 201 | /// AppLoader used to load the current executing application | 195 | /// AppLoader used to load the current executing application |
| 202 | std::unique_ptr<Loader::AppLoader> app_loader; | 196 | std::unique_ptr<Loader::AppLoader> app_loader; |
| 203 | std::unique_ptr<Tegra::GPU> gpu_core; | 197 | std::unique_ptr<Tegra::GPU> gpu_core; |
| 204 | std::unique_ptr<AudioCore::AudioOut> audio_core; | ||
| 205 | std::shared_ptr<Tegra::DebugContext> debug_context; | 198 | std::shared_ptr<Tegra::DebugContext> debug_context; |
| 206 | Kernel::SharedPtr<Kernel::Process> current_process; | 199 | Kernel::SharedPtr<Kernel::Process> current_process; |
| 207 | std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; | 200 | std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor; |
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp index 521e21078..47e032b19 100644 --- a/src/core/file_sys/partition_filesystem.cpp +++ b/src/core/file_sys/partition_filesystem.cpp | |||
| @@ -97,9 +97,8 @@ void PartitionFilesystem::PrintDebugInfo() const { | |||
| 97 | LOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic); | 97 | LOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic); |
| 98 | LOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries); | 98 | LOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries); |
| 99 | for (u32 i = 0; i < pfs_header.num_entries; i++) { | 99 | for (u32 i = 0; i < pfs_header.num_entries; i++) { |
| 100 | LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes, at 0x{:X})", i, | 100 | LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes)", i, |
| 101 | pfs_files[i]->GetName(), pfs_files[i]->GetSize(), | 101 | pfs_files[i]->GetName(), pfs_files[i]->GetSize()); |
| 102 | dynamic_cast<OffsetVfsFile*>(pfs_files[i].get())->GetOffset()); | ||
| 103 | } | 102 | } |
| 104 | } | 103 | } |
| 105 | 104 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 97ef07bf9..94d2a973d 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -11,6 +11,9 @@ | |||
| 11 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 12 | #include "core/hle/service/am/applet_ae.h" | 12 | #include "core/hle/service/am/applet_ae.h" |
| 13 | #include "core/hle/service/am/applet_oe.h" | 13 | #include "core/hle/service/am/applet_oe.h" |
| 14 | #include "core/hle/service/am/idle.h" | ||
| 15 | #include "core/hle/service/am/omm.h" | ||
| 16 | #include "core/hle/service/am/spsm.h" | ||
| 14 | #include "core/hle/service/apm/apm.h" | 17 | #include "core/hle/service/apm/apm.h" |
| 15 | #include "core/hle/service/filesystem/filesystem.h" | 18 | #include "core/hle/service/filesystem/filesystem.h" |
| 16 | #include "core/hle/service/nvflinger/nvflinger.h" | 19 | #include "core/hle/service/nvflinger/nvflinger.h" |
| @@ -689,6 +692,9 @@ void InstallInterfaces(SM::ServiceManager& service_manager, | |||
| 689 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger) { | 692 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger) { |
| 690 | std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager); | 693 | std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager); |
| 691 | std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager); | 694 | std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager); |
| 695 | std::make_shared<IdleSys>()->InstallAsService(service_manager); | ||
| 696 | std::make_shared<OMM>()->InstallAsService(service_manager); | ||
| 697 | std::make_shared<SPSM>()->InstallAsService(service_manager); | ||
| 692 | } | 698 | } |
| 693 | 699 | ||
| 694 | IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") { | 700 | IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") { |
diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp new file mode 100644 index 000000000..af46e9494 --- /dev/null +++ b/src/core/hle/service/am/idle.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/am/idle.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | IdleSys::IdleSys() : ServiceFramework{"idle:sys"} { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {0, nullptr, "GetAutoPowerDownEvent"}, | ||
| 13 | {1, nullptr, "Unknown1"}, | ||
| 14 | {2, nullptr, "Unknown2"}, | ||
| 15 | {3, nullptr, "Unknown3"}, | ||
| 16 | {4, nullptr, "Unknown4"}, | ||
| 17 | {5, nullptr, "Unknown5"}, | ||
| 18 | }; | ||
| 19 | // clang-format on | ||
| 20 | |||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h new file mode 100644 index 000000000..1eb68d2c9 --- /dev/null +++ b/src/core/hle/service/am/idle.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class IdleSys final : public ServiceFramework<IdleSys> { | ||
| 12 | public: | ||
| 13 | explicit IdleSys(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp new file mode 100644 index 000000000..447fe8669 --- /dev/null +++ b/src/core/hle/service/am/omm.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/am/omm.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | OMM::OMM() : ServiceFramework{"omm"} { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {0, nullptr, "GetOperationMode"}, | ||
| 13 | {1, nullptr, "GetOperationModeChangeEvent"}, | ||
| 14 | {2, nullptr, "EnableAudioVisual"}, | ||
| 15 | {3, nullptr, "DisableAudioVisual"}, | ||
| 16 | {4, nullptr, "EnterSleepAndWait"}, | ||
| 17 | {5, nullptr, "GetCradleStatus"}, | ||
| 18 | {6, nullptr, "FadeInDisplay"}, | ||
| 19 | {7, nullptr, "FadeOutDisplay"}, | ||
| 20 | {8, nullptr, "Unknown1"}, | ||
| 21 | {9, nullptr, "Unknown2"}, | ||
| 22 | {10, nullptr, "Unknown3"}, | ||
| 23 | {11, nullptr, "Unknown4"}, | ||
| 24 | {12, nullptr, "Unknown5"}, | ||
| 25 | {13, nullptr, "Unknown6"}, | ||
| 26 | {14, nullptr, "Unknown7"}, | ||
| 27 | {15, nullptr, "Unknown8"}, | ||
| 28 | {16, nullptr, "Unknown9"}, | ||
| 29 | {17, nullptr, "Unknown10"}, | ||
| 30 | {18, nullptr, "Unknown11"}, | ||
| 31 | {19, nullptr, "Unknown12"}, | ||
| 32 | {20, nullptr, "Unknown13"}, | ||
| 33 | {21, nullptr, "Unknown14"}, | ||
| 34 | {22, nullptr, "Unknown15"}, | ||
| 35 | {23, nullptr, "Unknown16"}, | ||
| 36 | }; | ||
| 37 | // clang-format on | ||
| 38 | |||
| 39 | RegisterHandlers(functions); | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h new file mode 100644 index 000000000..49e5d331c --- /dev/null +++ b/src/core/hle/service/am/omm.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class OMM final : public ServiceFramework<OMM> { | ||
| 12 | public: | ||
| 13 | explicit OMM(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp new file mode 100644 index 000000000..a05d433d0 --- /dev/null +++ b/src/core/hle/service/am/spsm.cpp | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/am/spsm.h" | ||
| 6 | |||
| 7 | namespace Service::AM { | ||
| 8 | |||
| 9 | SPSM::SPSM() : ServiceFramework{"spsm"} { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {0, nullptr, "GetState"}, | ||
| 13 | {1, nullptr, "SleepSystemAndWaitAwake"}, | ||
| 14 | {2, nullptr, "Unknown1"}, | ||
| 15 | {3, nullptr, "Unknown2"}, | ||
| 16 | {4, nullptr, "GetNotificationMessageEventHandle"}, | ||
| 17 | {5, nullptr, "Unknown3"}, | ||
| 18 | {6, nullptr, "Unknown4"}, | ||
| 19 | {7, nullptr, "Unknown5"}, | ||
| 20 | {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, | ||
| 21 | {9, nullptr, "ChangeHomeButtonLongPressingTime"}, | ||
| 22 | {10, nullptr, "Unknown6"}, | ||
| 23 | {11, nullptr, "Unknown7"}, | ||
| 24 | }; | ||
| 25 | // clang-format on | ||
| 26 | |||
| 27 | RegisterHandlers(functions); | ||
| 28 | } | ||
| 29 | |||
| 30 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h new file mode 100644 index 000000000..57dde62e1 --- /dev/null +++ b/src/core/hle/service/am/spsm.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::AM { | ||
| 10 | |||
| 11 | class SPSM final : public ServiceFramework<SPSM> { | ||
| 12 | public: | ||
| 13 | explicit SPSM(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | } // namespace Service::AM | ||
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index a15d53ff8..ab37c2a69 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -25,9 +25,8 @@ constexpr int DefaultSampleRate{48000}; | |||
| 25 | 25 | ||
| 26 | class IAudioOut final : public ServiceFramework<IAudioOut> { | 26 | class IAudioOut final : public ServiceFramework<IAudioOut> { |
| 27 | public: | 27 | public: |
| 28 | IAudioOut(AudoutParams audio_params) | 28 | IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core) |
| 29 | : ServiceFramework("IAudioOut"), audio_params(audio_params), | 29 | : ServiceFramework("IAudioOut"), audio_params(audio_params), audio_core(audio_core) { |
| 30 | audio_core(Core::System::GetInstance().AudioCore()) { | ||
| 31 | 30 | ||
| 32 | static const FunctionInfo functions[] = { | 31 | static const FunctionInfo functions[] = { |
| 33 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 32 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
| @@ -195,7 +194,7 @@ void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) { | |||
| 195 | // TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl | 194 | // TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl |
| 196 | // will likely need to be updated as well. | 195 | // will likely need to be updated as well. |
| 197 | ASSERT_MSG(!audio_out_interface, "Unimplemented"); | 196 | ASSERT_MSG(!audio_out_interface, "Unimplemented"); |
| 198 | audio_out_interface = std::make_shared<IAudioOut>(std::move(params)); | 197 | audio_out_interface = std::make_shared<IAudioOut>(std::move(params), *audio_core); |
| 199 | 198 | ||
| 200 | IPC::ResponseBuilder rb{ctx, 6, 0, 1}; | 199 | IPC::ResponseBuilder rb{ctx, 6, 0, 1}; |
| 201 | rb.Push(RESULT_SUCCESS); | 200 | rb.Push(RESULT_SUCCESS); |
| @@ -212,6 +211,7 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") { | |||
| 212 | {2, &AudOutU::ListAudioOutsImpl, "ListAudioOutsAuto"}, | 211 | {2, &AudOutU::ListAudioOutsImpl, "ListAudioOutsAuto"}, |
| 213 | {3, &AudOutU::OpenAudioOutImpl, "OpenAudioOutAuto"}}; | 212 | {3, &AudOutU::OpenAudioOutImpl, "OpenAudioOutAuto"}}; |
| 214 | RegisterHandlers(functions); | 213 | RegisterHandlers(functions); |
| 214 | audio_core = std::make_unique<AudioCore::AudioOut>(); | ||
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | } // namespace Service::Audio | 217 | } // namespace Service::Audio |
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h index bc43f1f44..e5c2184d5 100644 --- a/src/core/hle/service/audio/audout_u.h +++ b/src/core/hle/service/audio/audout_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "audio_core/audio_out.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Kernel { | 10 | namespace Kernel { |
| @@ -33,6 +34,7 @@ public: | |||
| 33 | 34 | ||
| 34 | private: | 35 | private: |
| 35 | std::shared_ptr<IAudioOut> audio_out_interface; | 36 | std::shared_ptr<IAudioOut> audio_out_interface; |
| 37 | std::unique_ptr<AudioCore::AudioOut> audio_core; | ||
| 36 | 38 | ||
| 37 | void ListAudioOutsImpl(Kernel::HLERequestContext& ctx); | 39 | void ListAudioOutsImpl(Kernel::HLERequestContext& ctx); |
| 38 | void OpenAudioOutImpl(Kernel::HLERequestContext& ctx); | 40 | void OpenAudioOutImpl(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 844df382c..371cd4997 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | ||
| 6 | #include <opus.h> | ||
| 5 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/hle_ipc.h" | 9 | #include "core/hle/kernel/hle_ipc.h" |
| @@ -9,19 +11,142 @@ | |||
| 9 | 11 | ||
| 10 | namespace Service::Audio { | 12 | namespace Service::Audio { |
| 11 | 13 | ||
| 14 | struct OpusDeleter { | ||
| 15 | void operator()(void* ptr) const { | ||
| 16 | operator delete(ptr); | ||
| 17 | } | ||
| 18 | }; | ||
| 19 | |||
| 20 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { | ||
| 21 | public: | ||
| 22 | IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate, | ||
| 23 | u32 channel_count) | ||
| 24 | : ServiceFramework("IHardwareOpusDecoderManager"), decoder(std::move(decoder)), | ||
| 25 | sample_rate(sample_rate), channel_count(channel_count) { | ||
| 26 | static const FunctionInfo functions[] = { | ||
| 27 | {0, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, | ||
| 28 | {1, nullptr, "SetContext"}, | ||
| 29 | {2, nullptr, "DecodeInterleavedForMultiStream"}, | ||
| 30 | {3, nullptr, "SetContextForMultiStream"}, | ||
| 31 | {4, nullptr, "Unknown4"}, | ||
| 32 | {5, nullptr, "Unknown5"}, | ||
| 33 | {6, nullptr, "Unknown6"}, | ||
| 34 | {7, nullptr, "Unknown7"}, | ||
| 35 | }; | ||
| 36 | RegisterHandlers(functions); | ||
| 37 | } | ||
| 38 | |||
| 39 | private: | ||
| 40 | void DecodeInterleaved(Kernel::HLERequestContext& ctx) { | ||
| 41 | u32 consumed = 0; | ||
| 42 | u32 sample_count = 0; | ||
| 43 | std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16)); | ||
| 44 | if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples)) { | ||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | // TODO(ogniK): Use correct error code | ||
| 47 | rb.Push(ResultCode(-1)); | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 51 | rb.Push(RESULT_SUCCESS); | ||
| 52 | rb.Push<u32>(consumed); | ||
| 53 | rb.Push<u32>(sample_count); | ||
| 54 | ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16)); | ||
| 55 | } | ||
| 56 | |||
| 57 | bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input, | ||
| 58 | std::vector<opus_int16>& output) { | ||
| 59 | size_t raw_output_sz = output.size() * sizeof(opus_int16); | ||
| 60 | if (sizeof(OpusHeader) > input.size()) | ||
| 61 | return false; | ||
| 62 | OpusHeader hdr{}; | ||
| 63 | std::memcpy(&hdr, input.data(), sizeof(OpusHeader)); | ||
| 64 | if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) { | ||
| 65 | return false; | ||
| 66 | } | ||
| 67 | auto frame = input.data() + sizeof(OpusHeader); | ||
| 68 | auto decoded_sample_count = opus_packet_get_nb_samples( | ||
| 69 | frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)), | ||
| 70 | static_cast<opus_int32>(sample_rate)); | ||
| 71 | if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz) | ||
| 72 | return false; | ||
| 73 | auto out_sample_count = | ||
| 74 | opus_decode(decoder.get(), frame, hdr.sz, output.data(), | ||
| 75 | (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0); | ||
| 76 | if (out_sample_count < 0) | ||
| 77 | return false; | ||
| 78 | sample_count = out_sample_count; | ||
| 79 | consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz); | ||
| 80 | return true; | ||
| 81 | } | ||
| 82 | |||
| 83 | struct OpusHeader { | ||
| 84 | u32_be sz; // Needs to be BE for some odd reason | ||
| 85 | INSERT_PADDING_WORDS(1); | ||
| 86 | }; | ||
| 87 | static_assert(sizeof(OpusHeader) == 0x8, "OpusHeader is an invalid size"); | ||
| 88 | |||
| 89 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder; | ||
| 90 | u32 sample_rate; | ||
| 91 | u32 channel_count; | ||
| 92 | }; | ||
| 93 | |||
| 94 | static size_t WorkerBufferSize(u32 channel_count) { | ||
| 95 | ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); | ||
| 96 | return opus_decoder_get_size(static_cast<int>(channel_count)); | ||
| 97 | } | ||
| 98 | |||
| 12 | void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { | 99 | void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { |
| 13 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 100 | IPC::RequestParser rp{ctx}; |
| 101 | auto sample_rate = rp.Pop<u32>(); | ||
| 102 | auto channel_count = rp.Pop<u32>(); | ||
| 103 | ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 || | ||
| 104 | sample_rate == 12000 || sample_rate == 8000, | ||
| 105 | "Invalid sample rate"); | ||
| 106 | ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); | ||
| 107 | u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count)); | ||
| 108 | LOG_DEBUG(Audio, "called worker_buffer_sz={}", worker_buffer_sz); | ||
| 109 | |||
| 14 | IPC::ResponseBuilder rb{ctx, 3}; | 110 | IPC::ResponseBuilder rb{ctx, 3}; |
| 15 | rb.Push(RESULT_SUCCESS); | 111 | rb.Push(RESULT_SUCCESS); |
| 16 | rb.Push<u32>(0x4000); | 112 | rb.Push<u32>(worker_buffer_sz); |
| 113 | } | ||
| 114 | |||
| 115 | void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) { | ||
| 116 | IPC::RequestParser rp{ctx}; | ||
| 117 | auto sample_rate = rp.Pop<u32>(); | ||
| 118 | auto channel_count = rp.Pop<u32>(); | ||
| 119 | auto buffer_sz = rp.Pop<u32>(); | ||
| 120 | LOG_DEBUG(Audio, "called sample_rate={}, channel_count={}, buffer_size={}", sample_rate, | ||
| 121 | channel_count, buffer_sz); | ||
| 122 | ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 || | ||
| 123 | sample_rate == 12000 || sample_rate == 8000, | ||
| 124 | "Invalid sample rate"); | ||
| 125 | ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count"); | ||
| 126 | |||
| 127 | size_t worker_sz = WorkerBufferSize(channel_count); | ||
| 128 | ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large"); | ||
| 129 | std::unique_ptr<OpusDecoder, OpusDeleter> decoder{ | ||
| 130 | static_cast<OpusDecoder*>(operator new(worker_sz))}; | ||
| 131 | if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) { | ||
| 132 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 133 | // TODO(ogniK): Use correct error code | ||
| 134 | rb.Push(ResultCode(-1)); | ||
| 135 | return; | ||
| 136 | } | ||
| 137 | |||
| 138 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 139 | rb.Push(RESULT_SUCCESS); | ||
| 140 | rb.PushIpcInterface<IHardwareOpusDecoderManager>(std::move(decoder), sample_rate, | ||
| 141 | channel_count); | ||
| 17 | } | 142 | } |
| 18 | 143 | ||
| 19 | HwOpus::HwOpus() : ServiceFramework("hwopus") { | 144 | HwOpus::HwOpus() : ServiceFramework("hwopus") { |
| 20 | static const FunctionInfo functions[] = { | 145 | static const FunctionInfo functions[] = { |
| 21 | {0, nullptr, "Initialize"}, | 146 | {0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"}, |
| 22 | {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, | 147 | {1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"}, |
| 23 | {2, nullptr, "InitializeMultiStream"}, | 148 | {2, nullptr, "OpenOpusDecoderForMultiStream"}, |
| 24 | {3, nullptr, "GetWorkBufferSizeMultiStream"}, | 149 | {3, nullptr, "GetWorkBufferSizeForMultiStream"}, |
| 25 | }; | 150 | }; |
| 26 | RegisterHandlers(functions); | 151 | RegisterHandlers(functions); |
| 27 | } | 152 | } |
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h index 090b8c825..5258d59f3 100644 --- a/src/core/hle/service/audio/hwopus.h +++ b/src/core/hle/service/audio/hwopus.h | |||
| @@ -14,6 +14,7 @@ public: | |||
| 14 | ~HwOpus() = default; | 14 | ~HwOpus() = default; |
| 15 | 15 | ||
| 16 | private: | 16 | private: |
| 17 | void OpenOpusDecoder(Kernel::HLERequestContext& ctx); | ||
| 17 | void GetWorkBufferSize(Kernel::HLERequestContext& ctx); | 18 | void GetWorkBufferSize(Kernel::HLERequestContext& ctx); |
| 18 | }; | 19 | }; |
| 19 | 20 | ||
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp new file mode 100644 index 000000000..b949bfabd --- /dev/null +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <memory> | ||
| 6 | |||
| 7 | #include "common/logging/log.h" | ||
| 8 | #include "core/hle/ipc_helpers.h" | ||
| 9 | #include "core/hle/kernel/hle_ipc.h" | ||
| 10 | #include "core/hle/service/btm/btm.h" | ||
| 11 | #include "core/hle/service/service.h" | ||
| 12 | #include "core/hle/service/sm/sm.h" | ||
| 13 | |||
| 14 | namespace Service::BTM { | ||
| 15 | |||
| 16 | class BTM final : public ServiceFramework<BTM> { | ||
| 17 | public: | ||
| 18 | explicit BTM() : ServiceFramework{"btm"} { | ||
| 19 | // clang-format off | ||
| 20 | static const FunctionInfo functions[] = { | ||
| 21 | {0, nullptr, "Unknown1"}, | ||
| 22 | {1, nullptr, "Unknown2"}, | ||
| 23 | {2, nullptr, "RegisterSystemEventForConnectedDeviceConditionImpl"}, | ||
| 24 | {3, nullptr, "Unknown3"}, | ||
| 25 | {4, nullptr, "Unknown4"}, | ||
| 26 | {5, nullptr, "Unknown5"}, | ||
| 27 | {6, nullptr, "Unknown6"}, | ||
| 28 | {7, nullptr, "Unknown7"}, | ||
| 29 | {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfoImpl"}, | ||
| 30 | {9, nullptr, "Unknown8"}, | ||
| 31 | {10, nullptr, "Unknown9"}, | ||
| 32 | {11, nullptr, "Unknown10"}, | ||
| 33 | {12, nullptr, "Unknown11"}, | ||
| 34 | {13, nullptr, "Unknown12"}, | ||
| 35 | {14, nullptr, "EnableRadioImpl"}, | ||
| 36 | {15, nullptr, "DisableRadioImpl"}, | ||
| 37 | {16, nullptr, "Unknown13"}, | ||
| 38 | {17, nullptr, "Unknown14"}, | ||
| 39 | {18, nullptr, "Unknown15"}, | ||
| 40 | {19, nullptr, "Unknown16"}, | ||
| 41 | {20, nullptr, "Unknown17"}, | ||
| 42 | {21, nullptr, "Unknown18"}, | ||
| 43 | }; | ||
| 44 | // clang-format on | ||
| 45 | |||
| 46 | RegisterHandlers(functions); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | |||
| 50 | class BTM_DBG final : public ServiceFramework<BTM_DBG> { | ||
| 51 | public: | ||
| 52 | explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { | ||
| 53 | // clang-format off | ||
| 54 | static const FunctionInfo functions[] = { | ||
| 55 | {0, nullptr, "RegisterSystemEventForDiscoveryImpl"}, | ||
| 56 | {1, nullptr, "Unknown1"}, | ||
| 57 | {2, nullptr, "Unknown2"}, | ||
| 58 | {3, nullptr, "Unknown3"}, | ||
| 59 | {4, nullptr, "Unknown4"}, | ||
| 60 | {5, nullptr, "Unknown5"}, | ||
| 61 | {6, nullptr, "Unknown6"}, | ||
| 62 | {7, nullptr, "Unknown7"}, | ||
| 63 | {8, nullptr, "Unknown8"}, | ||
| 64 | }; | ||
| 65 | // clang-format on | ||
| 66 | |||
| 67 | RegisterHandlers(functions); | ||
| 68 | } | ||
| 69 | }; | ||
| 70 | |||
| 71 | class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> { | ||
| 72 | public: | ||
| 73 | explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} { | ||
| 74 | // clang-format off | ||
| 75 | static const FunctionInfo functions[] = { | ||
| 76 | {0, nullptr, "StartGamepadPairingImpl"}, | ||
| 77 | {1, nullptr, "CancelGamepadPairingImpl"}, | ||
| 78 | {2, nullptr, "ClearGamepadPairingDatabaseImpl"}, | ||
| 79 | {3, nullptr, "GetPairedGamepadCountImpl"}, | ||
| 80 | {4, nullptr, "EnableRadioImpl"}, | ||
| 81 | {5, nullptr, "DisableRadioImpl"}, | ||
| 82 | {6, nullptr, "GetRadioOnOffImpl"}, | ||
| 83 | {7, nullptr, "AcquireRadioEventImpl"}, | ||
| 84 | {8, nullptr, "AcquireGamepadPairingEventImpl"}, | ||
| 85 | {9, nullptr, "IsGamepadPairingStartedImpl"}, | ||
| 86 | }; | ||
| 87 | // clang-format on | ||
| 88 | |||
| 89 | RegisterHandlers(functions); | ||
| 90 | } | ||
| 91 | }; | ||
| 92 | |||
| 93 | class BTM_SYS final : public ServiceFramework<BTM_SYS> { | ||
| 94 | public: | ||
| 95 | explicit BTM_SYS() : ServiceFramework{"btm:sys"} { | ||
| 96 | // clang-format off | ||
| 97 | static const FunctionInfo functions[] = { | ||
| 98 | {0, &BTM_SYS::GetCoreImpl, "GetCoreImpl"}, | ||
| 99 | }; | ||
| 100 | // clang-format on | ||
| 101 | |||
| 102 | RegisterHandlers(functions); | ||
| 103 | } | ||
| 104 | |||
| 105 | private: | ||
| 106 | void GetCoreImpl(Kernel::HLERequestContext& ctx) { | ||
| 107 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 108 | rb.Push(RESULT_SUCCESS); | ||
| 109 | rb.PushIpcInterface<IBtmSystemCore>(); | ||
| 110 | |||
| 111 | LOG_DEBUG(Service_BTM, "called"); | ||
| 112 | } | ||
| 113 | }; | ||
| 114 | |||
| 115 | void InstallInterfaces(SM::ServiceManager& sm) { | ||
| 116 | std::make_shared<BTM>()->InstallAsService(sm); | ||
| 117 | std::make_shared<BTM_DBG>()->InstallAsService(sm); | ||
| 118 | std::make_shared<BTM_SYS>()->InstallAsService(sm); | ||
| 119 | } | ||
| 120 | |||
| 121 | } // namespace Service::BTM | ||
diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h new file mode 100644 index 000000000..e6425a7e3 --- /dev/null +++ b/src/core/hle/service/btm/btm.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Service::SM { | ||
| 8 | class ServiceManager; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::BTM { | ||
| 12 | |||
| 13 | void InstallInterfaces(SM::ServiceManager& sm); | ||
| 14 | |||
| 15 | } // namespace Service::BTM | ||
diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp new file mode 100644 index 000000000..566fbf924 --- /dev/null +++ b/src/core/hle/service/fgm/fgm.cpp | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <memory> | ||
| 6 | |||
| 7 | #include "core/hle/ipc_helpers.h" | ||
| 8 | #include "core/hle/kernel/hle_ipc.h" | ||
| 9 | #include "core/hle/service/fgm/fgm.h" | ||
| 10 | #include "core/hle/service/service.h" | ||
| 11 | #include "core/hle/service/sm/sm.h" | ||
| 12 | |||
| 13 | namespace Service::FGM { | ||
| 14 | |||
| 15 | class IRequest final : public ServiceFramework<IRequest> { | ||
| 16 | public: | ||
| 17 | explicit IRequest() : ServiceFramework{"IRequest"} { | ||
| 18 | // clang-format off | ||
| 19 | static const FunctionInfo functions[] = { | ||
| 20 | {0, nullptr, "Initialize"}, | ||
| 21 | {1, nullptr, "Set"}, | ||
| 22 | {2, nullptr, "Get"}, | ||
| 23 | {3, nullptr, "Cancel"}, | ||
| 24 | }; | ||
| 25 | // clang-format on | ||
| 26 | |||
| 27 | RegisterHandlers(functions); | ||
| 28 | } | ||
| 29 | }; | ||
| 30 | |||
| 31 | class FGM final : public ServiceFramework<FGM> { | ||
| 32 | public: | ||
| 33 | explicit FGM(const char* name) : ServiceFramework{name} { | ||
| 34 | // clang-format off | ||
| 35 | static const FunctionInfo functions[] = { | ||
| 36 | {0, &FGM::Initialize, "Initialize"}, | ||
| 37 | }; | ||
| 38 | // clang-format on | ||
| 39 | |||
| 40 | RegisterHandlers(functions); | ||
| 41 | } | ||
| 42 | |||
| 43 | private: | ||
| 44 | void Initialize(Kernel::HLERequestContext& ctx) { | ||
| 45 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 46 | rb.Push(RESULT_SUCCESS); | ||
| 47 | rb.PushIpcInterface<IRequest>(); | ||
| 48 | |||
| 49 | LOG_DEBUG(Service_FGM, "called"); | ||
| 50 | } | ||
| 51 | }; | ||
| 52 | |||
| 53 | class FGM_DBG final : public ServiceFramework<FGM_DBG> { | ||
| 54 | public: | ||
| 55 | explicit FGM_DBG() : ServiceFramework{"fgm:dbg"} { | ||
| 56 | // clang-format off | ||
| 57 | static const FunctionInfo functions[] = { | ||
| 58 | {0, nullptr, "Initialize"}, | ||
| 59 | {1, nullptr, "Read"}, | ||
| 60 | {2, nullptr, "Cancel"}, | ||
| 61 | }; | ||
| 62 | // clang-format on | ||
| 63 | |||
| 64 | RegisterHandlers(functions); | ||
| 65 | } | ||
| 66 | }; | ||
| 67 | |||
| 68 | void InstallInterfaces(SM::ServiceManager& sm) { | ||
| 69 | std::make_shared<FGM>("fgm")->InstallAsService(sm); | ||
| 70 | std::make_shared<FGM>("fgm:0")->InstallAsService(sm); | ||
| 71 | std::make_shared<FGM>("fgm:9")->InstallAsService(sm); | ||
| 72 | std::make_shared<FGM_DBG>()->InstallAsService(sm); | ||
| 73 | } | ||
| 74 | |||
| 75 | } // namespace Service::FGM | ||
diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h new file mode 100644 index 000000000..e59691264 --- /dev/null +++ b/src/core/hle/service/fgm/fgm.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Service::SM { | ||
| 8 | class ServiceManager; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::FGM { | ||
| 12 | |||
| 13 | void InstallInterfaces(SM::ServiceManager& sm); | ||
| 14 | |||
| 15 | } // namespace Service::FGM | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e4619a547..ed53f96c5 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -326,7 +326,7 @@ public: | |||
| 326 | {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, | 326 | {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, |
| 327 | {80, nullptr, "GetGyroscopeZeroDriftMode"}, | 327 | {80, nullptr, "GetGyroscopeZeroDriftMode"}, |
| 328 | {81, nullptr, "ResetGyroscopeZeroDriftMode"}, | 328 | {81, nullptr, "ResetGyroscopeZeroDriftMode"}, |
| 329 | {82, nullptr, "IsSixAxisSensorAtRest"}, | 329 | {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, |
| 330 | {91, nullptr, "ActivateGesture"}, | 330 | {91, nullptr, "ActivateGesture"}, |
| 331 | {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, | 331 | {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"}, |
| 332 | {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, | 332 | {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"}, |
| @@ -343,7 +343,7 @@ public: | |||
| 343 | "SetNpadJoyAssignmentModeSingleByDefault"}, | 343 | "SetNpadJoyAssignmentModeSingleByDefault"}, |
| 344 | {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, | 344 | {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, |
| 345 | {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, | 345 | {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, |
| 346 | {125, nullptr, "MergeSingleJoyAsDualJoy"}, | 346 | {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"}, |
| 347 | {126, nullptr, "StartLrAssignmentMode"}, | 347 | {126, nullptr, "StartLrAssignmentMode"}, |
| 348 | {127, nullptr, "StopLrAssignmentMode"}, | 348 | {127, nullptr, "StopLrAssignmentMode"}, |
| 349 | {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, | 349 | {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, |
| @@ -455,6 +455,14 @@ private: | |||
| 455 | LOG_WARNING(Service_HID, "(STUBBED) called"); | 455 | LOG_WARNING(Service_HID, "(STUBBED) called"); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) { | ||
| 459 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 460 | rb.Push(RESULT_SUCCESS); | ||
| 461 | // TODO (Hexagon12): Properly implement reading gyroscope values from controllers. | ||
| 462 | rb.Push(true); | ||
| 463 | LOG_WARNING(Service_HID, "(STUBBED) called"); | ||
| 464 | } | ||
| 465 | |||
| 458 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { | 466 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { |
| 459 | IPC::ResponseBuilder rb{ctx, 2}; | 467 | IPC::ResponseBuilder rb{ctx, 2}; |
| 460 | rb.Push(RESULT_SUCCESS); | 468 | rb.Push(RESULT_SUCCESS); |
| @@ -530,6 +538,12 @@ private: | |||
| 530 | LOG_WARNING(Service_HID, "(STUBBED) called"); | 538 | LOG_WARNING(Service_HID, "(STUBBED) called"); |
| 531 | } | 539 | } |
| 532 | 540 | ||
| 541 | void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { | ||
| 542 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 543 | rb.Push(RESULT_SUCCESS); | ||
| 544 | LOG_WARNING(Service_HID, "(STUBBED) called"); | ||
| 545 | } | ||
| 546 | |||
| 533 | void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { | 547 | void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { |
| 534 | IPC::ResponseBuilder rb{ctx, 2}; | 548 | IPC::ResponseBuilder rb{ctx, 2}; |
| 535 | rb.Push(RESULT_SUCCESS); | 549 | rb.Push(RESULT_SUCCESS); |
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 44e062f50..010072a5b 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | |||
| @@ -97,7 +97,9 @@ u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& | |||
| 97 | u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { | 97 | u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { |
| 98 | LOG_DEBUG(Service_NVDRV, "called"); | 98 | LOG_DEBUG(Service_NVDRV, "called"); |
| 99 | IoctlActiveSlotMask params{}; | 99 | IoctlActiveSlotMask params{}; |
| 100 | std::memcpy(¶ms, input.data(), input.size()); | 100 | if (input.size() > 0) { |
| 101 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 102 | } | ||
| 101 | params.slot = 0x07; | 103 | params.slot = 0x07; |
| 102 | params.mask = 0x01; | 104 | params.mask = 0x01; |
| 103 | std::memcpy(output.data(), ¶ms, output.size()); | 105 | std::memcpy(output.data(), ¶ms, output.size()); |
| @@ -107,7 +109,9 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector | |||
| 107 | u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { | 109 | u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { |
| 108 | LOG_DEBUG(Service_NVDRV, "called"); | 110 | LOG_DEBUG(Service_NVDRV, "called"); |
| 109 | IoctlZcullGetCtxSize params{}; | 111 | IoctlZcullGetCtxSize params{}; |
| 110 | std::memcpy(¶ms, input.data(), input.size()); | 112 | if (input.size() > 0) { |
| 113 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 114 | } | ||
| 111 | params.size = 0x1; | 115 | params.size = 0x1; |
| 112 | std::memcpy(output.data(), ¶ms, output.size()); | 116 | std::memcpy(output.data(), ¶ms, output.size()); |
| 113 | return 0; | 117 | return 0; |
| @@ -116,7 +120,11 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u | |||
| 116 | u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { | 120 | u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { |
| 117 | LOG_DEBUG(Service_NVDRV, "called"); | 121 | LOG_DEBUG(Service_NVDRV, "called"); |
| 118 | IoctlNvgpuGpuZcullGetInfoArgs params{}; | 122 | IoctlNvgpuGpuZcullGetInfoArgs params{}; |
| 119 | std::memcpy(¶ms, input.data(), input.size()); | 123 | |
| 124 | if (input.size() > 0) { | ||
| 125 | std::memcpy(¶ms, input.data(), input.size()); | ||
| 126 | } | ||
| 127 | |||
| 120 | params.width_align_pixels = 0x20; | 128 | params.width_align_pixels = 0x20; |
| 121 | params.height_align_pixels = 0x20; | 129 | params.height_align_pixels = 0x20; |
| 122 | params.pixel_squares_by_aliquots = 0x400; | 130 | params.pixel_squares_by_aliquots = 0x400; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index 126782573..5a1123ad2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -132,9 +132,12 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp | |||
| 132 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", | 132 | LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", |
| 133 | params.address, params.num_entries, params.flags); | 133 | params.address, params.num_entries, params.flags); |
| 134 | 134 | ||
| 135 | auto entries = std::vector<IoctlGpfifoEntry>(); | 135 | ASSERT_MSG(input.size() == |
| 136 | entries.resize(params.num_entries); | 136 | sizeof(IoctlSubmitGpfifo) + params.num_entries * sizeof(IoctlGpfifoEntry), |
| 137 | std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)], | 137 | "Incorrect input size"); |
| 138 | |||
| 139 | std::vector<IoctlGpfifoEntry> entries(params.num_entries); | ||
| 140 | std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], | ||
| 138 | params.num_entries * sizeof(IoctlGpfifoEntry)); | 141 | params.num_entries * sizeof(IoctlGpfifoEntry)); |
| 139 | for (auto entry : entries) { | 142 | for (auto entry : entries) { |
| 140 | Tegra::GPUVAddr va_addr = entry.Address(); | 143 | Tegra::GPUVAddr va_addr = entry.Address(); |
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp new file mode 100644 index 000000000..39cf05eba --- /dev/null +++ b/src/core/hle/service/pcie/pcie.cpp | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <memory> | ||
| 6 | |||
| 7 | #include "core/hle/service/pcie/pcie.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/sm/sm.h" | ||
| 10 | |||
| 11 | namespace Service::PCIe { | ||
| 12 | |||
| 13 | class ISession final : public ServiceFramework<ISession> { | ||
| 14 | public: | ||
| 15 | explicit ISession() : ServiceFramework{"ISession"} { | ||
| 16 | // clang-format off | ||
| 17 | static const FunctionInfo functions[] = { | ||
| 18 | {0, nullptr, "QueryFunctions"}, | ||
| 19 | {1, nullptr, "AcquireFunction"}, | ||
| 20 | {2, nullptr, "ReleaseFunction"}, | ||
| 21 | {3, nullptr, "GetFunctionState"}, | ||
| 22 | {4, nullptr, "GetBarProfile"}, | ||
| 23 | {5, nullptr, "ReadConfig"}, | ||
| 24 | {6, nullptr, "WriteConfig"}, | ||
| 25 | {7, nullptr, "ReadBarRegion"}, | ||
| 26 | {8, nullptr, "WriteBarRegion"}, | ||
| 27 | {9, nullptr, "FindCapability"}, | ||
| 28 | {10, nullptr, "FindExtendedCapability"}, | ||
| 29 | {11, nullptr, "MapDma"}, | ||
| 30 | {12, nullptr, "UnmapDma"}, | ||
| 31 | {13, nullptr, "UnmapDmaBusAddress"}, | ||
| 32 | {14, nullptr, "GetDmaBusAddress"}, | ||
| 33 | {15, nullptr, "GetDmaBusAddressRange"}, | ||
| 34 | {16, nullptr, "SetDmaEnable"}, | ||
| 35 | {17, nullptr, "AcquireIrq"}, | ||
| 36 | {18, nullptr, "ReleaseIrq"}, | ||
| 37 | {19, nullptr, "SetIrqEnable"}, | ||
| 38 | {20, nullptr, "SetAspmEnable"}, | ||
| 39 | }; | ||
| 40 | // clang-format on | ||
| 41 | |||
| 42 | RegisterHandlers(functions); | ||
| 43 | } | ||
| 44 | }; | ||
| 45 | |||
| 46 | class PCIe final : public ServiceFramework<PCIe> { | ||
| 47 | public: | ||
| 48 | explicit PCIe() : ServiceFramework{"pcie"} { | ||
| 49 | // clang-format off | ||
| 50 | static const FunctionInfo functions[] = { | ||
| 51 | {0, nullptr, "RegisterClassDriver"}, | ||
| 52 | {1, nullptr, "QueryFunctionsUnregistered"}, | ||
| 53 | }; | ||
| 54 | // clang-format on | ||
| 55 | |||
| 56 | RegisterHandlers(functions); | ||
| 57 | } | ||
| 58 | }; | ||
| 59 | |||
| 60 | void InstallInterfaces(SM::ServiceManager& sm) { | ||
| 61 | std::make_shared<PCIe>()->InstallAsService(sm); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // namespace Service::PCIe | ||
diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h new file mode 100644 index 000000000..59c22ca45 --- /dev/null +++ b/src/core/hle/service/pcie/pcie.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Service::SM { | ||
| 8 | class ServiceManager; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::PCIe { | ||
| 12 | |||
| 13 | void InstallInterfaces(SM::ServiceManager& sm); | ||
| 14 | |||
| 15 | } // namespace Service::PCIe | ||
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 5180a0c93..fccc4c461 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -22,10 +22,12 @@ | |||
| 22 | #include "core/hle/service/audio/audio.h" | 22 | #include "core/hle/service/audio/audio.h" |
| 23 | #include "core/hle/service/bcat/bcat.h" | 23 | #include "core/hle/service/bcat/bcat.h" |
| 24 | #include "core/hle/service/btdrv/btdrv.h" | 24 | #include "core/hle/service/btdrv/btdrv.h" |
| 25 | #include "core/hle/service/btm/btm.h" | ||
| 25 | #include "core/hle/service/erpt/erpt.h" | 26 | #include "core/hle/service/erpt/erpt.h" |
| 26 | #include "core/hle/service/es/es.h" | 27 | #include "core/hle/service/es/es.h" |
| 27 | #include "core/hle/service/eupld/eupld.h" | 28 | #include "core/hle/service/eupld/eupld.h" |
| 28 | #include "core/hle/service/fatal/fatal.h" | 29 | #include "core/hle/service/fatal/fatal.h" |
| 30 | #include "core/hle/service/fgm/fgm.h" | ||
| 29 | #include "core/hle/service/filesystem/filesystem.h" | 31 | #include "core/hle/service/filesystem/filesystem.h" |
| 30 | #include "core/hle/service/friend/friend.h" | 32 | #include "core/hle/service/friend/friend.h" |
| 31 | #include "core/hle/service/grc/grc.h" | 33 | #include "core/hle/service/grc/grc.h" |
| @@ -43,6 +45,7 @@ | |||
| 43 | #include "core/hle/service/nim/nim.h" | 45 | #include "core/hle/service/nim/nim.h" |
| 44 | #include "core/hle/service/ns/ns.h" | 46 | #include "core/hle/service/ns/ns.h" |
| 45 | #include "core/hle/service/nvdrv/nvdrv.h" | 47 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 48 | #include "core/hle/service/pcie/pcie.h" | ||
| 46 | #include "core/hle/service/pctl/pctl.h" | 49 | #include "core/hle/service/pctl/pctl.h" |
| 47 | #include "core/hle/service/pm/pm.h" | 50 | #include "core/hle/service/pm/pm.h" |
| 48 | #include "core/hle/service/prepo/prepo.h" | 51 | #include "core/hle/service/prepo/prepo.h" |
| @@ -55,6 +58,7 @@ | |||
| 55 | #include "core/hle/service/ssl/ssl.h" | 58 | #include "core/hle/service/ssl/ssl.h" |
| 56 | #include "core/hle/service/time/time.h" | 59 | #include "core/hle/service/time/time.h" |
| 57 | #include "core/hle/service/vi/vi.h" | 60 | #include "core/hle/service/vi/vi.h" |
| 61 | #include "core/hle/service/wlan/wlan.h" | ||
| 58 | 62 | ||
| 59 | using Kernel::ClientPort; | 63 | using Kernel::ClientPort; |
| 60 | using Kernel::ServerPort; | 64 | using Kernel::ServerPort; |
| @@ -201,10 +205,12 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) { | |||
| 201 | Audio::InstallInterfaces(*sm); | 205 | Audio::InstallInterfaces(*sm); |
| 202 | BCAT::InstallInterfaces(*sm); | 206 | BCAT::InstallInterfaces(*sm); |
| 203 | BtDrv::InstallInterfaces(*sm); | 207 | BtDrv::InstallInterfaces(*sm); |
| 208 | BTM::InstallInterfaces(*sm); | ||
| 204 | ERPT::InstallInterfaces(*sm); | 209 | ERPT::InstallInterfaces(*sm); |
| 205 | ES::InstallInterfaces(*sm); | 210 | ES::InstallInterfaces(*sm); |
| 206 | EUPLD::InstallInterfaces(*sm); | 211 | EUPLD::InstallInterfaces(*sm); |
| 207 | Fatal::InstallInterfaces(*sm); | 212 | Fatal::InstallInterfaces(*sm); |
| 213 | FGM::InstallInterfaces(*sm); | ||
| 208 | FileSystem::InstallInterfaces(*sm); | 214 | FileSystem::InstallInterfaces(*sm); |
| 209 | Friend::InstallInterfaces(*sm); | 215 | Friend::InstallInterfaces(*sm); |
| 210 | GRC::InstallInterfaces(*sm); | 216 | GRC::InstallInterfaces(*sm); |
| @@ -222,15 +228,17 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) { | |||
| 222 | NIM::InstallInterfaces(*sm); | 228 | NIM::InstallInterfaces(*sm); |
| 223 | NS::InstallInterfaces(*sm); | 229 | NS::InstallInterfaces(*sm); |
| 224 | Nvidia::InstallInterfaces(*sm); | 230 | Nvidia::InstallInterfaces(*sm); |
| 231 | PCIe::InstallInterfaces(*sm); | ||
| 225 | PCTL::InstallInterfaces(*sm); | 232 | PCTL::InstallInterfaces(*sm); |
| 226 | PlayReport::InstallInterfaces(*sm); | 233 | PlayReport::InstallInterfaces(*sm); |
| 227 | PM::InstallInterfaces(*sm); | 234 | PM::InstallInterfaces(*sm); |
| 235 | Set::InstallInterfaces(*sm); | ||
| 228 | Sockets::InstallInterfaces(*sm); | 236 | Sockets::InstallInterfaces(*sm); |
| 229 | SPL::InstallInterfaces(*sm); | 237 | SPL::InstallInterfaces(*sm); |
| 230 | SSL::InstallInterfaces(*sm); | 238 | SSL::InstallInterfaces(*sm); |
| 231 | Time::InstallInterfaces(*sm); | 239 | Time::InstallInterfaces(*sm); |
| 232 | VI::InstallInterfaces(*sm, nv_flinger); | 240 | VI::InstallInterfaces(*sm, nv_flinger); |
| 233 | Set::InstallInterfaces(*sm); | 241 | WLAN::InstallInterfaces(*sm); |
| 234 | 242 | ||
| 235 | LOG_DEBUG(Service, "initialized OK"); | 243 | LOG_DEBUG(Service, "initialized OK"); |
| 236 | } | 244 | } |
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp new file mode 100644 index 000000000..2654594c1 --- /dev/null +++ b/src/core/hle/service/wlan/wlan.cpp | |||
| @@ -0,0 +1,172 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <memory> | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | #include "core/hle/service/sm/sm.h" | ||
| 9 | #include "core/hle/service/wlan/wlan.h" | ||
| 10 | |||
| 11 | namespace Service::WLAN { | ||
| 12 | |||
| 13 | class WLANInfra final : public ServiceFramework<WLANInfra> { | ||
| 14 | public: | ||
| 15 | explicit WLANInfra() : ServiceFramework{"wlan:inf"} { | ||
| 16 | // clang-format off | ||
| 17 | static const FunctionInfo functions[] = { | ||
| 18 | {0, nullptr, "Unknown1"}, | ||
| 19 | {1, nullptr, "Unknown2"}, | ||
| 20 | {2, nullptr, "GetMacAddress"}, | ||
| 21 | {3, nullptr, "StartScan"}, | ||
| 22 | {4, nullptr, "StopScan"}, | ||
| 23 | {5, nullptr, "Connect"}, | ||
| 24 | {6, nullptr, "CancelConnect"}, | ||
| 25 | {7, nullptr, "Disconnect"}, | ||
| 26 | {8, nullptr, "Unknown3"}, | ||
| 27 | {9, nullptr, "Unknown4"}, | ||
| 28 | {10, nullptr, "GetState"}, | ||
| 29 | {11, nullptr, "GetScanResult"}, | ||
| 30 | {12, nullptr, "GetRssi"}, | ||
| 31 | {13, nullptr, "ChangeRxAntenna"}, | ||
| 32 | {14, nullptr, "Unknown5"}, | ||
| 33 | {15, nullptr, "Unknown6"}, | ||
| 34 | {16, nullptr, "RequestWakeUp"}, | ||
| 35 | {17, nullptr, "RequestIfUpDown"}, | ||
| 36 | {18, nullptr, "Unknown7"}, | ||
| 37 | {19, nullptr, "Unknown8"}, | ||
| 38 | {20, nullptr, "Unknown9"}, | ||
| 39 | {21, nullptr, "Unknown10"}, | ||
| 40 | {22, nullptr, "Unknown11"}, | ||
| 41 | {23, nullptr, "Unknown12"}, | ||
| 42 | {24, nullptr, "Unknown13"}, | ||
| 43 | {25, nullptr, "Unknown14"}, | ||
| 44 | {26, nullptr, "Unknown15"}, | ||
| 45 | {27, nullptr, "Unknown16"}, | ||
| 46 | }; | ||
| 47 | // clang-format on | ||
| 48 | |||
| 49 | RegisterHandlers(functions); | ||
| 50 | } | ||
| 51 | }; | ||
| 52 | |||
| 53 | class WLANLocal final : public ServiceFramework<WLANLocal> { | ||
| 54 | public: | ||
| 55 | explicit WLANLocal() : ServiceFramework{"wlan:lcl"} { | ||
| 56 | // clang-format off | ||
| 57 | static const FunctionInfo functions[] = { | ||
| 58 | {0, nullptr, "Unknown1"}, | ||
| 59 | {1, nullptr, "Unknown2"}, | ||
| 60 | {2, nullptr, "Unknown3"}, | ||
| 61 | {3, nullptr, "Unknown4"}, | ||
| 62 | {4, nullptr, "Unknown5"}, | ||
| 63 | {5, nullptr, "Unknown6"}, | ||
| 64 | {6, nullptr, "GetMacAddress"}, | ||
| 65 | {7, nullptr, "CreateBss"}, | ||
| 66 | {8, nullptr, "DestroyBss"}, | ||
| 67 | {9, nullptr, "StartScan"}, | ||
| 68 | {10, nullptr, "StopScan"}, | ||
| 69 | {11, nullptr, "Connect"}, | ||
| 70 | {12, nullptr, "CancelConnect"}, | ||
| 71 | {13, nullptr, "Join"}, | ||
| 72 | {14, nullptr, "CancelJoin"}, | ||
| 73 | {15, nullptr, "Disconnect"}, | ||
| 74 | {16, nullptr, "SetBeaconLostCount"}, | ||
| 75 | {17, nullptr, "Unknown7"}, | ||
| 76 | {18, nullptr, "Unknown8"}, | ||
| 77 | {19, nullptr, "Unknown9"}, | ||
| 78 | {20, nullptr, "GetBssIndicationEvent"}, | ||
| 79 | {21, nullptr, "GetBssIndicationInfo"}, | ||
| 80 | {22, nullptr, "GetState"}, | ||
| 81 | {23, nullptr, "GetAllowedChannels"}, | ||
| 82 | {24, nullptr, "AddIe"}, | ||
| 83 | {25, nullptr, "DeleteIe"}, | ||
| 84 | {26, nullptr, "Unknown10"}, | ||
| 85 | {27, nullptr, "Unknown11"}, | ||
| 86 | {28, nullptr, "CreateRxEntry"}, | ||
| 87 | {29, nullptr, "DeleteRxEntry"}, | ||
| 88 | {30, nullptr, "Unknown12"}, | ||
| 89 | {31, nullptr, "Unknown13"}, | ||
| 90 | {32, nullptr, "AddMatchingDataToRxEntry"}, | ||
| 91 | {33, nullptr, "RemoveMatchingDataFromRxEntry"}, | ||
| 92 | {34, nullptr, "GetScanResult"}, | ||
| 93 | {35, nullptr, "Unknown14"}, | ||
| 94 | {36, nullptr, "SetActionFrameWithBeacon"}, | ||
| 95 | {37, nullptr, "CancelActionFrameWithBeacon"}, | ||
| 96 | {38, nullptr, "CreateRxEntryForActionFrame"}, | ||
| 97 | {39, nullptr, "DeleteRxEntryForActionFrame"}, | ||
| 98 | {40, nullptr, "Unknown15"}, | ||
| 99 | {41, nullptr, "Unknown16"}, | ||
| 100 | {42, nullptr, "CancelGetActionFrame"}, | ||
| 101 | {43, nullptr, "GetRssi"}, | ||
| 102 | {44, nullptr, "Unknown17"}, | ||
| 103 | {45, nullptr, "Unknown18"}, | ||
| 104 | {46, nullptr, "Unknown19"}, | ||
| 105 | {47, nullptr, "Unknown20"}, | ||
| 106 | {48, nullptr, "Unknown21"}, | ||
| 107 | }; | ||
| 108 | // clang-format on | ||
| 109 | |||
| 110 | RegisterHandlers(functions); | ||
| 111 | } | ||
| 112 | }; | ||
| 113 | |||
| 114 | class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> { | ||
| 115 | public: | ||
| 116 | explicit WLANLocalGetFrame() : ServiceFramework{"wlan:lg"} { | ||
| 117 | // clang-format off | ||
| 118 | static const FunctionInfo functions[] = { | ||
| 119 | {0, nullptr, "Unknown"}, | ||
| 120 | }; | ||
| 121 | // clang-format on | ||
| 122 | |||
| 123 | RegisterHandlers(functions); | ||
| 124 | } | ||
| 125 | }; | ||
| 126 | |||
| 127 | class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> { | ||
| 128 | public: | ||
| 129 | explicit WLANSocketGetFrame() : ServiceFramework{"wlan:sg"} { | ||
| 130 | // clang-format off | ||
| 131 | static const FunctionInfo functions[] = { | ||
| 132 | {0, nullptr, "Unknown"}, | ||
| 133 | }; | ||
| 134 | // clang-format on | ||
| 135 | |||
| 136 | RegisterHandlers(functions); | ||
| 137 | } | ||
| 138 | }; | ||
| 139 | |||
| 140 | class WLANSocketManager final : public ServiceFramework<WLANSocketManager> { | ||
| 141 | public: | ||
| 142 | explicit WLANSocketManager() : ServiceFramework{"wlan:soc"} { | ||
| 143 | // clang-format off | ||
| 144 | static const FunctionInfo functions[] = { | ||
| 145 | {0, nullptr, "Unknown1"}, | ||
| 146 | {1, nullptr, "Unknown2"}, | ||
| 147 | {2, nullptr, "Unknown3"}, | ||
| 148 | {3, nullptr, "Unknown4"}, | ||
| 149 | {4, nullptr, "Unknown5"}, | ||
| 150 | {5, nullptr, "Unknown6"}, | ||
| 151 | {6, nullptr, "GetMacAddress"}, | ||
| 152 | {7, nullptr, "SwitchTsfTimerFunction"}, | ||
| 153 | {8, nullptr, "Unknown7"}, | ||
| 154 | {9, nullptr, "Unknown8"}, | ||
| 155 | {10, nullptr, "Unknown9"}, | ||
| 156 | {11, nullptr, "Unknown10"}, | ||
| 157 | }; | ||
| 158 | // clang-format on | ||
| 159 | |||
| 160 | RegisterHandlers(functions); | ||
| 161 | } | ||
| 162 | }; | ||
| 163 | |||
| 164 | void InstallInterfaces(SM::ServiceManager& sm) { | ||
| 165 | std::make_shared<WLANInfra>()->InstallAsService(sm); | ||
| 166 | std::make_shared<WLANLocal>()->InstallAsService(sm); | ||
| 167 | std::make_shared<WLANLocalGetFrame>()->InstallAsService(sm); | ||
| 168 | std::make_shared<WLANSocketGetFrame>()->InstallAsService(sm); | ||
| 169 | std::make_shared<WLANSocketManager>()->InstallAsService(sm); | ||
| 170 | } | ||
| 171 | |||
| 172 | } // namespace Service::WLAN | ||
diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h new file mode 100644 index 000000000..054ea928a --- /dev/null +++ b/src/core/hle/service/wlan/wlan.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Service::SM { | ||
| 8 | class ServiceManager; | ||
| 9 | } | ||
| 10 | |||
| 11 | namespace Service::WLAN { | ||
| 12 | |||
| 13 | void InstallInterfaces(SM::ServiceManager& sm); | ||
| 14 | |||
| 15 | } // namespace Service::WLAN | ||
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp index 44ece01c1..377bd66ab 100644 --- a/src/video_core/macro_interpreter.cpp +++ b/src/video_core/macro_interpreter.cpp | |||
| @@ -102,11 +102,11 @@ bool MacroInterpreter::Step(const std::vector<u32>& code, bool is_delay_slot) { | |||
| 102 | if (taken) { | 102 | if (taken) { |
| 103 | // Ignore the delay slot if the branch has the annul bit. | 103 | // Ignore the delay slot if the branch has the annul bit. |
| 104 | if (opcode.branch_annul) { | 104 | if (opcode.branch_annul) { |
| 105 | pc = base_address + (opcode.immediate << 2); | 105 | pc = base_address + opcode.GetBranchTarget(); |
| 106 | return true; | 106 | return true; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | delayed_pc = base_address + (opcode.immediate << 2); | 109 | delayed_pc = base_address + opcode.GetBranchTarget(); |
| 110 | // Execute one more instruction due to the delay slot. | 110 | // Execute one more instruction due to the delay slot. |
| 111 | return Step(code, true); | 111 | return Step(code, true); |
| 112 | } | 112 | } |
diff --git a/src/video_core/macro_interpreter.h b/src/video_core/macro_interpreter.h index a71e359d8..7d836b816 100644 --- a/src/video_core/macro_interpreter.h +++ b/src/video_core/macro_interpreter.h | |||
| @@ -91,6 +91,10 @@ private: | |||
| 91 | u32 GetBitfieldMask() const { | 91 | u32 GetBitfieldMask() const { |
| 92 | return (1 << bf_size) - 1; | 92 | return (1 << bf_size) - 1; |
| 93 | } | 93 | } |
| 94 | |||
| 95 | s32 GetBranchTarget() const { | ||
| 96 | return static_cast<s32>(immediate * sizeof(u32)); | ||
| 97 | } | ||
| 94 | }; | 98 | }; |
| 95 | 99 | ||
| 96 | union MethodAddress { | 100 | union MethodAddress { |
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index d6647eeea..39ed3bccf 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp | |||
| @@ -10,8 +10,9 @@ | |||
| 10 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { | 10 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { |
| 11 | ui->setupUi(this); | 11 | ui->setupUi(this); |
| 12 | ui->labelLogo->setPixmap(QIcon::fromTheme("yuzu").pixmap(200)); | 12 | ui->labelLogo->setPixmap(QIcon::fromTheme("yuzu").pixmap(200)); |
| 13 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( | 13 | ui->labelBuildInfo->setText( |
| 14 | Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | 14 | ui->labelBuildInfo->text().arg(Common::g_build_name, Common::g_scm_branch, |
| 15 | Common::g_scm_desc, QString(Common::g_build_date).left(10))); | ||
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | AboutDialog::~AboutDialog() {} | 18 | AboutDialog::~AboutDialog() {} |
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index 2680480cc..f122ba39d 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui | |||
| @@ -70,7 +70,7 @@ | |||
| 70 | </sizepolicy> | 70 | </sizepolicy> |
| 71 | </property> | 71 | </property> |
| 72 | <property name="text"> | 72 | <property name="text"> |
| 73 | <string><html><head/><body><p>%1 | %2-%3</p></body></html></string> | 73 | <string><html><head/><body><p>%1 | %2-%3 (%4)</p></body></html></string> |
| 74 | </property> | 74 | </property> |
| 75 | </widget> | 75 | </widget> |
| 76 | </item> | 76 | </item> |
| @@ -115,7 +115,7 @@ p, li { white-space: pre-wrap; } | |||
| 115 | <item> | 115 | <item> |
| 116 | <widget class="QLabel" name="labelLinks"> | 116 | <widget class="QLabel" name="labelLinks"> |
| 117 | <property name="text"> | 117 | <property name="text"> |
| 118 | <string><html><head/><body><p><a href="https://yuzu-emu.org/"><span style=" text-decoration: underline; color:#0000ff;">Website</span></a> | <a href="https://github.com/yuzu-emu"><span style=" text-decoration: underline; color:#0000ff;">Source Code</span></a> | <a href="https://github.com/yuzu-emu/yuzu/graphs/contributors"><span style=" text-decoration: underline; color:#0000ff;">Contributors</span></a> | <a href="https://github.com/yuzu-emu/yuzu/blob/master/license.txt"><span style=" text-decoration: underline; color:#0000ff;">License</span></a></p></body></html></string> | 118 | <string><html><head/><body><p><a href="https://yuzu-emu.org/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://github.com/yuzu-emu"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://github.com/yuzu-emu/yuzu/graphs/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://github.com/yuzu-emu/yuzu/blob/master/license.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></string> |
| 119 | </property> | 119 | </property> |
| 120 | <property name="openExternalLinks"> | 120 | <property name="openExternalLinks"> |
| 121 | <bool>true</bool> | 121 | <bool>true</bool> |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 5e66239ff..7fd07539a 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -44,5 +44,4 @@ void ConfigureDebug::applyConfiguration() { | |||
| 44 | Log::Filter filter; | 44 | Log::Filter filter; |
| 45 | filter.ParseFilterString(Settings::values.log_filter); | 45 | filter.ParseFilterString(Settings::values.log_filter); |
| 46 | Log::SetGlobalFilter(filter); | 46 | Log::SetGlobalFilter(filter); |
| 47 | Settings::Apply(); | ||
| 48 | } | 47 | } |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index baa558667..cb7d3f8bf 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -44,5 +44,4 @@ void ConfigureGeneral::applyConfiguration() { | |||
| 44 | Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); | 44 | Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); |
| 45 | Settings::values.use_multi_core = ui->use_multi_core->isChecked(); | 45 | Settings::values.use_multi_core = ui->use_multi_core->isChecked(); |
| 46 | Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); | 46 | Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); |
| 47 | Settings::Apply(); | ||
| 48 | } | 47 | } |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 7664880d5..3379b7963 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -67,5 +67,4 @@ void ConfigureGraphics::applyConfiguration() { | |||
| 67 | ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex())); | 67 | ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex())); |
| 68 | Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked(); | 68 | Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked(); |
| 69 | Settings::values.use_accurate_framebuffers = ui->use_accurate_framebuffers->isChecked(); | 69 | Settings::values.use_accurate_framebuffers = ui->use_accurate_framebuffers->isChecked(); |
| 70 | Settings::Apply(); | ||
| 71 | } | 70 | } |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 78559e2bb..5e7badedf 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -191,8 +191,6 @@ void ConfigureInput::applyConfiguration() { | |||
| 191 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 191 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 192 | std::transform(analogs_param.begin(), analogs_param.end(), Settings::values.analogs.begin(), | 192 | std::transform(analogs_param.begin(), analogs_param.end(), Settings::values.analogs.begin(), |
| 193 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 193 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 194 | |||
| 195 | Settings::Apply(); | ||
| 196 | } | 194 | } |
| 197 | 195 | ||
| 198 | void ConfigureInput::loadConfiguration() { | 196 | void ConfigureInput::loadConfiguration() { |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 96998643e..be38cfa9b 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -723,10 +723,12 @@ void GMainWindow::ToggleWindowMode() { | |||
| 723 | 723 | ||
| 724 | void GMainWindow::OnConfigure() { | 724 | void GMainWindow::OnConfigure() { |
| 725 | ConfigureDialog configureDialog(this); | 725 | ConfigureDialog configureDialog(this); |
| 726 | auto old_theme = UISettings::values.theme; | ||
| 726 | auto result = configureDialog.exec(); | 727 | auto result = configureDialog.exec(); |
| 727 | if (result == QDialog::Accepted) { | 728 | if (result == QDialog::Accepted) { |
| 728 | configureDialog.applyConfiguration(); | 729 | configureDialog.applyConfiguration(); |
| 729 | UpdateUITheme(); | 730 | if (UISettings::values.theme != old_theme) |
| 731 | UpdateUITheme(); | ||
| 730 | config->Save(); | 732 | config->Save(); |
| 731 | } | 733 | } |
| 732 | } | 734 | } |
| @@ -957,7 +959,6 @@ int main(int argc, char* argv[]) { | |||
| 957 | QCoreApplication::setOrganizationName("yuzu team"); | 959 | QCoreApplication::setOrganizationName("yuzu team"); |
| 958 | QCoreApplication::setApplicationName("yuzu"); | 960 | QCoreApplication::setApplicationName("yuzu"); |
| 959 | 961 | ||
| 960 | QApplication::setAttribute(Qt::AA_X11InitThreads); | ||
| 961 | QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); | 962 | QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); |
| 962 | QApplication app(argc, argv); | 963 | QApplication app(argc, argv); |
| 963 | 964 | ||