summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt12
-rw-r--r--src/audio_core/audio_out.cpp17
-rw-r--r--src/audio_core/audio_out.h8
-rw-r--r--src/audio_core/buffer.h3
-rw-r--r--src/audio_core/cubeb_sink.cpp190
-rw-r--r--src/audio_core/cubeb_sink.h31
-rw-r--r--src/audio_core/null_sink.h27
-rw-r--r--src/audio_core/sink.h29
-rw-r--r--src/audio_core/sink_details.cpp44
-rw-r--r--src/audio_core/sink_details.h32
-rw-r--r--src/audio_core/sink_stream.h32
-rw-r--r--src/audio_core/stream.cpp35
-rw-r--r--src/audio_core/stream.h22
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/logging/backend.cpp4
-rw-r--r--src/common/logging/log.h4
-rw-r--r--src/common/logging/text_formatter.h1
-rw-r--r--src/common/string_util.cpp8
-rw-r--r--src/common/swap.h2
-rw-r--r--src/common/timer.cpp95
-rw-r--r--src/common/timer.h17
-rw-r--r--src/core/CMakeLists.txt16
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp16
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/file_sys/partition_filesystem.cpp5
-rw-r--r--src/core/hle/service/am/am.cpp6
-rw-r--r--src/core/hle/service/am/idle.cpp24
-rw-r--r--src/core/hle/service/am/idle.h16
-rw-r--r--src/core/hle/service/am/omm.cpp42
-rw-r--r--src/core/hle/service/am/omm.h16
-rw-r--r--src/core/hle/service/am/spsm.cpp30
-rw-r--r--src/core/hle/service/am/spsm.h16
-rw-r--r--src/core/hle/service/audio/audout_u.cpp8
-rw-r--r--src/core/hle/service/audio/audout_u.h2
-rw-r--r--src/core/hle/service/audio/hwopus.cpp135
-rw-r--r--src/core/hle/service/audio/hwopus.h1
-rw-r--r--src/core/hle/service/btm/btm.cpp121
-rw-r--r--src/core/hle/service/btm/btm.h15
-rw-r--r--src/core/hle/service/fgm/fgm.cpp75
-rw-r--r--src/core/hle/service/fgm/fgm.h15
-rw-r--r--src/core/hle/service/hid/hid.cpp18
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp14
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp9
-rw-r--r--src/core/hle/service/pcie/pcie.cpp64
-rw-r--r--src/core/hle/service/pcie/pcie.h15
-rw-r--r--src/core/hle/service/service.cpp10
-rw-r--r--src/core/hle/service/wlan/wlan.cpp172
-rw-r--r--src/core/hle/service/wlan/wlan.h15
-rw-r--r--src/video_core/macro_interpreter.cpp4
-rw-r--r--src/video_core/macro_interpreter.h4
-rw-r--r--src/yuzu/about_dialog.cpp5
-rw-r--r--src/yuzu/aboutdialog.ui4
-rw-r--r--src/yuzu/configuration/configure_debug.cpp1
-rw-r--r--src/yuzu/configuration/configure_general.cpp1
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp1
-rw-r--r--src/yuzu/configuration/configure_input.cpp2
-rw-r--r--src/yuzu/main.cpp5
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
9create_target_directory_groups(audio_core) 16create_target_directory_groups(audio_core)
10 17
11target_link_libraries(audio_core PUBLIC common core) 18target_link_libraries(audio_core PUBLIC common core)
19
20if(ENABLE_CUBEB)
21 target_link_libraries(audio_core PRIVATE cubeb)
22 target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
23endif()
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
9namespace AudioCore { 11namespace 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
12static Stream::Format ChannelsToStreamFormat(int num_channels) { 14static 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
27StreamPtr AudioOut::OpenStream(int sample_rate, int num_channels, 29StreamPtr 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
34std::vector<u64> AudioOut::GetTagsAndReleaseBuffers(StreamPtr stream, size_t max_count) { 41std::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
14namespace AudioCore { 15namespace AudioCore {
15 16
16using 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 */
21class AudioOut { 20class AudioOut {
22public: 21public:
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
39private: 38private:
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
38using 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
12namespace AudioCore {
13
14class SinkStreamImpl final : public SinkStream {
15public:
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, &params, &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, &params, 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
83private:
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
96CubebSink::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
120CubebSink::~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
132SinkStream& 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
137long 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
162void SinkStreamImpl::StateCallback(cubeb_stream* stream, void* user_data, cubeb_state state) {}
163
164std::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
14namespace AudioCore {
15
16class CubebSink final : public Sink {
17public:
18 explicit CubebSink(std::string device_id);
19 ~CubebSink() override;
20
21 SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) override;
22
23private:
24 cubeb* ctx{};
25 cubeb_devid output_device{};
26 std::vector<SinkStreamPtr> sink_streams;
27};
28
29std::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
9namespace AudioCore {
10
11class NullSink final : public Sink {
12public:
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
20private:
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
12namespace AudioCore {
13
14constexpr 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 */
21class Sink {
22public:
23 virtual ~Sink() = default;
24 virtual SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels) = 0;
25};
26
27using 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
16namespace AudioCore {
17
18// g_sink_details is ordered in terms of desirability, with the best choice at the top.
19const 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
27const 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
11namespace AudioCore {
12
13class Sink;
14
15struct 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
28extern const std::vector<SinkDetails> g_sink_details;
29
30const 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
11namespace 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 */
17class SinkStream {
18public:
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
30using 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
12namespace AudioCore { 14namespace AudioCore {
13 15
14constexpr size_t MaxAudioBufferCount{32}; 16constexpr size_t MaxAudioBufferCount{32};
15 17
16/// Returns the sample size for the specified audio stream format 18u32 Stream::GetNumChannels() const {
17static 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
32Stream::Stream(int sample_rate, Format format, ReleaseCallback&& release_callback) 32u32 Stream::GetSampleSize() const {
33 : sample_rate{sample_rate}, format{format}, release_callback{std::move(release_callback)} { 33 return GetNumChannels() * 2;
34}
35
36Stream::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
47s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { 54s64 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
17namespace AudioCore { 18namespace AudioCore {
18 19
19using 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
63private: 74private:
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
101using 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
9namespace Log { 10namespace 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
26std::string ToLower(std::string str) { 26std::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
32std::string ToUpper(std::string str) { 33std::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) {
69inline u64 swap64(u64 _data) { 69inline 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)
73inline u16 swap16(u16 _data) { 73inline 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
21namespace Common { 11namespace Common {
22 12
23u32 Timer::GetTimeMs() { 13std::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()
66u64 Timer::GetTimeDifference() { 51std::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()
77u64 Timer::GetTimeElapsed() { 62std::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()
91std::string Timer::GetTimeElapsedFormatted() const { 76std::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
116void Timer::IncreaseResolution() {
117#ifdef _WIN32
118 timeBeginPeriod(1);
119#endif
120}
121
122void 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
129u64 Timer::GetTimeSinceJan1970() { 101std::chrono::seconds Timer::GetTimeSinceJan1970() {
130 time_t ltime; 102 return std::chrono::duration_cast<std::chrono::seconds>(GetTimeMs());
131 time(&ltime);
132 return ((u64)ltime);
133} 103}
134 104
135u64 Timer::GetLocalTimeSinceJan1970() { 105std::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// ----------------
181double Timer::GetDoubleTime() { 143double 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
36private: 35private:
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
314create_target_directory_groups(core) 328create_target_directory_groups(core)
315 329
316target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) 330target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
317target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static unicorn) 331target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static opus unicorn)
318 332
319if (ARCHITECTURE_x86_64) 333if (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
141ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index) 141ARM_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
152ARM_Dynarmic::~ARM_Dynarmic() = default; 150ARM_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
208void ARM_Dynarmic::SetTlsAddress(u64 address) { 206void 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
220void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { 218void 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
229void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) { 227void 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
694IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") { 700IHomeMenuFunctions::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
7namespace Service::AM {
8
9IdleSys::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
9namespace Service::AM {
10
11class IdleSys final : public ServiceFramework<IdleSys> {
12public:
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
7namespace Service::AM {
8
9OMM::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
9namespace Service::AM {
10
11class OMM final : public ServiceFramework<OMM> {
12public:
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
7namespace Service::AM {
8
9SPSM::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
9namespace Service::AM {
10
11class SPSM final : public ServiceFramework<SPSM> {
12public:
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
26class IAudioOut final : public ServiceFramework<IAudioOut> { 26class IAudioOut final : public ServiceFramework<IAudioOut> {
27public: 27public:
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
9namespace Kernel { 10namespace Kernel {
@@ -33,6 +34,7 @@ public:
33 34
34private: 35private:
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
10namespace Service::Audio { 12namespace Service::Audio {
11 13
14struct OpusDeleter {
15 void operator()(void* ptr) const {
16 operator delete(ptr);
17 }
18};
19
20class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
21public:
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
39private:
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
94static 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
12void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) { 99void 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
115void 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
19HwOpus::HwOpus() : ServiceFramework("hwopus") { 144HwOpus::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
16private: 16private:
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
14namespace Service::BTM {
15
16class BTM final : public ServiceFramework<BTM> {
17public:
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
50class BTM_DBG final : public ServiceFramework<BTM_DBG> {
51public:
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
71class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
72public:
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
93class BTM_SYS final : public ServiceFramework<BTM_SYS> {
94public:
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
105private:
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
115void 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
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::BTM {
12
13void 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
13namespace Service::FGM {
14
15class IRequest final : public ServiceFramework<IRequest> {
16public:
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
31class FGM final : public ServiceFramework<FGM> {
32public:
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
43private:
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
53class FGM_DBG final : public ServiceFramework<FGM_DBG> {
54public:
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
68void 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
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::FGM {
12
13void 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>&
97u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { 97u32 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(&params, input.data(), input.size()); 100 if (input.size() > 0) {
101 std::memcpy(&params, 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(), &params, output.size()); 105 std::memcpy(output.data(), &params, output.size());
@@ -107,7 +109,9 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector
107u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { 109u32 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(&params, input.data(), input.size()); 112 if (input.size() > 0) {
113 std::memcpy(&params, input.data(), input.size());
114 }
111 params.size = 0x1; 115 params.size = 0x1;
112 std::memcpy(output.data(), &params, output.size()); 116 std::memcpy(output.data(), &params, 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
116u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { 120u32 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(&params, input.data(), input.size()); 123
124 if (input.size() > 0) {
125 std::memcpy(&params, 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
11namespace Service::PCIe {
12
13class ISession final : public ServiceFramework<ISession> {
14public:
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
46class PCIe final : public ServiceFramework<PCIe> {
47public:
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
60void 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
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::PCIe {
12
13void 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
59using Kernel::ClientPort; 63using Kernel::ClientPort;
60using Kernel::ServerPort; 64using 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
11namespace Service::WLAN {
12
13class WLANInfra final : public ServiceFramework<WLANInfra> {
14public:
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
53class WLANLocal final : public ServiceFramework<WLANLocal> {
54public:
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
114class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> {
115public:
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
127class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> {
128public:
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
140class WLANSocketManager final : public ServiceFramework<WLANSocketManager> {
141public:
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
164void 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
7namespace Service::SM {
8class ServiceManager;
9}
10
11namespace Service::WLAN {
12
13void 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 @@
10AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { 10AboutDialog::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
17AboutDialog::~AboutDialog() {} 18AboutDialog::~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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 | %2-%3&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 73 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 | %2-%3 (%4)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://yuzu-emu.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Website&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Source Code&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/graphs/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Contributors&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/blob/master/license.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;License&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 118 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://yuzu-emu.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Website&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Source Code&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/graphs/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Contributors&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/blob/master/license.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;License&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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
198void ConfigureInput::loadConfiguration() { 196void 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
724void GMainWindow::OnConfigure() { 724void 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