summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar David2018-06-23 12:22:33 +1000
committerGravatar bunnei2018-06-22 22:22:33 -0400
commit81f24f568519ce7b035e3631b12a816e2a1c8579 (patch)
tree9a2c55f0d5cc2091627111cfa742dfd98aa915ea /src
parentMerge pull request #526 from janisozaur/appveyor-ninja (diff)
downloadyuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.tar.gz
yuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.tar.xz
yuzu-81f24f568519ce7b035e3631b12a816e2a1c8579.zip
Fixed RequestUpdateAudioRenderer deadlocks and calculated section sizes properly (#580)
* Fixed RequestUpdateAudioRenderer deadlocks and calculated section sizes properly This fixes RequestUpdateAudioRenderer deadlocks in games like Puyo Puyo Tetris and games which require a proper section size in games such as Retro City Rampage. This fixes causes various games to start rendering or trying to render
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/audio/audren_u.cpp83
-rw-r--r--src/core/hle/service/audio/audren_u.h37
2 files changed, 76 insertions, 44 deletions
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 44b7ef216..653ded8e9 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -17,7 +17,8 @@ constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)};
17 17
18class IAudioRenderer final : public ServiceFramework<IAudioRenderer> { 18class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
19public: 19public:
20 IAudioRenderer() : ServiceFramework("IAudioRenderer") { 20 IAudioRenderer(AudioRendererParameters audren_params)
21 : ServiceFramework("IAudioRenderer"), worker_params(audren_params) {
21 static const FunctionInfo functions[] = { 22 static const FunctionInfo functions[] = {
22 {0, nullptr, "GetAudioRendererSampleRate"}, 23 {0, nullptr, "GetAudioRendererSampleRate"},
23 {1, nullptr, "GetAudioRendererSampleCount"}, 24 {1, nullptr, "GetAudioRendererSampleCount"},
@@ -60,16 +61,27 @@ private:
60 AudioRendererConfig config; 61 AudioRendererConfig config;
61 auto buf = ctx.ReadBuffer(); 62 auto buf = ctx.ReadBuffer();
62 std::memcpy(&config, buf.data(), sizeof(AudioRendererConfig)); 63 std::memcpy(&config, buf.data(), sizeof(AudioRendererConfig));
64 u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
63 65
64 AudioRendererResponse response_data{config}; 66 std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
67 std::memcpy(mem_pool_info.data(),
68 buf.data() + sizeof(AudioRendererConfig) + config.behavior_size,
69 memory_pool_count * sizeof(MemoryPoolInfo));
70
71 AudioRendererResponse response_data{worker_params};
65 72
66 ASSERT(ctx.GetWriteBufferSize() == response_data.total_size); 73 ASSERT(ctx.GetWriteBufferSize() == response_data.total_size);
67 74
68 std::vector<u8> output(response_data.total_size); 75 std::vector<u8> output(response_data.total_size);
69 std::memcpy(output.data(), &response_data, sizeof(AudioRendererResponse)); 76 std::memcpy(output.data(), &response_data, sizeof(AudioRendererResponse));
70 std::vector<MemoryPoolEntry> memory_pool(config.memory_pools_size / 0x20); 77 std::vector<MemoryPoolEntry> memory_pool(memory_pool_count);
71 for (auto& entry : memory_pool) { 78 for (unsigned i = 0; i < memory_pool.size(); i++) {
72 entry.state = 5; 79 if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestAttach)
80 memory_pool[i].state = MemoryPoolStates::Attached;
81 else if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestDetach)
82 memory_pool[i].state = MemoryPoolStates::Detached;
83 else
84 memory_pool[i].state = mem_pool_info[i].pool_state;
73 } 85 }
74 std::memcpy(output.data() + sizeof(AudioRendererResponse), memory_pool.data(), 86 std::memcpy(output.data() + sizeof(AudioRendererResponse), memory_pool.data(),
75 response_data.memory_pools_size); 87 response_data.memory_pools_size);
@@ -108,14 +120,32 @@ private:
108 NGLOG_WARNING(Service_Audio, "(STUBBED) called"); 120 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
109 } 121 }
110 122
123 enum class MemoryPoolStates : u32 { // Should be LE
124 Invalid = 0x0,
125 Unknown = 0x1,
126 RequestDetach = 0x2,
127 Detached = 0x3,
128 RequestAttach = 0x4,
129 Attached = 0x5,
130 Released = 0x6,
131 };
132
111 struct MemoryPoolEntry { 133 struct MemoryPoolEntry {
112 u32_le state; 134 MemoryPoolStates state;
113 u32_le unknown_4; 135 u32_le unknown_4;
114 u32_le unknown_8; 136 u32_le unknown_8;
115 u32_le unknown_c; 137 u32_le unknown_c;
116 }; 138 };
117 static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size"); 139 static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size");
118 140
141 struct MemoryPoolInfo {
142 u64_le pool_address;
143 u64_le pool_size;
144 MemoryPoolStates pool_state;
145 INSERT_PADDING_WORDS(3); // Unknown
146 };
147 static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size");
148
119 struct AudioRendererConfig { 149 struct AudioRendererConfig {
120 u32 revision; 150 u32 revision;
121 u32 behavior_size; 151 u32 behavior_size;
@@ -132,13 +162,13 @@ private:
132 static_assert(sizeof(AudioRendererConfig) == 0x40, "AudioRendererConfig has wrong size"); 162 static_assert(sizeof(AudioRendererConfig) == 0x40, "AudioRendererConfig has wrong size");
133 163
134 struct AudioRendererResponse { 164 struct AudioRendererResponse {
135 AudioRendererResponse(const AudioRendererConfig& config) { 165 AudioRendererResponse(const AudioRendererParameters& config) {
136 revision = config.revision; 166 revision = config.revision;
137 error_info_size = 0xb0; 167 error_info_size = 0xb0;
138 memory_pools_size = (config.memory_pools_size / 0x20) * 0x10; 168 memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
139 voices_size = (config.voices_size / 0x170) * 0x10; 169 voices_size = config.voice_count * 0x10;
140 effects_size = (config.effects_size / 0xC0) * 0x10; 170 effects_size = config.effect_count * 0x10;
141 sinks_size = (config.sinks_size / 0x140) * 0x20; 171 sinks_size = config.sink_count * 0x20;
142 performance_manager_size = 0x10; 172 performance_manager_size = 0x10;
143 total_size = sizeof(AudioRendererResponse) + error_info_size + memory_pools_size + 173 total_size = sizeof(AudioRendererResponse) + error_info_size + memory_pools_size +
144 voices_size + effects_size + sinks_size + performance_manager_size; 174 voices_size + effects_size + sinks_size + performance_manager_size;
@@ -162,6 +192,7 @@ private:
162 CoreTiming::EventType* audio_event; 192 CoreTiming::EventType* audio_event;
163 193
164 Kernel::SharedPtr<Kernel::Event> system_event; 194 Kernel::SharedPtr<Kernel::Event> system_event;
195 AudioRendererParameters worker_params;
165}; 196};
166 197
167class IAudioDevice final : public ServiceFramework<IAudioDevice> { 198class IAudioDevice final : public ServiceFramework<IAudioDevice> {
@@ -259,10 +290,12 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
259} 290}
260 291
261void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { 292void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
293 IPC::RequestParser rp{ctx};
294 auto params = rp.PopRaw<AudioRendererParameters>();
262 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 295 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
263 296
264 rb.Push(RESULT_SUCCESS); 297 rb.Push(RESULT_SUCCESS);
265 rb.PushIpcInterface<Audio::IAudioRenderer>(); 298 rb.PushIpcInterface<Audio::IAudioRenderer>(std::move(params));
266 299
267 NGLOG_DEBUG(Service_Audio, "called"); 300 NGLOG_DEBUG(Service_Audio, "called");
268} 301}
@@ -271,19 +304,19 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
271 IPC::RequestParser rp{ctx}; 304 IPC::RequestParser rp{ctx};
272 auto params = rp.PopRaw<AudioRendererParameters>(); 305 auto params = rp.PopRaw<AudioRendererParameters>();
273 306
274 u64 buffer_sz = Common::AlignUp(4 * params.unknown8, 0x40); 307 u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40);
275 buffer_sz += params.unknownC * 1024; 308 buffer_sz += params.unknown_c * 1024;
276 buffer_sz += 0x940 * (params.unknownC + 1); 309 buffer_sz += 0x940 * (params.unknown_c + 1);
277 buffer_sz += 0x3F0 * params.voice_count; 310 buffer_sz += 0x3F0 * params.voice_count;
278 buffer_sz += Common::AlignUp(8 * (params.unknownC + 1), 0x10); 311 buffer_sz += Common::AlignUp(8 * (params.unknown_c + 1), 0x10);
279 buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10); 312 buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
280 buffer_sz += 313 buffer_sz +=
281 Common::AlignUp((0x3C0 * (params.sink_count + params.unknownC) + 4 * params.sample_count) * 314 Common::AlignUp((0x3C0 * (params.sink_count + params.unknown_c) + 4 * params.sample_count) *
282 (params.unknown8 + 6), 315 (params.unknown_8 + 6),
283 0x40); 316 0x40);
284 317
285 if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) { 318 if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
286 u32 count = params.unknownC + 1; 319 u32 count = params.unknown_c + 1;
287 u64 node_count = Common::AlignUp(count, 0x40); 320 u64 node_count = Common::AlignUp(count, 0x40);
288 u64 node_state_buffer_sz = 321 u64 node_state_buffer_sz =
289 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8); 322 4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8);
@@ -298,20 +331,20 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
298 } 331 }
299 332
300 buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50; 333 buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50;
301 if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) { 334 if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
302 buffer_sz += 0xE0 * params.unknown2c; 335 buffer_sz += 0xE0 * params.unknown_2c;
303 buffer_sz += 0x20 * params.splitter_count; 336 buffer_sz += 0x20 * params.splitter_count;
304 buffer_sz += Common::AlignUp(4 * params.unknown2c, 0x10); 337 buffer_sz += Common::AlignUp(4 * params.unknown_2c, 0x10);
305 } 338 }
306 buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count; 339 buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count;
307 u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count + 340 u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count +
308 ((params.voice_count * 256) | 0x40); 341 ((params.voice_count * 256) | 0x40);
309 342
310 if (params.unknown1c >= 1) { 343 if (params.unknown_1c >= 1) {
311 output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count + 344 output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count +
312 16 * params.voice_count + 16) + 345 16 * params.voice_count + 16) +
313 0x658) * 346 0x658) *
314 (params.unknown1c + 1) + 347 (params.unknown_1c + 1) +
315 0xc0, 348 0xc0,
316 0x40) + 349 0x40) +
317 output_sz; 350 output_sz;
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 7dbd9b74d..e8baf99ee 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -12,6 +12,24 @@ class HLERequestContext;
12 12
13namespace Service::Audio { 13namespace Service::Audio {
14 14
15struct AudioRendererParameters {
16 u32_le sample_rate;
17 u32_le sample_count;
18 u32_le unknown_8;
19 u32_le unknown_c;
20 u32_le voice_count;
21 u32_le sink_count;
22 u32_le effect_count;
23 u32_le unknown_1c;
24 u8 unknown_20;
25 INSERT_PADDING_BYTES(3);
26 u32_le splitter_count;
27 u32_le unknown_2c;
28 INSERT_PADDING_WORDS(1);
29 u32_le revision;
30};
31static_assert(sizeof(AudioRendererParameters) == 52, "AudioRendererParameters is an invalid size");
32
15class AudRenU final : public ServiceFramework<AudRenU> { 33class AudRenU final : public ServiceFramework<AudRenU> {
16public: 34public:
17 explicit AudRenU(); 35 explicit AudRenU();
@@ -22,25 +40,6 @@ private:
22 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); 40 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
23 void GetAudioDevice(Kernel::HLERequestContext& ctx); 41 void GetAudioDevice(Kernel::HLERequestContext& ctx);
24 42
25 struct AudioRendererParameters {
26 u32_le sample_rate;
27 u32_le sample_count;
28 u32_le unknown8;
29 u32_le unknownC;
30 u32_le voice_count;
31 u32_le sink_count;
32 u32_le effect_count;
33 u32_le unknown1c;
34 u8 unknown20;
35 u8 padding1[3];
36 u32_le splitter_count;
37 u32_le unknown2c;
38 u8 padding2[4];
39 u32_le magic;
40 };
41 static_assert(sizeof(AudioRendererParameters) == 52,
42 "AudioRendererParameters is an invalid size");
43
44 enum class AudioFeatures : u32 { 43 enum class AudioFeatures : u32 {
45 Splitter, 44 Splitter,
46 }; 45 };