summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/chunk_file.h623
-rw-r--r--src/common/linear_disk_cache.h167
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/file_sys/disk_filesystem.cpp33
-rw-r--r--src/core/file_sys/disk_filesystem.h2
-rw-r--r--src/core/file_sys/filesystem.cpp6
-rw-r--r--src/core/file_sys/filesystem.h3
-rw-r--r--src/core/file_sys/partition_filesystem.cpp3
-rw-r--r--src/core/file_sys/program_metadata.cpp39
-rw-r--r--src/core/file_sys/romfs_factory.cpp6
-rw-r--r--src/core/file_sys/romfs_filesystem.cpp41
-rw-r--r--src/core/file_sys/romfs_filesystem.h2
-rw-r--r--src/core/file_sys/savedata_factory.cpp9
-rw-r--r--src/core/file_sys/sdmc_factory.cpp5
-rw-r--r--src/core/gdbstub/gdbstub.cpp75
-rw-r--r--src/core/hle/kernel/condition_variable.cpp64
-rw-r--r--src/core/hle/kernel/condition_variable.h63
-rw-r--r--src/core/hle/kernel/errors.h1
-rw-r--r--src/core/hle/kernel/handle_table.cpp4
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp5
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/mutex.cpp179
-rw-r--r--src/core/hle/kernel/mutex.h88
-rw-r--r--src/core/hle/kernel/process.cpp8
-rw-r--r--src/core/hle/kernel/resource_limit.cpp6
-rw-r--r--src/core/hle/kernel/scheduler.cpp6
-rw-r--r--src/core/hle/kernel/server_session.cpp6
-rw-r--r--src/core/hle/kernel/shared_memory.cpp17
-rw-r--r--src/core/hle/kernel/svc.cpp296
-rw-r--r--src/core/hle/kernel/thread.cpp81
-rw-r--r--src/core/hle/kernel/thread.h36
-rw-r--r--src/core/hle/kernel/timer.cpp4
-rw-r--r--src/core/hle/kernel/vm_manager.cpp8
-rw-r--r--src/core/hle/service/acc/acc.cpp20
-rw-r--r--src/core/hle/service/am/am.cpp64
-rw-r--r--src/core/hle/service/am/applet_ae.cpp18
-rw-r--r--src/core/hle/service/am/applet_oe.cpp18
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp4
-rw-r--r--src/core/hle/service/apm/interface.cpp6
-rw-r--r--src/core/hle/service/audio/audout_u.cpp16
-rw-r--r--src/core/hle/service/audio/audren_u.cpp26
-rw-r--r--src/core/hle/service/fatal/fatal.cpp4
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp8
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp71
-rw-r--r--src/core/hle/service/friend/friend.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp50
-rw-r--r--src/core/hle/service/lm/lm.cpp12
-rw-r--r--src/core/hle/service/nifm/nifm.cpp22
-rw-r--r--src/core/hle/service/ns/pl_u.cpp12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp71
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp14
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp18
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp39
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp12
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp14
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp10
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h6
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/hle/service/pctl/module.cpp (renamed from src/core/hle/service/pctl/pctl_a.cpp)39
-rw-r--r--src/core/hle/service/pctl/module.h28
-rw-r--r--src/core/hle/service/pctl/pctl.cpp11
-rw-r--r--src/core/hle/service/pctl/pctl.h8
-rw-r--r--src/core/hle/service/pctl/pctl_a.h20
-rw-r--r--src/core/hle/service/service.cpp10
-rw-r--r--src/core/hle/service/set/set.cpp2
-rw-r--r--src/core/hle/service/set/set_sys.cpp2
-rw-r--r--src/core/hle/service/sm/controller.cpp8
-rw-r--r--src/core/hle/service/sm/sm.cpp9
-rw-r--r--src/core/hle/service/sockets/bsd.cpp13
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp2
-rw-r--r--src/core/hle/service/spl/module.cpp2
-rw-r--r--src/core/hle/service/ssl/ssl.cpp6
-rw-r--r--src/core/hle/service/time/time.cpp24
-rw-r--r--src/core/hle/service/vi/vi.cpp53
-rw-r--r--src/core/hw/hw.cpp10
-rw-r--r--src/core/hw/lcd.cpp8
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp8
-rw-r--r--src/core/loader/elf.cpp26
-rw-r--r--src/core/loader/linker.cpp4
-rw-r--r--src/core/loader/loader.cpp8
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp7
-rw-r--r--src/core/memory.cpp112
-rw-r--r--src/core/memory.h3
-rw-r--r--src/video_core/command_processor.cpp45
-rw-r--r--src/video_core/engines/fermi_2d.cpp61
-rw-r--r--src/video_core/engines/fermi_2d.h89
-rw-r--r--src/video_core/engines/maxwell_3d.cpp71
-rw-r--r--src/video_core/engines/maxwell_3d.h54
-rw-r--r--src/video_core/engines/shader_bytecode.h43
-rw-r--r--src/video_core/gpu.cpp14
-rw-r--r--src/video_core/gpu.h10
-rw-r--r--src/video_core/memory_manager.cpp121
-rw-r--r--src/video_core/memory_manager.h36
-rw-r--r--src/video_core/rasterizer_interface.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp147
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h13
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp147
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h86
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp55
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp19
-rw-r--r--src/video_core/textures/decoders.cpp6
-rw-r--r--src/video_core/textures/decoders.h4
-rw-r--r--src/video_core/video_core.cpp6
-rw-r--r--src/yuzu/debugger/graphics/graphics_surface.cpp10
-rw-r--r--src/yuzu/debugger/wait_tree.cpp86
-rw-r--r--src/yuzu/debugger/wait_tree.h43
110 files changed, 1811 insertions, 2244 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 32cb85de0..f49a31612 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -31,7 +31,6 @@ add_library(common STATIC
31 bit_set.h 31 bit_set.h
32 break_points.cpp 32 break_points.cpp
33 break_points.h 33 break_points.h
34 chunk_file.h
35 cityhash.cpp 34 cityhash.cpp
36 cityhash.h 35 cityhash.h
37 color.h 36 color.h
@@ -41,7 +40,6 @@ add_library(common STATIC
41 file_util.cpp 40 file_util.cpp
42 file_util.h 41 file_util.h
43 hash.h 42 hash.h
44 linear_disk_cache.h
45 logging/backend.cpp 43 logging/backend.cpp
46 logging/backend.h 44 logging/backend.h
47 logging/filter.cpp 45 logging/filter.cpp
diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h
deleted file mode 100644
index 972ef9039..000000000
--- a/src/common/chunk_file.h
+++ /dev/null
@@ -1,623 +0,0 @@
1// Copyright (C) 2003 Dolphin Project.
2
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, version 2.0 or later versions.
6
7// This program is distributed in the hope that it will be useful,
8// but WITHOUT ANY WARRANTY; without even the implied warranty of
9// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10// GNU General Public License 2.0 for more details.
11
12// A copy of the GPL 2.0 should have been included with the program.
13// If not, see http://www.gnu.org/licenses/
14
15// Official SVN repository and contact information can be found at
16// http://code.google.com/p/dolphin-emu/
17
18#pragma once
19
20// Extremely simple serialization framework.
21
22// (mis)-features:
23// + Super fast
24// + Very simple
25// + Same code is used for serialization and deserializaition (in most cases)
26// - Zero backwards/forwards compatibility
27// - Serialization code for anything complex has to be manually written.
28
29#include <cstring>
30#include <deque>
31#include <list>
32#include <map>
33#include <set>
34#include <string>
35#include <type_traits>
36#include <utility>
37#include <vector>
38#include "common/assert.h"
39#include "common/common_types.h"
40#include "common/logging/log.h"
41
42template <class T>
43struct LinkedListItem : public T {
44 LinkedListItem<T>* next;
45};
46
47class PointerWrap;
48
49class PointerWrapSection {
50public:
51 PointerWrapSection(PointerWrap& p, int ver, const char* title)
52 : p_(p), ver_(ver), title_(title) {}
53 ~PointerWrapSection();
54
55 bool operator==(const int& v) const {
56 return ver_ == v;
57 }
58 bool operator!=(const int& v) const {
59 return ver_ != v;
60 }
61 bool operator<=(const int& v) const {
62 return ver_ <= v;
63 }
64 bool operator>=(const int& v) const {
65 return ver_ >= v;
66 }
67 bool operator<(const int& v) const {
68 return ver_ < v;
69 }
70 bool operator>(const int& v) const {
71 return ver_ > v;
72 }
73
74 operator bool() const {
75 return ver_ > 0;
76 }
77
78private:
79 PointerWrap& p_;
80 int ver_;
81 const char* title_;
82};
83
84// Wrapper class
85class PointerWrap {
86// This makes it a compile error if you forget to define DoState() on non-POD.
87// Which also can be a problem, for example struct tm is non-POD on linux, for whatever reason...
88#ifdef _MSC_VER
89 template <typename T, bool isPOD = std::is_pod<T>::value,
90 bool isPointer = std::is_pointer<T>::value>
91#else
92 template <typename T, bool isPOD = __is_pod(T), bool isPointer = std::is_pointer<T>::value>
93#endif
94 struct DoHelper {
95 static void DoArray(PointerWrap* p, T* x, int count) {
96 for (int i = 0; i < count; ++i)
97 p->Do(x[i]);
98 }
99
100 static void Do(PointerWrap* p, T& x) {
101 p->DoClass(x);
102 }
103 };
104
105 template <typename T>
106 struct DoHelper<T, true, false> {
107 static void DoArray(PointerWrap* p, T* x, int count) {
108 p->DoVoid((void*)x, sizeof(T) * count);
109 }
110
111 static void Do(PointerWrap* p, T& x) {
112 p->DoVoid((void*)&x, sizeof(x));
113 }
114 };
115
116public:
117 enum Mode {
118 MODE_READ = 1, // load
119 MODE_WRITE, // save
120 MODE_MEASURE, // calculate size
121 MODE_VERIFY, // compare
122 };
123
124 enum Error {
125 ERROR_NONE = 0,
126 ERROR_WARNING = 1,
127 ERROR_FAILURE = 2,
128 };
129
130 u8** ptr;
131 Mode mode;
132 Error error;
133
134public:
135 PointerWrap(u8** ptr_, Mode mode_) : ptr(ptr_), mode(mode_), error(ERROR_NONE) {}
136 PointerWrap(unsigned char** ptr_, int mode_)
137 : ptr((u8**)ptr_), mode((Mode)mode_), error(ERROR_NONE) {}
138
139 PointerWrapSection Section(const char* title, int ver) {
140 return Section(title, ver, ver);
141 }
142
143 // The returned object can be compared against the version that was loaded.
144 // This can be used to support versions as old as minVer.
145 // Version = 0 means the section was not found.
146 PointerWrapSection Section(const char* title, int minVer, int ver) {
147 char marker[16] = {0};
148 int foundVersion = ver;
149
150 strncpy(marker, title, sizeof(marker));
151 if (!ExpectVoid(marker, sizeof(marker))) {
152 // Might be before we added name markers for safety.
153 if (foundVersion == 1 && ExpectVoid(&foundVersion, sizeof(foundVersion)))
154 DoMarker(title);
155 // Wasn't found, but maybe we can still load the state.
156 else
157 foundVersion = 0;
158 } else
159 Do(foundVersion);
160
161 if (error == ERROR_FAILURE || foundVersion < minVer || foundVersion > ver) {
162 LOG_ERROR(Common, "Savestate failure: wrong version %d found for %s", foundVersion,
163 title);
164 SetError(ERROR_FAILURE);
165 return PointerWrapSection(*this, -1, title);
166 }
167 return PointerWrapSection(*this, foundVersion, title);
168 }
169
170 void SetMode(Mode mode_) {
171 mode = mode_;
172 }
173 Mode GetMode() const {
174 return mode;
175 }
176 u8** GetPPtr() {
177 return ptr;
178 }
179 void SetError(Error error_) {
180 if (error < error_)
181 error = error_;
182 if (error > ERROR_WARNING)
183 mode = PointerWrap::MODE_MEASURE;
184 }
185
186 bool ExpectVoid(void* data, int size) {
187 switch (mode) {
188 case MODE_READ:
189 if (memcmp(data, *ptr, size) != 0)
190 return false;
191 break;
192 case MODE_WRITE:
193 memcpy(*ptr, data, size);
194 break;
195 case MODE_MEASURE:
196 break; // MODE_MEASURE - don't need to do anything
197 case MODE_VERIFY:
198 for (int i = 0; i < size; i++) {
199 DEBUG_ASSERT_MSG(
200 ((u8*)data)[i] == (*ptr)[i],
201 "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
202 ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i],
203 &(*ptr)[i]);
204 }
205 break;
206 default:
207 break; // throw an error?
208 }
209 (*ptr) += size;
210 return true;
211 }
212
213 void DoVoid(void* data, int size) {
214 switch (mode) {
215 case MODE_READ:
216 memcpy(data, *ptr, size);
217 break;
218 case MODE_WRITE:
219 memcpy(*ptr, data, size);
220 break;
221 case MODE_MEASURE:
222 break; // MODE_MEASURE - don't need to do anything
223 case MODE_VERIFY:
224 for (int i = 0; i < size; i++) {
225 DEBUG_ASSERT_MSG(
226 ((u8*)data)[i] == (*ptr)[i],
227 "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
228 ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i],
229 &(*ptr)[i]);
230 }
231 break;
232 default:
233 break; // throw an error?
234 }
235 (*ptr) += size;
236 }
237
238 template <class K, class T>
239 void Do(std::map<K, T*>& x) {
240 if (mode == MODE_READ) {
241 for (auto it = x.begin(), end = x.end(); it != end; ++it) {
242 if (it->second != nullptr)
243 delete it->second;
244 }
245 }
246 T* dv = nullptr;
247 DoMap(x, dv);
248 }
249
250 template <class K, class T>
251 void Do(std::map<K, T>& x) {
252 T dv = T();
253 DoMap(x, dv);
254 }
255
256 template <class K, class T>
257 void DoMap(std::map<K, T>& x, T& default_val) {
258 unsigned int number = (unsigned int)x.size();
259 Do(number);
260 switch (mode) {
261 case MODE_READ: {
262 x.clear();
263 while (number > 0) {
264 K first = K();
265 Do(first);
266 T second = default_val;
267 Do(second);
268 x[first] = second;
269 --number;
270 }
271 } break;
272 case MODE_WRITE:
273 case MODE_MEASURE:
274 case MODE_VERIFY: {
275 typename std::map<K, T>::iterator itr = x.begin();
276 while (number > 0) {
277 K first = itr->first;
278 Do(first);
279 Do(itr->second);
280 --number;
281 ++itr;
282 }
283 } break;
284 }
285 }
286
287 template <class K, class T>
288 void Do(std::multimap<K, T*>& x) {
289 if (mode == MODE_READ) {
290 for (auto it = x.begin(), end = x.end(); it != end; ++it) {
291 if (it->second != nullptr)
292 delete it->second;
293 }
294 }
295 T* dv = nullptr;
296 DoMultimap(x, dv);
297 }
298
299 template <class K, class T>
300 void Do(std::multimap<K, T>& x) {
301 T dv = T();
302 DoMultimap(x, dv);
303 }
304
305 template <class K, class T>
306 void DoMultimap(std::multimap<K, T>& x, T& default_val) {
307 unsigned int number = (unsigned int)x.size();
308 Do(number);
309 switch (mode) {
310 case MODE_READ: {
311 x.clear();
312 while (number > 0) {
313 K first = K();
314 Do(first);
315 T second = default_val;
316 Do(second);
317 x.insert(std::make_pair(first, second));
318 --number;
319 }
320 } break;
321 case MODE_WRITE:
322 case MODE_MEASURE:
323 case MODE_VERIFY: {
324 typename std::multimap<K, T>::iterator itr = x.begin();
325 while (number > 0) {
326 Do(itr->first);
327 Do(itr->second);
328 --number;
329 ++itr;
330 }
331 } break;
332 }
333 }
334
335 // Store vectors.
336 template <class T>
337 void Do(std::vector<T*>& x) {
338 T* dv = nullptr;
339 DoVector(x, dv);
340 }
341
342 template <class T>
343 void Do(std::vector<T>& x) {
344 T dv = T();
345 DoVector(x, dv);
346 }
347
348 template <class T>
349 void DoPOD(std::vector<T>& x) {
350 T dv = T();
351 DoVectorPOD(x, dv);
352 }
353
354 template <class T>
355 void Do(std::vector<T>& x, T& default_val) {
356 DoVector(x, default_val);
357 }
358
359 template <class T>
360 void DoVector(std::vector<T>& x, T& default_val) {
361 u32 vec_size = (u32)x.size();
362 Do(vec_size);
363 x.resize(vec_size, default_val);
364 if (vec_size > 0)
365 DoArray(&x[0], vec_size);
366 }
367
368 template <class T>
369 void DoVectorPOD(std::vector<T>& x, T& default_val) {
370 u32 vec_size = (u32)x.size();
371 Do(vec_size);
372 x.resize(vec_size, default_val);
373 if (vec_size > 0)
374 DoArray(&x[0], vec_size);
375 }
376
377 // Store deques.
378 template <class T>
379 void Do(std::deque<T*>& x) {
380 T* dv = nullptr;
381 DoDeque(x, dv);
382 }
383
384 template <class T>
385 void Do(std::deque<T>& x) {
386 T dv = T();
387 DoDeque(x, dv);
388 }
389
390 template <class T>
391 void DoDeque(std::deque<T>& x, T& default_val) {
392 u32 deq_size = (u32)x.size();
393 Do(deq_size);
394 x.resize(deq_size, default_val);
395 u32 i;
396 for (i = 0; i < deq_size; i++)
397 Do(x[i]);
398 }
399
400 // Store STL lists.
401 template <class T>
402 void Do(std::list<T*>& x) {
403 T* dv = nullptr;
404 Do(x, dv);
405 }
406
407 template <class T>
408 void Do(std::list<T>& x) {
409 T dv = T();
410 DoList(x, dv);
411 }
412
413 template <class T>
414 void Do(std::list<T>& x, T& default_val) {
415 DoList(x, default_val);
416 }
417
418 template <class T>
419 void DoList(std::list<T>& x, T& default_val) {
420 u32 list_size = (u32)x.size();
421 Do(list_size);
422 x.resize(list_size, default_val);
423
424 typename std::list<T>::iterator itr, end;
425 for (itr = x.begin(), end = x.end(); itr != end; ++itr)
426 Do(*itr);
427 }
428
429 // Store STL sets.
430 template <class T>
431 void Do(std::set<T*>& x) {
432 if (mode == MODE_READ) {
433 for (auto it = x.begin(), end = x.end(); it != end; ++it) {
434 if (*it != nullptr)
435 delete *it;
436 }
437 }
438 DoSet(x);
439 }
440
441 template <class T>
442 void Do(std::set<T>& x) {
443 DoSet(x);
444 }
445
446 template <class T>
447 void DoSet(std::set<T>& x) {
448 unsigned int number = (unsigned int)x.size();
449 Do(number);
450
451 switch (mode) {
452 case MODE_READ: {
453 x.clear();
454 while (number-- > 0) {
455 T it = T();
456 Do(it);
457 x.insert(it);
458 }
459 } break;
460 case MODE_WRITE:
461 case MODE_MEASURE:
462 case MODE_VERIFY: {
463 typename std::set<T>::iterator itr = x.begin();
464 while (number-- > 0)
465 Do(*itr++);
466 } break;
467
468 default:
469 LOG_ERROR(Common, "Savestate error: invalid mode %d.", mode);
470 }
471 }
472
473 // Store strings.
474 void Do(std::string& x) {
475 int stringLen = (int)x.length() + 1;
476 Do(stringLen);
477
478 switch (mode) {
479 case MODE_READ:
480 x = (char*)*ptr;
481 break;
482 case MODE_WRITE:
483 memcpy(*ptr, x.c_str(), stringLen);
484 break;
485 case MODE_MEASURE:
486 break;
487 case MODE_VERIFY:
488 DEBUG_ASSERT_MSG((x == (char*)*ptr),
489 "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n",
490 x.c_str(), (char*)*ptr, ptr);
491 break;
492 }
493 (*ptr) += stringLen;
494 }
495
496 void Do(std::wstring& x) {
497 int stringLen = sizeof(wchar_t) * ((int)x.length() + 1);
498 Do(stringLen);
499
500 switch (mode) {
501 case MODE_READ:
502 x = (wchar_t*)*ptr;
503 break;
504 case MODE_WRITE:
505 memcpy(*ptr, x.c_str(), stringLen);
506 break;
507 case MODE_MEASURE:
508 break;
509 case MODE_VERIFY:
510 DEBUG_ASSERT_MSG((x == (wchar_t*)*ptr),
511 "Savestate verification failure: \"%ls\" != \"%ls\" (at %p).\n",
512 x.c_str(), (wchar_t*)*ptr, ptr);
513 break;
514 }
515 (*ptr) += stringLen;
516 }
517
518 template <class T>
519 void DoClass(T& x) {
520 x.DoState(*this);
521 }
522
523 template <class T>
524 void DoClass(T*& x) {
525 if (mode == MODE_READ) {
526 if (x != nullptr)
527 delete x;
528 x = new T();
529 }
530 x->DoState(*this);
531 }
532
533 template <class T>
534 void DoArray(T* x, int count) {
535 DoHelper<T>::DoArray(this, x, count);
536 }
537
538 template <class T>
539 void Do(T& x) {
540 DoHelper<T>::Do(this, x);
541 }
542
543 template <class T>
544 void DoPOD(T& x) {
545 DoHelper<T>::Do(this, x);
546 }
547
548 template <class T>
549 void DoPointer(T*& x, T* const base) {
550 // pointers can be more than 2^31 apart, but you're using this function wrong if you need
551 // that much range
552 s32 offset = x - base;
553 Do(offset);
554 if (mode == MODE_READ)
555 x = base + offset;
556 }
557
558 template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*),
559 void (*TDo)(PointerWrap&, T*)>
560 void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end = nullptr) {
561 LinkedListItem<T>* list_cur = list_start;
562 LinkedListItem<T>* prev = nullptr;
563
564 while (true) {
565 u8 shouldExist = (list_cur ? 1 : 0);
566 Do(shouldExist);
567 if (shouldExist == 1) {
568 LinkedListItem<T>* cur = list_cur ? list_cur : TNew();
569 TDo(*this, (T*)cur);
570 if (!list_cur) {
571 if (mode == MODE_READ) {
572 cur->next = nullptr;
573 list_cur = cur;
574 if (prev)
575 prev->next = cur;
576 else
577 list_start = cur;
578 } else {
579 TFree(cur);
580 continue;
581 }
582 }
583 } else {
584 if (mode == MODE_READ) {
585 if (prev)
586 prev->next = nullptr;
587 if (list_end)
588 *list_end = prev;
589 if (list_cur) {
590 if (list_start == list_cur)
591 list_start = nullptr;
592 do {
593 LinkedListItem<T>* next = list_cur->next;
594 TFree(list_cur);
595 list_cur = next;
596 } while (list_cur);
597 }
598 }
599 break;
600 }
601 prev = list_cur;
602 list_cur = list_cur->next;
603 }
604 }
605
606 void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42) {
607 u32 cookie = arbitraryNumber;
608 Do(cookie);
609 if (mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) {
610 LOG_ERROR(Common,
611 "After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). "
612 "Aborting savestate load...",
613 prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
614 SetError(ERROR_FAILURE);
615 }
616 }
617};
618
619inline PointerWrapSection::~PointerWrapSection() {
620 if (ver_ > 0) {
621 p_.DoMarker(title_);
622 }
623}
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h
deleted file mode 100644
index 94c695163..000000000
--- a/src/common/linear_disk_cache.h
+++ /dev/null
@@ -1,167 +0,0 @@
1// Copyright 2013 Dolphin Emulator Project / 2014 Citra 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 <fstream>
8#include "common/common_types.h"
9
10// defined in Version.cpp
11extern const char* scm_rev_git_str;
12
13// On disk format:
14// header{
15// u32 'DCAC';
16// u32 version; // svn_rev
17// u16 sizeof(key_type);
18// u16 sizeof(value_type);
19//}
20
21// key_value_pair{
22// u32 value_size;
23// key_type key;
24// value_type[value_size] value;
25//}
26
27template <typename K, typename V>
28class LinearDiskCacheReader {
29public:
30 virtual void Read(const K& key, const V* value, u32 value_size) = 0;
31};
32
33// Dead simple unsorted key-value store with append functionality.
34// No random read functionality, all reading is done in OpenAndRead.
35// Keys and values can contain any characters, including \0.
36//
37// Suitable for caching generated shader bytecode between executions.
38// Not tuned for extreme performance but should be reasonably fast.
39// Does not support keys or values larger than 2GB, which should be reasonable.
40// Keys must have non-zero length; values can have zero length.
41
42// K and V are some POD type
43// K : the key type
44// V : value array type
45template <typename K, typename V>
46class LinearDiskCache {
47public:
48 // return number of read entries
49 u32 OpenAndRead(const char* filename, LinearDiskCacheReader<K, V>& reader) {
50 using std::ios_base;
51
52 // close any currently opened file
53 Close();
54 m_num_entries = 0;
55
56 // try opening for reading/writing
57 OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
58
59 m_file.seekg(0, std::ios::end);
60 std::fstream::pos_type end_pos = m_file.tellg();
61 m_file.seekg(0, std::ios::beg);
62 std::fstream::pos_type start_pos = m_file.tellg();
63 std::streamoff file_size = end_pos - start_pos;
64
65 if (m_file.is_open() && ValidateHeader()) {
66 // good header, read some key/value pairs
67 K key;
68
69 V* value = nullptr;
70 u32 value_size;
71 u32 entry_number;
72
73 std::fstream::pos_type last_pos = m_file.tellg();
74
75 while (Read(&value_size)) {
76 std::streamoff next_extent =
77 (last_pos - start_pos) + sizeof(value_size) + value_size;
78 if (next_extent > file_size)
79 break;
80
81 delete[] value;
82 value = new V[value_size];
83
84 // read key/value and pass to reader
85 if (Read(&key) && Read(value, value_size) && Read(&entry_number) &&
86 entry_number == m_num_entries + 1) {
87 reader.Read(key, value, value_size);
88 } else {
89 break;
90 }
91
92 m_num_entries++;
93 last_pos = m_file.tellg();
94 }
95 m_file.seekp(last_pos);
96 m_file.clear();
97
98 delete[] value;
99 return m_num_entries;
100 }
101
102 // failed to open file for reading or bad header
103 // close and recreate file
104 Close();
105 m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
106 WriteHeader();
107 return 0;
108 }
109
110 void Sync() {
111 m_file.flush();
112 }
113
114 void Close() {
115 if (m_file.is_open())
116 m_file.close();
117 // clear any error flags
118 m_file.clear();
119 }
120
121 // Appends a key-value pair to the store.
122 void Append(const K& key, const V* value, u32 value_size) {
123 // TODO: Should do a check that we don't already have "key"? (I think each caller does that
124 // already.)
125 Write(&value_size);
126 Write(&key);
127 Write(value, value_size);
128 m_num_entries++;
129 Write(&m_num_entries);
130 }
131
132private:
133 void WriteHeader() {
134 Write(&m_header);
135 }
136
137 bool ValidateHeader() {
138 char file_header[sizeof(Header)];
139
140 return (Read(file_header, sizeof(Header)) &&
141 !memcmp((const char*)&m_header, file_header, sizeof(Header)));
142 }
143
144 template <typename D>
145 bool Write(const D* data, u32 count = 1) {
146 return m_file.write((const char*)data, count * sizeof(D)).good();
147 }
148
149 template <typename D>
150 bool Read(const D* data, u32 count = 1) {
151 return m_file.read((char*)data, count * sizeof(D)).good();
152 }
153
154 struct Header {
155 Header() : id(*(u32*)"DCAC"), key_t_size(sizeof(K)), value_t_size(sizeof(V)) {
156 memcpy(ver, scm_rev_git_str, 40);
157 }
158
159 const u32 id;
160 const u16 key_t_size, value_t_size;
161 char ver[40];
162
163 } m_header;
164
165 std::fstream m_file;
166 u32 m_num_entries;
167};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c2a6f56cd..45dbd6796 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -42,8 +42,6 @@ add_library(core STATIC
42 hle/kernel/client_port.h 42 hle/kernel/client_port.h
43 hle/kernel/client_session.cpp 43 hle/kernel/client_session.cpp
44 hle/kernel/client_session.h 44 hle/kernel/client_session.h
45 hle/kernel/condition_variable.cpp
46 hle/kernel/condition_variable.h
47 hle/kernel/errors.h 45 hle/kernel/errors.h
48 hle/kernel/event.cpp 46 hle/kernel/event.cpp
49 hle/kernel/event.h 47 hle/kernel/event.h
@@ -183,10 +181,10 @@ add_library(core STATIC
183 hle/service/nvflinger/buffer_queue.h 181 hle/service/nvflinger/buffer_queue.h
184 hle/service/nvflinger/nvflinger.cpp 182 hle/service/nvflinger/nvflinger.cpp
185 hle/service/nvflinger/nvflinger.h 183 hle/service/nvflinger/nvflinger.h
184 hle/service/pctl/module.cpp
185 hle/service/pctl/module.h
186 hle/service/pctl/pctl.cpp 186 hle/service/pctl/pctl.cpp
187 hle/service/pctl/pctl.h 187 hle/service/pctl/pctl.h
188 hle/service/pctl/pctl_a.cpp
189 hle/service/pctl/pctl_a.h
190 hle/service/prepo/prepo.cpp 188 hle/service/prepo/prepo.cpp
191 hle/service/prepo/prepo.h 189 hle/service/prepo/prepo.h
192 hle/service/service.cpp 190 hle/service/service.cpp
diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp
index ca1323873..8aa0e0aa4 100644
--- a/src/core/file_sys/disk_filesystem.cpp
+++ b/src/core/file_sys/disk_filesystem.cpp
@@ -67,26 +67,32 @@ ResultCode Disk_FileSystem::DeleteFile(const std::string& path) const {
67 return RESULT_SUCCESS; 67 return RESULT_SUCCESS;
68} 68}
69 69
70ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { 70ResultCode Disk_FileSystem::RenameFile(const std::string& src_path,
71 LOG_WARNING(Service_FS, "(STUBBED) called"); 71 const std::string& dest_path) const {
72 const std::string full_src_path = base_directory + src_path;
73 const std::string full_dest_path = base_directory + dest_path;
74
75 if (!FileUtil::Exists(full_src_path)) {
76 return ERROR_PATH_NOT_FOUND;
77 }
72 // TODO(wwylele): Use correct error code 78 // TODO(wwylele): Use correct error code
73 return ResultCode(-1); 79 return FileUtil::Rename(full_src_path, full_dest_path) ? RESULT_SUCCESS : ResultCode(-1);
74} 80}
75 81
76ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const { 82ResultCode Disk_FileSystem::DeleteDirectory(const Path& path) const {
77 LOG_WARNING(Service_FS, "(STUBBED) called"); 83 NGLOG_WARNING(Service_FS, "(STUBBED) called");
78 // TODO(wwylele): Use correct error code 84 // TODO(wwylele): Use correct error code
79 return ResultCode(-1); 85 return ResultCode(-1);
80} 86}
81 87
82ResultCode Disk_FileSystem::DeleteDirectoryRecursively(const Path& path) const { 88ResultCode Disk_FileSystem::DeleteDirectoryRecursively(const Path& path) const {
83 LOG_WARNING(Service_FS, "(STUBBED) called"); 89 NGLOG_WARNING(Service_FS, "(STUBBED) called");
84 // TODO(wwylele): Use correct error code 90 // TODO(wwylele): Use correct error code
85 return ResultCode(-1); 91 return ResultCode(-1);
86} 92}
87 93
88ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const { 94ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const {
89 LOG_WARNING(Service_FS, "(STUBBED) called"); 95 NGLOG_WARNING(Service_FS, "(STUBBED) called");
90 96
91 std::string full_path = base_directory + path; 97 std::string full_path = base_directory + path;
92 if (size == 0) { 98 if (size == 0) {
@@ -101,7 +107,7 @@ ResultCode Disk_FileSystem::CreateFile(const std::string& path, u64 size) const
101 return RESULT_SUCCESS; 107 return RESULT_SUCCESS;
102 } 108 }
103 109
104 LOG_ERROR(Service_FS, "Too large file"); 110 NGLOG_ERROR(Service_FS, "Too large file");
105 // TODO(Subv): Find out the correct error code 111 // TODO(Subv): Find out the correct error code
106 return ResultCode(-1); 112 return ResultCode(-1);
107} 113}
@@ -114,13 +120,13 @@ ResultCode Disk_FileSystem::CreateDirectory(const std::string& path) const {
114 return RESULT_SUCCESS; 120 return RESULT_SUCCESS;
115 } 121 }
116 122
117 LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating %s", full_path.c_str()); 123 NGLOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating {}", full_path);
118 // TODO(wwylele): Use correct error code 124 // TODO(wwylele): Use correct error code
119 return ResultCode(-1); 125 return ResultCode(-1);
120} 126}
121 127
122ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const { 128ResultCode Disk_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const {
123 LOG_WARNING(Service_FS, "(STUBBED) called"); 129 NGLOG_WARNING(Service_FS, "(STUBBED) called");
124 // TODO(wwylele): Use correct error code 130 // TODO(wwylele): Use correct error code
125 return ResultCode(-1); 131 return ResultCode(-1);
126} 132}
@@ -140,7 +146,7 @@ ResultVal<std::unique_ptr<DirectoryBackend>> Disk_FileSystem::OpenDirectory(
140} 146}
141 147
142u64 Disk_FileSystem::GetFreeSpaceSize() const { 148u64 Disk_FileSystem::GetFreeSpaceSize() const {
143 LOG_WARNING(Service_FS, "(STUBBED) called"); 149 NGLOG_WARNING(Service_FS, "(STUBBED) called");
144 return 0; 150 return 0;
145} 151}
146 152
@@ -157,14 +163,14 @@ ResultVal<FileSys::EntryType> Disk_FileSystem::GetEntryType(const std::string& p
157} 163}
158 164
159ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { 165ResultVal<size_t> Disk_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
160 LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); 166 NGLOG_TRACE(Service_FS, "called offset={}, length={}", offset, length);
161 file->Seek(offset, SEEK_SET); 167 file->Seek(offset, SEEK_SET);
162 return MakeResult<size_t>(file->ReadBytes(buffer, length)); 168 return MakeResult<size_t>(file->ReadBytes(buffer, length));
163} 169}
164 170
165ResultVal<size_t> Disk_Storage::Write(const u64 offset, const size_t length, const bool flush, 171ResultVal<size_t> Disk_Storage::Write(const u64 offset, const size_t length, const bool flush,
166 const u8* buffer) const { 172 const u8* buffer) const {
167 LOG_WARNING(Service_FS, "(STUBBED) called"); 173 NGLOG_WARNING(Service_FS, "(STUBBED) called");
168 file->Seek(offset, SEEK_SET); 174 file->Seek(offset, SEEK_SET);
169 size_t written = file->WriteBytes(buffer, length); 175 size_t written = file->WriteBytes(buffer, length);
170 if (flush) { 176 if (flush) {
@@ -198,8 +204,7 @@ u64 Disk_Directory::Read(const u64 count, Entry* entries) {
198 const std::string& filename = file.virtualName; 204 const std::string& filename = file.virtualName;
199 Entry& entry = entries[entries_read]; 205 Entry& entry = entries[entries_read];
200 206
201 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, 207 NGLOG_TRACE(Service_FS, "File {}: size={} dir={}", filename, file.size, file.isDirectory);
202 file.isDirectory);
203 208
204 // TODO(Link Mauve): use a proper conversion to UTF-16. 209 // TODO(Link Mauve): use a proper conversion to UTF-16.
205 for (size_t j = 0; j < FILENAME_LENGTH; ++j) { 210 for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h
index 8f9e1145a..591e39fda 100644
--- a/src/core/file_sys/disk_filesystem.h
+++ b/src/core/file_sys/disk_filesystem.h
@@ -26,7 +26,7 @@ public:
26 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, 26 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
27 Mode mode) const override; 27 Mode mode) const override;
28 ResultCode DeleteFile(const std::string& path) const override; 28 ResultCode DeleteFile(const std::string& path) const override;
29 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; 29 ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
30 ResultCode DeleteDirectory(const Path& path) const override; 30 ResultCode DeleteDirectory(const Path& path) const override;
31 ResultCode DeleteDirectoryRecursively(const Path& path) const override; 31 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
32 ResultCode CreateFile(const std::string& path, u64 size) const override; 32 ResultCode CreateFile(const std::string& path, u64 size) const override;
diff --git a/src/core/file_sys/filesystem.cpp b/src/core/file_sys/filesystem.cpp
index 82fdb3c46..87083878b 100644
--- a/src/core/file_sys/filesystem.cpp
+++ b/src/core/file_sys/filesystem.cpp
@@ -71,7 +71,7 @@ std::string Path::AsString() const {
71 case Binary: 71 case Binary:
72 default: 72 default:
73 // TODO(yuriks): Add assert 73 // TODO(yuriks): Add assert
74 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); 74 NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
75 return {}; 75 return {};
76 } 76 }
77} 77}
@@ -87,7 +87,7 @@ std::u16string Path::AsU16Str() const {
87 case Invalid: 87 case Invalid:
88 case Binary: 88 case Binary:
89 // TODO(yuriks): Add assert 89 // TODO(yuriks): Add assert
90 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); 90 NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
91 return {}; 91 return {};
92 } 92 }
93 93
@@ -115,7 +115,7 @@ std::vector<u8> Path::AsBinary() const {
115 case Invalid: 115 case Invalid:
116 default: 116 default:
117 // TODO(yuriks): Add assert 117 // TODO(yuriks): Add assert
118 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); 118 NGLOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
119 return {}; 119 return {};
120 } 120 }
121} 121}
diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h
index beefcfdb2..295a3133e 100644
--- a/src/core/file_sys/filesystem.h
+++ b/src/core/file_sys/filesystem.h
@@ -126,7 +126,8 @@ public:
126 * @param dest_path Destination path relative to the archive 126 * @param dest_path Destination path relative to the archive
127 * @return Result of the operation 127 * @return Result of the operation
128 */ 128 */
129 virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; 129 virtual ResultCode RenameFile(const std::string& src_path,
130 const std::string& dest_path) const = 0;
130 131
131 /** 132 /**
132 * Rename a Directory specified by its path 133 * Rename a Directory specified by its path
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 4a58a9291..808254ecc 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -2,7 +2,6 @@
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 <cinttypes>
6#include <utility> 5#include <utility>
7#include "common/file_util.h" 6#include "common/file_util.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
@@ -40,7 +39,7 @@ Loader::ResultStatus PartitionFilesystem::Load(const std::string& file_path, siz
40 39
41 Loader::ResultStatus result = Load(file_data); 40 Loader::ResultStatus result = Load(file_data);
42 if (result != Loader::ResultStatus::Success) 41 if (result != Loader::ResultStatus::Success)
43 LOG_ERROR(Service_FS, "Failed to load PFS from file %s!", file_path.c_str()); 42 NGLOG_ERROR(Service_FS, "Failed to load PFS from file {}!", file_path);
44 43
45 return result; 44 return result;
46} 45}
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index a6dcebcc3..1f5ded514 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -2,7 +2,6 @@
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 <cinttypes>
6#include "common/file_util.h" 5#include "common/file_util.h"
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8#include "core/file_sys/program_metadata.h" 7#include "core/file_sys/program_metadata.h"
@@ -22,7 +21,7 @@ Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
22 21
23 Loader::ResultStatus result = Load(file_data); 22 Loader::ResultStatus result = Load(file_data);
24 if (result != Loader::ResultStatus::Success) 23 if (result != Loader::ResultStatus::Success)
25 LOG_ERROR(Service_FS, "Failed to load NPDM from file %s!", file_path.c_str()); 24 NGLOG_ERROR(Service_FS, "Failed to load NPDM from file {}!", file_path);
26 25
27 return result; 26 return result;
28} 27}
@@ -77,14 +76,14 @@ u64 ProgramMetadata::GetFilesystemPermissions() const {
77} 76}
78 77
79void ProgramMetadata::Print() const { 78void ProgramMetadata::Print() const {
80 LOG_DEBUG(Service_FS, "Magic: %.4s", npdm_header.magic.data()); 79 NGLOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
81 LOG_DEBUG(Service_FS, "Main thread priority: 0x%02x", npdm_header.main_thread_priority); 80 NGLOG_DEBUG(Service_FS, "Main thread priority: {:#04X}", npdm_header.main_thread_priority);
82 LOG_DEBUG(Service_FS, "Main thread core: %u", npdm_header.main_thread_cpu); 81 NGLOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
83 LOG_DEBUG(Service_FS, "Main thread stack size: 0x%x bytes", npdm_header.main_stack_size); 82 NGLOG_DEBUG(Service_FS, "Main thread stack size: {:#X} bytes", npdm_header.main_stack_size);
84 LOG_DEBUG(Service_FS, "Process category: %u", npdm_header.process_category); 83 NGLOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
85 LOG_DEBUG(Service_FS, "Flags: %02x", npdm_header.flags); 84 NGLOG_DEBUG(Service_FS, "Flags: {:02X}", npdm_header.flags);
86 LOG_DEBUG(Service_FS, " > 64-bit instructions: %s", 85 NGLOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
87 npdm_header.has_64_bit_instructions ? "YES" : "NO"); 86 npdm_header.has_64_bit_instructions ? "YES" : "NO");
88 87
89 auto address_space = "Unknown"; 88 auto address_space = "Unknown";
90 switch (npdm_header.address_space_type) { 89 switch (npdm_header.address_space_type) {
@@ -96,19 +95,19 @@ void ProgramMetadata::Print() const {
96 break; 95 break;
97 } 96 }
98 97
99 LOG_DEBUG(Service_FS, " > Address space: %s\n", address_space); 98 NGLOG_DEBUG(Service_FS, " > Address space: {}\n", address_space);
100 99
101 // Begin ACID printing (potential perms, signed) 100 // Begin ACID printing (potential perms, signed)
102 LOG_DEBUG(Service_FS, "Magic: %.4s", acid_header.magic.data()); 101 NGLOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
103 LOG_DEBUG(Service_FS, "Flags: %02x", acid_header.flags); 102 NGLOG_DEBUG(Service_FS, "Flags: {:02X}", acid_header.flags);
104 LOG_DEBUG(Service_FS, " > Is Retail: %s", acid_header.is_retail ? "YES" : "NO"); 103 NGLOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
105 LOG_DEBUG(Service_FS, "Title ID Min: %016" PRIX64, acid_header.title_id_min); 104 NGLOG_DEBUG(Service_FS, "Title ID Min: {:016X}", acid_header.title_id_min);
106 LOG_DEBUG(Service_FS, "Title ID Max: %016" PRIX64, acid_header.title_id_max); 105 NGLOG_DEBUG(Service_FS, "Title ID Max: {:016X}", acid_header.title_id_max);
107 LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", acid_file_access.permissions); 106 NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", acid_file_access.permissions);
108 107
109 // Begin ACI0 printing (actual perms, unsigned) 108 // Begin ACI0 printing (actual perms, unsigned)
110 LOG_DEBUG(Service_FS, "Magic: %.4s", aci_header.magic.data()); 109 NGLOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
111 LOG_DEBUG(Service_FS, "Title ID: %016" PRIX64, aci_header.title_id); 110 NGLOG_DEBUG(Service_FS, "Title ID: {:016X}", aci_header.title_id);
112 LOG_DEBUG(Service_FS, "Filesystem Access: %016" PRIX64 "\n", aci_file_access.permissions); 111 NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", aci_file_access.permissions);
113} 112}
114} // namespace FileSys 113} // namespace FileSys
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp
index b21427948..dc7591aca 100644
--- a/src/core/file_sys/romfs_factory.cpp
+++ b/src/core/file_sys/romfs_factory.cpp
@@ -14,7 +14,7 @@ namespace FileSys {
14RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) { 14RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) {
15 // Load the RomFS from the app 15 // Load the RomFS from the app
16 if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) { 16 if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) {
17 LOG_ERROR(Service_FS, "Unable to read RomFS!"); 17 NGLOG_ERROR(Service_FS, "Unable to read RomFS!");
18 } 18 }
19} 19}
20 20
@@ -24,13 +24,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> RomFS_Factory::Open(const Path& pa
24} 24}
25 25
26ResultCode RomFS_Factory::Format(const Path& path) { 26ResultCode RomFS_Factory::Format(const Path& path) {
27 LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); 27 NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
28 // TODO(bunnei): Find the right error code for this 28 // TODO(bunnei): Find the right error code for this
29 return ResultCode(-1); 29 return ResultCode(-1);
30} 30}
31 31
32ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const { 32ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const {
33 LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); 33 NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
34 // TODO(bunnei): Find the right error code for this 34 // TODO(bunnei): Find the right error code for this
35 return ResultCode(-1); 35 return ResultCode(-1);
36} 36}
diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp
index 3d77e2d5f..8e2bce687 100644
--- a/src/core/file_sys/romfs_filesystem.cpp
+++ b/src/core/file_sys/romfs_filesystem.cpp
@@ -21,73 +21,72 @@ ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const std:
21} 21}
22 22
23ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const { 23ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const {
24 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", 24 NGLOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive ({}).", GetName());
25 GetName().c_str());
26 // TODO(bunnei): Use correct error code 25 // TODO(bunnei): Use correct error code
27 return ResultCode(-1); 26 return ResultCode(-1);
28} 27}
29 28
30ResultCode RomFS_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { 29ResultCode RomFS_FileSystem::RenameFile(const std::string& src_path,
31 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", 30 const std::string& dest_path) const {
32 GetName().c_str()); 31 NGLOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive ({}).",
32 GetName());
33 // TODO(wwylele): Use correct error code 33 // TODO(wwylele): Use correct error code
34 return ResultCode(-1); 34 return ResultCode(-1);
35} 35}
36 36
37ResultCode RomFS_FileSystem::DeleteDirectory(const Path& path) const { 37ResultCode RomFS_FileSystem::DeleteDirectory(const Path& path) const {
38 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", 38 NGLOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive ({}).",
39 GetName().c_str()); 39 GetName());
40 // TODO(wwylele): Use correct error code 40 // TODO(wwylele): Use correct error code
41 return ResultCode(-1); 41 return ResultCode(-1);
42} 42}
43 43
44ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const { 44ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const {
45 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", 45 NGLOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive ({}).",
46 GetName().c_str()); 46 GetName());
47 // TODO(wwylele): Use correct error code 47 // TODO(wwylele): Use correct error code
48 return ResultCode(-1); 48 return ResultCode(-1);
49} 49}
50 50
51ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const { 51ResultCode RomFS_FileSystem::CreateFile(const std::string& path, u64 size) const {
52 LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", 52 NGLOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive ({}).", GetName());
53 GetName().c_str());
54 // TODO(bunnei): Use correct error code 53 // TODO(bunnei): Use correct error code
55 return ResultCode(-1); 54 return ResultCode(-1);
56} 55}
57 56
58ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const { 57ResultCode RomFS_FileSystem::CreateDirectory(const std::string& path) const {
59 LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", 58 NGLOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive ({}).",
60 GetName().c_str()); 59 GetName());
61 // TODO(wwylele): Use correct error code 60 // TODO(wwylele): Use correct error code
62 return ResultCode(-1); 61 return ResultCode(-1);
63} 62}
64 63
65ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const { 64ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const {
66 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", 65 NGLOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive ({}).",
67 GetName().c_str()); 66 GetName());
68 // TODO(wwylele): Use correct error code 67 // TODO(wwylele): Use correct error code
69 return ResultCode(-1); 68 return ResultCode(-1);
70} 69}
71 70
72ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory( 71ResultVal<std::unique_ptr<DirectoryBackend>> RomFS_FileSystem::OpenDirectory(
73 const std::string& path) const { 72 const std::string& path) const {
74 LOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive"); 73 NGLOG_WARNING(Service_FS, "Opening Directory in a ROMFS archive");
75 return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>()); 74 return MakeResult<std::unique_ptr<DirectoryBackend>>(std::make_unique<ROMFSDirectory>());
76} 75}
77 76
78u64 RomFS_FileSystem::GetFreeSpaceSize() const { 77u64 RomFS_FileSystem::GetFreeSpaceSize() const {
79 LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); 78 NGLOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive");
80 return 0; 79 return 0;
81} 80}
82 81
83ResultVal<FileSys::EntryType> RomFS_FileSystem::GetEntryType(const std::string& path) const { 82ResultVal<FileSys::EntryType> RomFS_FileSystem::GetEntryType(const std::string& path) const {
84 LOG_CRITICAL(Service_FS, "Called within an ROMFS archive (path %s).", path.c_str()); 83 NGLOG_CRITICAL(Service_FS, "Called within an ROMFS archive (path {}).", path);
85 // TODO(wwylele): Use correct error code 84 // TODO(wwylele): Use correct error code
86 return ResultCode(-1); 85 return ResultCode(-1);
87} 86}
88 87
89ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { 88ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const {
90 LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); 89 NGLOG_TRACE(Service_FS, "called offset={}, length={}", offset, length);
91 romfs_file->Seek(data_offset + offset, SEEK_SET); 90 romfs_file->Seek(data_offset + offset, SEEK_SET);
92 size_t read_length = (size_t)std::min((u64)length, data_size - offset); 91 size_t read_length = (size_t)std::min((u64)length, data_size - offset);
93 92
@@ -96,7 +95,7 @@ ResultVal<size_t> RomFS_Storage::Read(const u64 offset, const size_t length, u8*
96 95
97ResultVal<size_t> RomFS_Storage::Write(const u64 offset, const size_t length, const bool flush, 96ResultVal<size_t> RomFS_Storage::Write(const u64 offset, const size_t length, const bool flush,
98 const u8* buffer) const { 97 const u8* buffer) const {
99 LOG_ERROR(Service_FS, "Attempted to write to ROMFS file"); 98 NGLOG_ERROR(Service_FS, "Attempted to write to ROMFS file");
100 // TODO(Subv): Find error code 99 // TODO(Subv): Find error code
101 return MakeResult<size_t>(0); 100 return MakeResult<size_t>(0);
102} 101}
@@ -106,7 +105,7 @@ u64 RomFS_Storage::GetSize() const {
106} 105}
107 106
108bool RomFS_Storage::SetSize(const u64 size) const { 107bool RomFS_Storage::SetSize(const u64 size) const {
109 LOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file"); 108 NGLOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file");
110 return false; 109 return false;
111} 110}
112 111
diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h
index 1b5cac409..ba9d85823 100644
--- a/src/core/file_sys/romfs_filesystem.h
+++ b/src/core/file_sys/romfs_filesystem.h
@@ -32,7 +32,7 @@ public:
32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, 32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
33 Mode mode) const override; 33 Mode mode) const override;
34 ResultCode DeleteFile(const std::string& path) const override; 34 ResultCode DeleteFile(const std::string& path) const override;
35 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; 35 ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const override;
36 ResultCode DeleteDirectory(const Path& path) const override; 36 ResultCode DeleteDirectory(const Path& path) const override;
37 ResultCode DeleteDirectoryRecursively(const Path& path) const override; 37 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
38 ResultCode CreateFile(const std::string& path, u64 size) const override; 38 ResultCode CreateFile(const std::string& path, u64 size) const override;
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 14868fed2..c1be8fee4 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -2,11 +2,9 @@
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 <cinttypes>
6#include <memory> 5#include <memory>
7#include "common/common_types.h" 6#include "common/common_types.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/core.h" 8#include "core/core.h"
11#include "core/file_sys/disk_filesystem.h" 9#include "core/file_sys/disk_filesystem.h"
12#include "core/file_sys/savedata_factory.h" 10#include "core/file_sys/savedata_factory.h"
@@ -30,7 +28,7 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path&
30} 28}
31 29
32ResultCode SaveData_Factory::Format(const Path& path) { 30ResultCode SaveData_Factory::Format(const Path& path) {
33 LOG_WARNING(Service_FS, "Format archive %s", GetName().c_str()); 31 NGLOG_WARNING(Service_FS, "Format archive {}", GetName());
34 // Create the save data directory. 32 // Create the save data directory.
35 if (!FileUtil::CreateFullPath(GetFullPath())) { 33 if (!FileUtil::CreateFullPath(GetFullPath())) {
36 // TODO(Subv): Find the correct error code. 34 // TODO(Subv): Find the correct error code.
@@ -41,7 +39,7 @@ ResultCode SaveData_Factory::Format(const Path& path) {
41} 39}
42 40
43ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const { 41ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const {
44 LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); 42 NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
45 // TODO(bunnei): Find the right error code for this 43 // TODO(bunnei): Find the right error code for this
46 return ResultCode(-1); 44 return ResultCode(-1);
47} 45}
@@ -50,8 +48,7 @@ std::string SaveData_Factory::GetFullPath() const {
50 u64 title_id = Core::CurrentProcess()->program_id; 48 u64 title_id = Core::CurrentProcess()->program_id;
51 // TODO(Subv): Somehow obtain this value. 49 // TODO(Subv): Somehow obtain this value.
52 u32 user = 0; 50 u32 user = 0;
53 return Common::StringFromFormat("%ssave/%016" PRIX64 "/%08X/", nand_directory.c_str(), title_id, 51 return fmt::format("{}save/{:016X}/{:08X}/", nand_directory, title_id, user);
54 user);
55} 52}
56 53
57} // namespace FileSys 54} // namespace FileSys
diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp
index 00e80d2a7..59ac3e0be 100644
--- a/src/core/file_sys/sdmc_factory.cpp
+++ b/src/core/file_sys/sdmc_factory.cpp
@@ -2,7 +2,6 @@
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 <cinttypes>
6#include <memory> 5#include <memory>
7#include "common/common_types.h" 6#include "common/common_types.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
@@ -26,13 +25,13 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& pat
26} 25}
27 26
28ResultCode SDMC_Factory::Format(const Path& path) { 27ResultCode SDMC_Factory::Format(const Path& path) {
29 LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); 28 NGLOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName());
30 // TODO(Subv): Find the right error code for this 29 // TODO(Subv): Find the right error code for this
31 return ResultCode(-1); 30 return ResultCode(-1);
32} 31}
33 32
34ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const { 33ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const {
35 LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); 34 NGLOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName());
36 // TODO(bunnei): Find the right error code for this 35 // TODO(bunnei): Find the right error code for this
37 return ResultCode(-1); 36 return ResultCode(-1);
38} 37}
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index e4f337a0a..46606b992 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -6,7 +6,6 @@
6 6
7#include <algorithm> 7#include <algorithm>
8#include <atomic> 8#include <atomic>
9#include <cinttypes>
10#include <climits> 9#include <climits>
11#include <csignal> 10#include <csignal>
12#include <cstdarg> 11#include <cstdarg>
@@ -180,7 +179,7 @@ static u8 HexCharToValue(u8 hex) {
180 return hex - 'A' + 0xA; 179 return hex - 'A' + 0xA;
181 } 180 }
182 181
183 LOG_ERROR(Debug_GDBStub, "Invalid nibble: %c (%02x)\n", hex, hex); 182 NGLOG_ERROR(Debug_GDBStub, "Invalid nibble: {} ({:02X})", hex, hex);
184 return 0; 183 return 0;
185} 184}
186 185
@@ -320,7 +319,7 @@ static u8 ReadByte() {
320 u8 c; 319 u8 c;
321 size_t received_size = recv(gdbserver_socket, reinterpret_cast<char*>(&c), 1, MSG_WAITALL); 320 size_t received_size = recv(gdbserver_socket, reinterpret_cast<char*>(&c), 1, MSG_WAITALL);
322 if (received_size != 1) { 321 if (received_size != 1) {
323 LOG_ERROR(Debug_GDBStub, "recv failed : %ld", received_size); 322 NGLOG_ERROR(Debug_GDBStub, "recv failed: {}", received_size);
324 Shutdown(); 323 Shutdown();
325 } 324 }
326 325
@@ -361,9 +360,8 @@ static void RemoveBreakpoint(BreakpointType type, PAddr addr) {
361 360
362 auto bp = p.find(static_cast<u64>(addr)); 361 auto bp = p.find(static_cast<u64>(addr));
363 if (bp != p.end()) { 362 if (bp != p.end()) {
364 LOG_DEBUG(Debug_GDBStub, 363 NGLOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
365 "gdb: removed a breakpoint: %016" PRIx64 " bytes at %016" PRIx64 " of type %d\n", 364 bp->second.len, bp->second.addr, static_cast<int>(type));
366 bp->second.len, bp->second.addr, static_cast<int>(type));
367 p.erase(static_cast<u64>(addr)); 365 p.erase(static_cast<u64>(addr));
368 } 366 }
369} 367}
@@ -408,10 +406,10 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) {
408 } 406 }
409 407
410 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { 408 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
411 LOG_DEBUG(Debug_GDBStub, 409 NGLOG_DEBUG(Debug_GDBStub,
412 "Found breakpoint type %d @ %016" PRIx64 ", range: %016" PRIx64 410 "Found breakpoint type {} @ {:016X}, range: {:016X}"
413 " - %016" PRIx64 " (%" PRIx64 " bytes)\n", 411 " - {:016X} ({:X} bytes)",
414 static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len); 412 static_cast<int>(type), addr, bp->second.addr, bp->second.addr + len, len);
415 return true; 413 return true;
416 } 414 }
417 } 415 }
@@ -427,7 +425,7 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) {
427static void SendPacket(const char packet) { 425static void SendPacket(const char packet) {
428 size_t sent_size = send(gdbserver_socket, &packet, 1, 0); 426 size_t sent_size = send(gdbserver_socket, &packet, 1, 0);
429 if (sent_size != 1) { 427 if (sent_size != 1) {
430 LOG_ERROR(Debug_GDBStub, "send failed"); 428 NGLOG_ERROR(Debug_GDBStub, "send failed");
431 } 429 }
432} 430}
433 431
@@ -445,7 +443,7 @@ static void SendReply(const char* reply) {
445 443
446 command_length = static_cast<u32>(strlen(reply)); 444 command_length = static_cast<u32>(strlen(reply));
447 if (command_length + 4 > sizeof(command_buffer)) { 445 if (command_length + 4 > sizeof(command_buffer)) {
448 LOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply"); 446 NGLOG_ERROR(Debug_GDBStub, "command_buffer overflow in SendReply");
449 return; 447 return;
450 } 448 }
451 449
@@ -462,7 +460,7 @@ static void SendReply(const char* reply) {
462 while (left > 0) { 460 while (left > 0) {
463 int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0); 461 int sent_size = send(gdbserver_socket, reinterpret_cast<char*>(ptr), left, 0);
464 if (sent_size < 0) { 462 if (sent_size < 0) {
465 LOG_ERROR(Debug_GDBStub, "gdb: send failed"); 463 NGLOG_ERROR(Debug_GDBStub, "gdb: send failed");
466 return Shutdown(); 464 return Shutdown();
467 } 465 }
468 466
@@ -473,7 +471,7 @@ static void SendReply(const char* reply) {
473 471
474/// Handle query command from gdb client. 472/// Handle query command from gdb client.
475static void HandleQuery() { 473static void HandleQuery() {
476 LOG_DEBUG(Debug_GDBStub, "gdb: query '%s'\n", command_buffer + 1); 474 NGLOG_DEBUG(Debug_GDBStub, "gdb: query '{}'", command_buffer + 1);
477 475
478 const char* query = reinterpret_cast<const char*>(command_buffer + 1); 476 const char* query = reinterpret_cast<const char*>(command_buffer + 1);
479 477
@@ -512,8 +510,8 @@ static void SendSignal(u32 signal) {
512 510
513 latest_signal = signal; 511 latest_signal = signal;
514 512
515 std::string buffer = Common::StringFromFormat("T%02x", latest_signal); 513 std::string buffer = fmt::format("T{:02x}", latest_signal);
516 LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); 514 NGLOG_DEBUG(Debug_GDBStub, "Response: {}", buffer);
517 SendReply(buffer.c_str()); 515 SendReply(buffer.c_str());
518} 516}
519 517
@@ -527,18 +525,18 @@ static void ReadCommand() {
527 // ignore ack 525 // ignore ack
528 return; 526 return;
529 } else if (c == 0x03) { 527 } else if (c == 0x03) {
530 LOG_INFO(Debug_GDBStub, "gdb: found break command\n"); 528 NGLOG_INFO(Debug_GDBStub, "gdb: found break command");
531 halt_loop = true; 529 halt_loop = true;
532 SendSignal(SIGTRAP); 530 SendSignal(SIGTRAP);
533 return; 531 return;
534 } else if (c != GDB_STUB_START) { 532 } else if (c != GDB_STUB_START) {
535 LOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte %02x\n", c); 533 NGLOG_DEBUG(Debug_GDBStub, "gdb: read invalid byte {:02X}", c);
536 return; 534 return;
537 } 535 }
538 536
539 while ((c = ReadByte()) != GDB_STUB_END) { 537 while ((c = ReadByte()) != GDB_STUB_END) {
540 if (command_length >= sizeof(command_buffer)) { 538 if (command_length >= sizeof(command_buffer)) {
541 LOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow\n"); 539 NGLOG_ERROR(Debug_GDBStub, "gdb: command_buffer overflow");
542 SendPacket(GDB_STUB_NACK); 540 SendPacket(GDB_STUB_NACK);
543 return; 541 return;
544 } 542 }
@@ -551,9 +549,10 @@ static void ReadCommand() {
551 u8 checksum_calculated = CalculateChecksum(command_buffer, command_length); 549 u8 checksum_calculated = CalculateChecksum(command_buffer, command_length);
552 550
553 if (checksum_received != checksum_calculated) { 551 if (checksum_received != checksum_calculated) {
554 LOG_ERROR(Debug_GDBStub, 552 NGLOG_ERROR(
555 "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n", 553 Debug_GDBStub,
556 checksum_calculated, checksum_received, command_buffer, command_length); 554 "gdb: invalid checksum: calculated {:02X} and read {:02X} for ${}# (length: {})",
555 checksum_calculated, checksum_received, command_buffer, command_length);
557 556
558 command_length = 0; 557 command_length = 0;
559 558
@@ -580,7 +579,7 @@ static bool IsDataAvailable() {
580 t.tv_usec = 0; 579 t.tv_usec = 0;
581 580
582 if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) { 581 if (select(gdbserver_socket + 1, &fd_socket, nullptr, nullptr, &t) < 0) {
583 LOG_ERROR(Debug_GDBStub, "select failed"); 582 NGLOG_ERROR(Debug_GDBStub, "select failed");
584 return false; 583 return false;
585 } 584 }
586 585
@@ -693,7 +692,7 @@ static void ReadMemory() {
693 u64 len = 692 u64 len =
694 HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset)); 693 HexToLong(start_offset, static_cast<u64>((command_buffer + command_length) - start_offset));
695 694
696 LOG_DEBUG(Debug_GDBStub, "gdb: addr: %016lx len: %016lx\n", addr, len); 695 NGLOG_DEBUG(Debug_GDBStub, "gdb: addr: {:016X} len: {:016X}", addr, len);
697 696
698 if (len * 2 > sizeof(reply)) { 697 if (len * 2 > sizeof(reply)) {
699 SendReply("E01"); 698 SendReply("E01");
@@ -781,8 +780,8 @@ static bool CommitBreakpoint(BreakpointType type, PAddr addr, u64 len) {
781 breakpoint.len = len; 780 breakpoint.len = len;
782 p.insert({addr, breakpoint}); 781 p.insert({addr, breakpoint});
783 782
784 LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %016" PRIx64 " bytes at %016" PRIx64 "\n", 783 NGLOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",
785 static_cast<int>(type), breakpoint.len, breakpoint.addr); 784 static_cast<int>(type), breakpoint.len, breakpoint.addr);
786 785
787 return true; 786 return true;
788} 787}
@@ -889,7 +888,7 @@ void HandlePacket() {
889 return; 888 return;
890 } 889 }
891 890
892 LOG_DEBUG(Debug_GDBStub, "Packet: %s", command_buffer); 891 NGLOG_DEBUG(Debug_GDBStub, "Packet: {}", command_buffer);
893 892
894 switch (command_buffer[0]) { 893 switch (command_buffer[0]) {
895 case 'q': 894 case 'q':
@@ -903,7 +902,7 @@ void HandlePacket() {
903 break; 902 break;
904 case 'k': 903 case 'k':
905 Shutdown(); 904 Shutdown();
906 LOG_INFO(Debug_GDBStub, "killed by gdb"); 905 NGLOG_INFO(Debug_GDBStub, "killed by gdb");
907 return; 906 return;
908 case 'g': 907 case 'g':
909 ReadRegisters(); 908 ReadRegisters();
@@ -982,7 +981,7 @@ static void Init(u16 port) {
982 breakpoints_write.clear(); 981 breakpoints_write.clear();
983 982
984 // Start gdb server 983 // Start gdb server
985 LOG_INFO(Debug_GDBStub, "Starting GDB server on port %d...", port); 984 NGLOG_INFO(Debug_GDBStub, "Starting GDB server on port {}...", port);
986 985
987 sockaddr_in saddr_server = {}; 986 sockaddr_in saddr_server = {};
988 saddr_server.sin_family = AF_INET; 987 saddr_server.sin_family = AF_INET;
@@ -995,28 +994,28 @@ static void Init(u16 port) {
995 994
996 int tmpsock = static_cast<int>(socket(PF_INET, SOCK_STREAM, 0)); 995 int tmpsock = static_cast<int>(socket(PF_INET, SOCK_STREAM, 0));
997 if (tmpsock == -1) { 996 if (tmpsock == -1) {
998 LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket"); 997 NGLOG_ERROR(Debug_GDBStub, "Failed to create gdb socket");
999 } 998 }
1000 999
1001 // Set socket to SO_REUSEADDR so it can always bind on the same port 1000 // Set socket to SO_REUSEADDR so it can always bind on the same port
1002 int reuse_enabled = 1; 1001 int reuse_enabled = 1;
1003 if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, 1002 if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled,
1004 sizeof(reuse_enabled)) < 0) { 1003 sizeof(reuse_enabled)) < 0) {
1005 LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); 1004 NGLOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option");
1006 } 1005 }
1007 1006
1008 const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server); 1007 const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server);
1009 socklen_t server_addrlen = sizeof(saddr_server); 1008 socklen_t server_addrlen = sizeof(saddr_server);
1010 if (bind(tmpsock, server_addr, server_addrlen) < 0) { 1009 if (bind(tmpsock, server_addr, server_addrlen) < 0) {
1011 LOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket"); 1010 NGLOG_ERROR(Debug_GDBStub, "Failed to bind gdb socket");
1012 } 1011 }
1013 1012
1014 if (listen(tmpsock, 1) < 0) { 1013 if (listen(tmpsock, 1) < 0) {
1015 LOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket"); 1014 NGLOG_ERROR(Debug_GDBStub, "Failed to listen to gdb socket");
1016 } 1015 }
1017 1016
1018 // Wait for gdb to connect 1017 // Wait for gdb to connect
1019 LOG_INFO(Debug_GDBStub, "Waiting for gdb to connect...\n"); 1018 NGLOG_INFO(Debug_GDBStub, "Waiting for gdb to connect...");
1020 sockaddr_in saddr_client; 1019 sockaddr_in saddr_client;
1021 sockaddr* client_addr = reinterpret_cast<sockaddr*>(&saddr_client); 1020 sockaddr* client_addr = reinterpret_cast<sockaddr*>(&saddr_client);
1022 socklen_t client_addrlen = sizeof(saddr_client); 1021 socklen_t client_addrlen = sizeof(saddr_client);
@@ -1027,9 +1026,9 @@ static void Init(u16 port) {
1027 halt_loop = false; 1026 halt_loop = false;
1028 step_loop = false; 1027 step_loop = false;
1029 1028
1030 LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); 1029 NGLOG_ERROR(Debug_GDBStub, "Failed to accept gdb client");
1031 } else { 1030 } else {
1032 LOG_INFO(Debug_GDBStub, "Client connected.\n"); 1031 NGLOG_INFO(Debug_GDBStub, "Client connected.");
1033 saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); 1032 saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr);
1034 } 1033 }
1035 1034
@@ -1048,7 +1047,7 @@ void Shutdown() {
1048 return; 1047 return;
1049 } 1048 }
1050 1049
1051 LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); 1050 NGLOG_INFO(Debug_GDBStub, "Stopping GDB ...");
1052 if (gdbserver_socket != -1) { 1051 if (gdbserver_socket != -1) {
1053 shutdown(gdbserver_socket, SHUT_RDWR); 1052 shutdown(gdbserver_socket, SHUT_RDWR);
1054 gdbserver_socket = -1; 1053 gdbserver_socket = -1;
@@ -1058,7 +1057,7 @@ void Shutdown() {
1058 WSACleanup(); 1057 WSACleanup();
1059#endif 1058#endif
1060 1059
1061 LOG_INFO(Debug_GDBStub, "GDB stopped."); 1060 NGLOG_INFO(Debug_GDBStub, "GDB stopped.");
1062} 1061}
1063 1062
1064bool IsServerEnabled() { 1063bool IsServerEnabled() {
diff --git a/src/core/hle/kernel/condition_variable.cpp b/src/core/hle/kernel/condition_variable.cpp
deleted file mode 100644
index a786d7f74..000000000
--- a/src/core/hle/kernel/condition_variable.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
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 "common/assert.h"
6#include "core/hle/kernel/condition_variable.h"
7#include "core/hle/kernel/errors.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/object_address_table.h"
10#include "core/hle/kernel/thread.h"
11
12namespace Kernel {
13
14ConditionVariable::ConditionVariable() {}
15ConditionVariable::~ConditionVariable() {}
16
17ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
18 std::string name) {
19 SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
20
21 condition_variable->name = std::move(name);
22 condition_variable->guest_addr = guest_addr;
23 condition_variable->mutex_addr = 0;
24
25 // Condition variables are referenced by guest address, so track this in the kernel
26 g_object_address_table.Insert(guest_addr, condition_variable);
27
28 return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable));
29}
30
31bool ConditionVariable::ShouldWait(Thread* thread) const {
32 return GetAvailableCount() <= 0;
33}
34
35void ConditionVariable::Acquire(Thread* thread) {
36 if (GetAvailableCount() <= 0)
37 return;
38
39 SetAvailableCount(GetAvailableCount() - 1);
40}
41
42ResultCode ConditionVariable::Release(s32 target) {
43 if (target == -1) {
44 // When -1, wake up all waiting threads
45 SetAvailableCount(static_cast<s32>(GetWaitingThreads().size()));
46 WakeupAllWaitingThreads();
47 } else {
48 // Otherwise, wake up just a single thread
49 SetAvailableCount(target);
50 WakeupWaitingThread(GetHighestPriorityReadyThread());
51 }
52
53 return RESULT_SUCCESS;
54}
55
56s32 ConditionVariable::GetAvailableCount() const {
57 return Memory::Read32(guest_addr);
58}
59
60void ConditionVariable::SetAvailableCount(s32 value) const {
61 Memory::Write32(guest_addr, value);
62}
63
64} // namespace Kernel
diff --git a/src/core/hle/kernel/condition_variable.h b/src/core/hle/kernel/condition_variable.h
deleted file mode 100644
index 1c9f06769..000000000
--- a/src/core/hle/kernel/condition_variable.h
+++ /dev/null
@@ -1,63 +0,0 @@
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 <string>
8#include <queue>
9#include "common/common_types.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/wait_object.h"
12#include "core/hle/result.h"
13
14namespace Kernel {
15
16class ConditionVariable final : public WaitObject {
17public:
18 /**
19 * Creates a condition variable.
20 * @param guest_addr Address of the object tracking the condition variable in guest memory. If
21 * specified, this condition variable will update the guest object when its state changes.
22 * @param name Optional name of condition variable.
23 * @return The created condition variable.
24 */
25 static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
26 std::string name = "Unknown");
27
28 std::string GetTypeName() const override {
29 return "ConditionVariable";
30 }
31 std::string GetName() const override {
32 return name;
33 }
34
35 static const HandleType HANDLE_TYPE = HandleType::ConditionVariable;
36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
39
40 s32 GetAvailableCount() const;
41 void SetAvailableCount(s32 value) const;
42
43 std::string name; ///< Name of condition variable (optional)
44 VAddr guest_addr; ///< Address of the guest condition variable value
45 VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition
46 ///< variable, used for implementing events
47
48 bool ShouldWait(Thread* thread) const override;
49 void Acquire(Thread* thread) override;
50
51 /**
52 * Releases a slot from a condition variable.
53 * @param target The number of threads to wakeup, -1 is all.
54 * @return ResultCode indicating if the operation succeeded.
55 */
56 ResultCode Release(s32 target);
57
58private:
59 ConditionVariable();
60 ~ConditionVariable() override;
61};
62
63} // namespace Kernel
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 29d8dfdaa..5be20c878 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -20,6 +20,7 @@ enum {
20 MaxConnectionsReached = 52, 20 MaxConnectionsReached = 52,
21 21
22 // Confirmed Switch OS error codes 22 // Confirmed Switch OS error codes
23 MisalignedAddress = 102,
23 InvalidHandle = 114, 24 InvalidHandle = 114,
24 Timeout = 117, 25 Timeout = 117,
25 SynchronizationCanceled = 118, 26 SynchronizationCanceled = 118,
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 822449cd5..f7a9920d8 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -26,7 +26,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
26 26
27 u16 slot = next_free_slot; 27 u16 slot = next_free_slot;
28 if (slot >= generations.size()) { 28 if (slot >= generations.size()) {
29 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); 29 NGLOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
30 return ERR_OUT_OF_HANDLES; 30 return ERR_OUT_OF_HANDLES;
31 } 31 }
32 next_free_slot = generations[slot]; 32 next_free_slot = generations[slot];
@@ -48,7 +48,7 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
48ResultVal<Handle> HandleTable::Duplicate(Handle handle) { 48ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
49 SharedPtr<Object> object = GetGeneric(handle); 49 SharedPtr<Object> object = GetGeneric(handle);
50 if (object == nullptr) { 50 if (object == nullptr) {
51 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); 51 NGLOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
52 return ERR_INVALID_HANDLE; 52 return ERR_INVALID_HANDLE;
53 } 53 }
54 return Create(std::move(object)); 54 return Create(std::move(object));
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index bef4f15f5..aa6ca1026 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -118,7 +118,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
118 std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>()); 118 std::make_shared<IPC::DomainMessageHeader>(rp.PopRaw<IPC::DomainMessageHeader>());
119 } else { 119 } else {
120 if (Session()->IsDomain()) 120 if (Session()->IsDomain())
121 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); 121 NGLOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
122 } 122 }
123 } 123 }
124 124
@@ -270,7 +270,8 @@ size_t HLERequestContext::WriteBuffer(const void* buffer, size_t size) const {
270 const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()}; 270 const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[0].Size()};
271 const size_t buffer_size{GetWriteBufferSize()}; 271 const size_t buffer_size{GetWriteBufferSize()};
272 if (size > buffer_size) { 272 if (size > buffer_size) {
273 LOG_CRITICAL(Core, "size (%016zx) is greater than buffer_size (%016zx)", size, buffer_size); 273 NGLOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size,
274 buffer_size);
274 size = buffer_size; // TODO(bunnei): This needs to be HW tested 275 size = buffer_size; // TODO(bunnei): This needs to be HW tested
275 } 276 }
276 277
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 053bf4e17..402ae900f 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -18,12 +18,10 @@ using Handle = u32;
18enum class HandleType : u32 { 18enum class HandleType : u32 {
19 Unknown, 19 Unknown,
20 Event, 20 Event,
21 Mutex,
22 SharedMemory, 21 SharedMemory,
23 Thread, 22 Thread,
24 Process, 23 Process,
25 AddressArbiter, 24 AddressArbiter,
26 ConditionVariable,
27 Timer, 25 Timer,
28 ResourceLimit, 26 ResourceLimit,
29 CodeSet, 27 CodeSet,
@@ -63,9 +61,7 @@ public:
63 bool IsWaitable() const { 61 bool IsWaitable() const {
64 switch (GetHandleType()) { 62 switch (GetHandleType()) {
65 case HandleType::Event: 63 case HandleType::Event:
66 case HandleType::Mutex:
67 case HandleType::Thread: 64 case HandleType::Thread:
68 case HandleType::ConditionVariable:
69 case HandleType::Timer: 65 case HandleType::Timer:
70 case HandleType::ServerPort: 66 case HandleType::ServerPort:
71 case HandleType::ServerSession: 67 case HandleType::ServerSession:
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 0b9dc700c..63733ad79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -7,6 +7,7 @@
7#include <boost/range/algorithm_ext/erase.hpp> 7#include <boost/range/algorithm_ext/erase.hpp>
8#include "common/assert.h" 8#include "common/assert.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/handle_table.h" 11#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/mutex.h" 13#include "core/hle/kernel/mutex.h"
@@ -15,124 +16,120 @@
15 16
16namespace Kernel { 17namespace Kernel {
17 18
18void ReleaseThreadMutexes(Thread* thread) { 19/// Returns the number of threads that are waiting for a mutex, and the highest priority one among
19 for (auto& mtx : thread->held_mutexes) { 20/// those.
20 mtx->SetHasWaiters(false); 21static std::pair<SharedPtr<Thread>, u32> GetHighestPriorityMutexWaitingThread(
21 mtx->SetHoldingThread(nullptr); 22 SharedPtr<Thread> current_thread, VAddr mutex_addr) {
22 mtx->WakeupAllWaitingThreads();
23 }
24 thread->held_mutexes.clear();
25}
26 23
27Mutex::Mutex() {} 24 SharedPtr<Thread> highest_priority_thread;
28Mutex::~Mutex() {} 25 u32 num_waiters = 0;
29 26
30SharedPtr<Mutex> Mutex::Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr, 27 for (auto& thread : current_thread->wait_mutex_threads) {
31 std::string name) { 28 if (thread->mutex_wait_address != mutex_addr)
32 SharedPtr<Mutex> mutex(new Mutex); 29 continue;
33 30
34 mutex->guest_addr = guest_addr; 31 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
35 mutex->name = std::move(name);
36 32
37 // If mutex was initialized with a holding thread, acquire it by the holding thread 33 ++num_waiters;
38 if (holding_thread) { 34 if (highest_priority_thread == nullptr ||
39 mutex->Acquire(holding_thread.get()); 35 thread->GetPriority() < highest_priority_thread->GetPriority()) {
36 highest_priority_thread = thread;
37 }
40 } 38 }
41 39
42 // Mutexes are referenced by guest address, so track this in the kernel 40 return {highest_priority_thread, num_waiters};
43 g_object_address_table.Insert(guest_addr, mutex);
44
45 return mutex;
46} 41}
47 42
48bool Mutex::ShouldWait(Thread* thread) const { 43/// Update the mutex owner field of all threads waiting on the mutex to point to the new owner.
49 auto holding_thread = GetHoldingThread(); 44static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_thread,
50 return holding_thread != nullptr && thread != holding_thread; 45 SharedPtr<Thread> new_owner) {
46 auto threads = current_thread->wait_mutex_threads;
47 for (auto& thread : threads) {
48 if (thread->mutex_wait_address != mutex_addr)
49 continue;
50
51 ASSERT(thread->lock_owner == current_thread);
52 current_thread->RemoveMutexWaiter(thread);
53 if (new_owner != thread)
54 new_owner->AddMutexWaiter(thread);
55 }
51} 56}
52 57
53void Mutex::Acquire(Thread* thread) { 58ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
54 ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); 59 Handle requesting_thread_handle) {
60 // The mutex address must be 4-byte aligned
61 if ((address % sizeof(u32)) != 0) {
62 return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
63 }
55 64
56 priority = thread->current_priority; 65 SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
57 thread->held_mutexes.insert(this); 66 SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
58 SetHoldingThread(thread);
59 thread->UpdatePriority();
60 Core::System::GetInstance().PrepareReschedule();
61}
62 67
63ResultCode Mutex::Release(Thread* thread) { 68 // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
64 auto holding_thread = GetHoldingThread(); 69 // thread.
65 ASSERT(holding_thread); 70 ASSERT(requesting_thread == GetCurrentThread());
66 71
67 // We can only release the mutex if it's held by the calling thread. 72 u32 addr_value = Memory::Read32(address);
68 ASSERT(thread == holding_thread); 73
74 // If the mutex isn't being held, just return success.
75 if (addr_value != (holding_thread_handle | Mutex::MutexHasWaitersFlag)) {
76 return RESULT_SUCCESS;
77 }
78
79 if (holding_thread == nullptr)
80 return ERR_INVALID_HANDLE;
81
82 // Wait until the mutex is released
83 GetCurrentThread()->mutex_wait_address = address;
84 GetCurrentThread()->wait_handle = requesting_thread_handle;
85
86 GetCurrentThread()->status = THREADSTATUS_WAIT_MUTEX;
87 GetCurrentThread()->wakeup_callback = nullptr;
88
89 // Update the lock holder thread's priority to prevent priority inversion.
90 holding_thread->AddMutexWaiter(GetCurrentThread());
69 91
70 holding_thread->held_mutexes.erase(this);
71 holding_thread->UpdatePriority();
72 SetHoldingThread(nullptr);
73 SetHasWaiters(!GetWaitingThreads().empty());
74 WakeupAllWaitingThreads();
75 Core::System::GetInstance().PrepareReschedule(); 92 Core::System::GetInstance().PrepareReschedule();
76 93
77 return RESULT_SUCCESS; 94 return RESULT_SUCCESS;
78} 95}
79 96
80void Mutex::AddWaitingThread(SharedPtr<Thread> thread) { 97ResultCode Mutex::Release(VAddr address) {
81 WaitObject::AddWaitingThread(thread); 98 // The mutex address must be 4-byte aligned
82 thread->pending_mutexes.insert(this); 99 if ((address % sizeof(u32)) != 0) {
83 SetHasWaiters(true); 100 return ResultCode(ErrorModule::Kernel, ErrCodes::MisalignedAddress);
84 UpdatePriority(); 101 }
85}
86
87void Mutex::RemoveWaitingThread(Thread* thread) {
88 WaitObject::RemoveWaitingThread(thread);
89 thread->pending_mutexes.erase(this);
90 if (!GetHasWaiters())
91 SetHasWaiters(!GetWaitingThreads().empty());
92 UpdatePriority();
93}
94 102
95void Mutex::UpdatePriority() { 103 auto [thread, num_waiters] = GetHighestPriorityMutexWaitingThread(GetCurrentThread(), address);
96 if (!GetHoldingThread())
97 return;
98 104
99 u32 best_priority = THREADPRIO_LOWEST; 105 // There are no more threads waiting for the mutex, release it completely.
100 for (auto& waiter : GetWaitingThreads()) { 106 if (thread == nullptr) {
101 if (waiter->current_priority < best_priority) 107 ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
102 best_priority = waiter->current_priority; 108 Memory::Write32(address, 0);
109 return RESULT_SUCCESS;
103 } 110 }
104 111
105 if (best_priority != priority) { 112 // Transfer the ownership of the mutex from the previous owner to the new one.
106 priority = best_priority; 113 TransferMutexOwnership(address, GetCurrentThread(), thread);
107 GetHoldingThread()->UpdatePriority();
108 }
109}
110 114
111Handle Mutex::GetOwnerHandle() const { 115 u32 mutex_value = thread->wait_handle;
112 GuestState guest_state{Memory::Read32(guest_addr)};
113 return guest_state.holding_thread_handle;
114}
115 116
116SharedPtr<Thread> Mutex::GetHoldingThread() const { 117 if (num_waiters >= 2) {
117 GuestState guest_state{Memory::Read32(guest_addr)}; 118 // Notify the guest that there are still some threads waiting for the mutex
118 return g_handle_table.Get<Thread>(guest_state.holding_thread_handle); 119 mutex_value |= Mutex::MutexHasWaitersFlag;
119} 120 }
120 121
121void Mutex::SetHoldingThread(SharedPtr<Thread> thread) { 122 // Grant the mutex to the next waiting thread and resume it.
122 GuestState guest_state{Memory::Read32(guest_addr)}; 123 Memory::Write32(address, mutex_value);
123 guest_state.holding_thread_handle.Assign(thread ? thread->guest_handle : 0);
124 Memory::Write32(guest_addr, guest_state.raw);
125}
126 124
127bool Mutex::GetHasWaiters() const { 125 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
128 GuestState guest_state{Memory::Read32(guest_addr)}; 126 thread->ResumeFromWait();
129 return guest_state.has_waiters != 0;
130}
131 127
132void Mutex::SetHasWaiters(bool has_waiters) { 128 thread->lock_owner = nullptr;
133 GuestState guest_state{Memory::Read32(guest_addr)}; 129 thread->condvar_wait_address = 0;
134 guest_state.has_waiters.Assign(has_waiters ? 1 : 0); 130 thread->mutex_wait_address = 0;
135 Memory::Write32(guest_addr, guest_state.raw); 131 thread->wait_handle = 0;
136}
137 132
133 return RESULT_SUCCESS;
134}
138} // namespace Kernel 135} // namespace Kernel
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 38db21005..3117e7c70 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -15,87 +15,23 @@ namespace Kernel {
15 15
16class Thread; 16class Thread;
17 17
18class Mutex final : public WaitObject { 18class Mutex final {
19public: 19public:
20 /** 20 /// Flag that indicates that a mutex still has threads waiting for it.
21 * Creates a mutex. 21 static constexpr u32 MutexHasWaitersFlag = 0x40000000;
22 * @param holding_thread Specifies a thread already holding the mutex. If not nullptr, this 22 /// Mask of the bits in a mutex address value that contain the mutex owner.
23 * thread will acquire the mutex. 23 static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
24 * @param guest_addr Address of the object tracking the mutex in guest memory. If specified,
25 * this mutex will update the guest object when its state changes.
26 * @param name Optional name of mutex
27 * @return Pointer to new Mutex object
28 */
29 static SharedPtr<Mutex> Create(SharedPtr<Kernel::Thread> holding_thread, VAddr guest_addr = 0,
30 std::string name = "Unknown");
31 24
32 std::string GetTypeName() const override { 25 /// Attempts to acquire a mutex at the specified address.
33 return "Mutex"; 26 static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
34 } 27 Handle requesting_thread_handle);
35 std::string GetName() const override {
36 return name;
37 }
38 28
39 static const HandleType HANDLE_TYPE = HandleType::Mutex; 29 /// Releases the mutex at the specified address.
40 HandleType GetHandleType() const override { 30 static ResultCode Release(VAddr address);
41 return HANDLE_TYPE;
42 }
43
44 u32 priority; ///< The priority of the mutex, used for priority inheritance.
45 std::string name; ///< Name of mutex (optional)
46 VAddr guest_addr; ///< Address of the guest mutex value
47
48 /**
49 * Elevate the mutex priority to the best priority
50 * among the priorities of all its waiting threads.
51 */
52 void UpdatePriority();
53
54 bool ShouldWait(Thread* thread) const override;
55 void Acquire(Thread* thread) override;
56
57 void AddWaitingThread(SharedPtr<Thread> thread) override;
58 void RemoveWaitingThread(Thread* thread) override;
59
60 /**
61 * Attempts to release the mutex from the specified thread.
62 * @param thread Thread that wants to release the mutex.
63 * @returns The result code of the operation.
64 */
65 ResultCode Release(Thread* thread);
66
67 /// Gets the handle to the holding process stored in the guest state.
68 Handle GetOwnerHandle() const;
69
70 /// Gets the Thread pointed to by the owner handle
71 SharedPtr<Thread> GetHoldingThread() const;
72 /// Sets the holding process handle in the guest state.
73 void SetHoldingThread(SharedPtr<Thread> thread);
74
75 /// Returns the has_waiters bit in the guest state.
76 bool GetHasWaiters() const;
77 /// Sets the has_waiters bit in the guest state.
78 void SetHasWaiters(bool has_waiters);
79 31
80private: 32private:
81 Mutex(); 33 Mutex() = default;
82 ~Mutex() override; 34 ~Mutex() = default;
83
84 /// Object in guest memory used to track the mutex state
85 union GuestState {
86 u32_le raw;
87 /// Handle of the thread that currently holds the mutex, 0 if available
88 BitField<0, 30, u32_le> holding_thread_handle;
89 /// 1 when there are threads waiting for this mutex, otherwise 0
90 BitField<30, 1, u32_le> has_waiters;
91 };
92 static_assert(sizeof(GuestState) == 4, "GuestState size is incorrect");
93}; 35};
94 36
95/**
96 * Releases all the mutexes held by the specified thread
97 * @param thread Thread that is holding the mutexes
98 */
99void ReleaseThreadMutexes(Thread* thread);
100
101} // namespace Kernel 37} // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 2cffec198..751a0524d 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -54,7 +54,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
54 continue; 54 continue;
55 } else if ((type & 0xF00) == 0xE00) { // 0x0FFF 55 } else if ((type & 0xF00) == 0xE00) { // 0x0FFF
56 // Allowed interrupts list 56 // Allowed interrupts list
57 LOG_WARNING(Loader, "ExHeader allowed interrupts list ignored"); 57 NGLOG_WARNING(Loader, "ExHeader allowed interrupts list ignored");
58 } else if ((type & 0xF80) == 0xF00) { // 0x07FF 58 } else if ((type & 0xF80) == 0xF00) { // 0x07FF
59 // Allowed syscalls mask 59 // Allowed syscalls mask
60 unsigned int index = ((descriptor >> 24) & 7) * 24; 60 unsigned int index = ((descriptor >> 24) & 7) * 24;
@@ -74,7 +74,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
74 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F 74 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
75 // Mapped memory range 75 // Mapped memory range
76 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) { 76 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
77 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); 77 NGLOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
78 continue; 78 continue;
79 } 79 }
80 u32 end_desc = kernel_caps[i + 1]; 80 u32 end_desc = kernel_caps[i + 1];
@@ -109,9 +109,9 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
109 109
110 int minor = kernel_version & 0xFF; 110 int minor = kernel_version & 0xFF;
111 int major = (kernel_version >> 8) & 0xFF; 111 int major = (kernel_version >> 8) & 0xFF;
112 LOG_INFO(Loader, "ExHeader kernel version: %d.%d", major, minor); 112 NGLOG_INFO(Loader, "ExHeader kernel version: {}.{}", major, minor);
113 } else { 113 } else {
114 LOG_ERROR(Loader, "Unhandled kernel caps descriptor: 0x%08X", descriptor); 114 NGLOG_ERROR(Loader, "Unhandled kernel caps descriptor: {:#010X}", descriptor);
115 } 115 }
116 } 116 }
117} 117}
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 88ca8ad7e..0ef5fc57d 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -29,7 +29,7 @@ SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory cat
29 case ResourceLimitCategory::OTHER: 29 case ResourceLimitCategory::OTHER:
30 return resource_limits[static_cast<u8>(category)]; 30 return resource_limits[static_cast<u8>(category)];
31 default: 31 default:
32 LOG_CRITICAL(Kernel, "Unknown resource limit category"); 32 NGLOG_CRITICAL(Kernel, "Unknown resource limit category");
33 UNREACHABLE(); 33 UNREACHABLE();
34 } 34 }
35} 35}
@@ -55,7 +55,7 @@ s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
55 case ResourceType::CPUTime: 55 case ResourceType::CPUTime:
56 return current_cpu_time; 56 return current_cpu_time;
57 default: 57 default:
58 LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource)); 58 NGLOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
59 UNIMPLEMENTED(); 59 UNIMPLEMENTED();
60 return 0; 60 return 0;
61 } 61 }
@@ -84,7 +84,7 @@ u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
84 case ResourceType::CPUTime: 84 case ResourceType::CPUTime:
85 return max_cpu_time; 85 return max_cpu_time;
86 default: 86 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource)); 87 NGLOG_ERROR(Kernel, "Unknown resource type={:08X}", static_cast<u32>(resource));
88 UNIMPLEMENTED(); 88 UNIMPLEMENTED();
89 return 0; 89 return 0;
90 } 90 }
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index 921f27efb..ff6a0941a 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -94,11 +94,11 @@ void Scheduler::Reschedule() {
94 Thread* next = PopNextReadyThread(); 94 Thread* next = PopNextReadyThread();
95 95
96 if (cur && next) { 96 if (cur && next) {
97 LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); 97 NGLOG_TRACE(Kernel, "context switch {} -> {}", cur->GetObjectId(), next->GetObjectId());
98 } else if (cur) { 98 } else if (cur) {
99 LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); 99 NGLOG_TRACE(Kernel, "context switch {} -> idle", cur->GetObjectId());
100 } else if (next) { 100 } else if (next) {
101 LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); 101 NGLOG_TRACE(Kernel, "context switch idle -> {}", next->GetObjectId());
102 } 102 }
103 103
104 SwitchContext(next); 104 SwitchContext(next);
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 33397d84f..b1f8e771c 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -68,7 +68,7 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
68 return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); 68 return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
69 69
70 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { 70 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
71 LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id); 71 NGLOG_DEBUG(IPC, "CloseVirtualHandle, object_id={:#010X}", object_id);
72 72
73 domain_request_handlers[object_id - 1] = nullptr; 73 domain_request_handlers[object_id - 1] = nullptr;
74 74
@@ -78,8 +78,8 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
78 } 78 }
79 } 79 }
80 80
81 LOG_CRITICAL(IPC, "Unknown domain command=%d", 81 NGLOG_CRITICAL(IPC, "Unknown domain command={}",
82 static_cast<int>(domain_message_header->command.Value())); 82 static_cast<int>(domain_message_header->command.Value()));
83 ASSERT(false); 83 ASSERT(false);
84 } 84 }
85 85
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index bc99993c8..f0b65c73d 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -107,16 +107,16 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
107 107
108 // Error out if the requested permissions don't match what the creator process allows. 108 // Error out if the requested permissions don't match what the creator process allows.
109 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { 109 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
110 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match", 110 NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
111 GetObjectId(), address, name.c_str()); 111 GetObjectId(), address, name);
112 return ERR_INVALID_COMBINATION; 112 return ERR_INVALID_COMBINATION;
113 } 113 }
114 114
115 // Error out if the provided permissions are not compatible with what the creator process needs. 115 // Error out if the provided permissions are not compatible with what the creator process needs.
116 if (other_permissions != MemoryPermission::DontCare && 116 if (other_permissions != MemoryPermission::DontCare &&
117 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { 117 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
118 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%lx name=%s, permissions don't match", 118 NGLOG_ERROR(Kernel, "cannot map id={}, address={:#X} name={}, permissions don't match",
119 GetObjectId(), address, name.c_str()); 119 GetObjectId(), address, name);
120 return ERR_WRONG_PERMISSION; 120 return ERR_WRONG_PERMISSION;
121 } 121 }
122 122
@@ -131,9 +131,10 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
131 auto result = target_process->vm_manager.MapMemoryBlock( 131 auto result = target_process->vm_manager.MapMemoryBlock(
132 target_address, backing_block, backing_block_offset, size, MemoryState::Shared); 132 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
133 if (result.Failed()) { 133 if (result.Failed()) {
134 LOG_ERROR(Kernel, 134 NGLOG_ERROR(
135 "cannot map id=%u, target_address=0x%lx name=%s, error mapping to virtual memory", 135 Kernel,
136 GetObjectId(), target_address, name.c_str()); 136 "cannot map id={}, target_address={:#X} name={}, error mapping to virtual memory",
137 GetObjectId(), target_address, name);
137 return result.Code(); 138 return result.Code();
138 } 139 }
139 140
@@ -151,7 +152,7 @@ VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
151 u32 masked_permissions = 152 u32 masked_permissions =
152 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); 153 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
153 return static_cast<VMAPermission>(masked_permissions); 154 return static_cast<VMAPermission>(masked_permissions);
154}; 155}
155 156
156u8* SharedMemory::GetPointer(u32 offset) { 157u8* SharedMemory::GetPointer(u32 offset) {
157 return backing_block->data() + backing_block_offset + offset; 158 return backing_block->data() + backing_block_offset + offset;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 633740992..cb19b1a69 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -13,7 +13,6 @@
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/hle/kernel/client_port.h" 14#include "core/hle/kernel/client_port.h"
15#include "core/hle/kernel/client_session.h" 15#include "core/hle/kernel/client_session.h"
16#include "core/hle/kernel/condition_variable.h"
17#include "core/hle/kernel/event.h" 16#include "core/hle/kernel/event.h"
18#include "core/hle/kernel/handle_table.h" 17#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/mutex.h" 18#include "core/hle/kernel/mutex.h"
@@ -32,7 +31,7 @@ namespace Kernel {
32 31
33/// Set the process heap to a given Size. It can both extend and shrink the heap. 32/// Set the process heap to a given Size. It can both extend and shrink the heap.
34static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) { 33static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
35 LOG_TRACE(Kernel_SVC, "called, heap_size=0x%llx", heap_size); 34 NGLOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", heap_size);
36 auto& process = *Core::CurrentProcess(); 35 auto& process = *Core::CurrentProcess();
37 CASCADE_RESULT(*heap_addr, 36 CASCADE_RESULT(*heap_addr,
38 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite)); 37 process.HeapAllocate(Memory::HEAP_VADDR, heap_size, VMAPermission::ReadWrite));
@@ -40,21 +39,21 @@ static ResultCode SetHeapSize(VAddr* heap_addr, u64 heap_size) {
40} 39}
41 40
42static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { 41static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) {
43 LOG_WARNING(Kernel_SVC, "(STUBBED) called, addr=0x%lx", addr); 42 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, addr={:#X}", addr);
44 return RESULT_SUCCESS; 43 return RESULT_SUCCESS;
45} 44}
46 45
47/// Maps a memory range into a different range. 46/// Maps a memory range into a different range.
48static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 47static ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
49 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr, 48 NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr,
50 src_addr, size); 49 src_addr, size);
51 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size); 50 return Core::CurrentProcess()->MirrorMemory(dst_addr, src_addr, size);
52} 51}
53 52
54/// Unmaps a region that was previously mapped with svcMapMemory 53/// Unmaps a region that was previously mapped with svcMapMemory
55static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) { 54static ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size) {
56 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x%llx, src_addr=0x%llx, size=0x%llx", dst_addr, 55 NGLOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr={:#X}, size={:#X}", dst_addr,
57 src_addr, size); 56 src_addr, size);
58 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size); 57 return Core::CurrentProcess()->UnmapMemory(dst_addr, src_addr, size);
59} 58}
60 59
@@ -69,11 +68,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
69 if (port_name.size() > PortNameMaxLength) 68 if (port_name.size() > PortNameMaxLength)
70 return ERR_PORT_NAME_TOO_LONG; 69 return ERR_PORT_NAME_TOO_LONG;
71 70
72 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str()); 71 NGLOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
73 72
74 auto it = Service::g_kernel_named_ports.find(port_name); 73 auto it = Service::g_kernel_named_ports.find(port_name);
75 if (it == Service::g_kernel_named_ports.end()) { 74 if (it == Service::g_kernel_named_ports.end()) {
76 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str()); 75 NGLOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
77 return ERR_NOT_FOUND; 76 return ERR_NOT_FOUND;
78 } 77 }
79 78
@@ -91,11 +90,11 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
91static ResultCode SendSyncRequest(Handle handle) { 90static ResultCode SendSyncRequest(Handle handle) {
92 SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle); 91 SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle);
93 if (!session) { 92 if (!session) {
94 LOG_ERROR(Kernel_SVC, "called with invalid handle=0x%08X", handle); 93 NGLOG_ERROR(Kernel_SVC, "called with invalid handle={:#010X}", handle);
95 return ERR_INVALID_HANDLE; 94 return ERR_INVALID_HANDLE;
96 } 95 }
97 96
98 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); 97 NGLOG_TRACE(Kernel_SVC, "called handle={:#010X}({})", handle, session->GetName());
99 98
100 Core::System::GetInstance().PrepareReschedule(); 99 Core::System::GetInstance().PrepareReschedule();
101 100
@@ -106,7 +105,7 @@ static ResultCode SendSyncRequest(Handle handle) {
106 105
107/// Get the ID for the specified thread. 106/// Get the ID for the specified thread.
108static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) { 107static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
109 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 108 NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
110 109
111 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); 110 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
112 if (!thread) { 111 if (!thread) {
@@ -119,7 +118,7 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
119 118
120/// Get the ID of the specified process 119/// Get the ID of the specified process
121static ResultCode GetProcessId(u32* process_id, Handle process_handle) { 120static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
122 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 121 NGLOG_TRACE(Kernel_SVC, "called process={:#010X}", process_handle);
123 122
124 const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); 123 const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
125 if (!process) { 124 if (!process) {
@@ -179,8 +178,8 @@ static ResultCode WaitSynchronization1(
179/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 178/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
180static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count, 179static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
181 s64 nano_seconds) { 180 s64 nano_seconds) {
182 LOG_TRACE(Kernel_SVC, "called handles_address=0x%llx, handle_count=%d, nano_seconds=%d", 181 NGLOG_TRACE(Kernel_SVC, "called handles_address={:#X}, handle_count={}, nano_seconds={}",
183 handles_address, handle_count, nano_seconds); 182 handles_address, handle_count, nano_seconds);
184 183
185 if (!Memory::IsValidVirtualAddress(handles_address)) 184 if (!Memory::IsValidVirtualAddress(handles_address))
186 return ERR_INVALID_POINTER; 185 return ERR_INVALID_POINTER;
@@ -240,7 +239,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
240 239
241/// Resumes a thread waiting on WaitSynchronization 240/// Resumes a thread waiting on WaitSynchronization
242static ResultCode CancelSynchronization(Handle thread_handle) { 241static ResultCode CancelSynchronization(Handle thread_handle) {
243 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 242 NGLOG_TRACE(Kernel_SVC, "called thread={:#X}", thread_handle);
244 243
245 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); 244 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
246 if (!thread) { 245 if (!thread) {
@@ -257,56 +256,38 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
257/// Attempts to locks a mutex, creating it if it does not already exist 256/// Attempts to locks a mutex, creating it if it does not already exist
258static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr, 257static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
259 Handle requesting_thread_handle) { 258 Handle requesting_thread_handle) {
260 LOG_TRACE(Kernel_SVC, 259 NGLOG_TRACE(Kernel_SVC,
261 "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " 260 "called holding_thread_handle={:#010X}, mutex_addr={:#X}, "
262 "requesting_current_thread_handle=0x%08X", 261 "requesting_current_thread_handle={:#010X}",
263 holding_thread_handle, mutex_addr, requesting_thread_handle); 262 holding_thread_handle, mutex_addr, requesting_thread_handle);
264
265 SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
266 SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
267
268 ASSERT(requesting_thread);
269 ASSERT(requesting_thread == GetCurrentThread());
270
271 SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
272 if (!mutex) {
273 // Create a new mutex for the specified address if one does not already exist
274 mutex = Mutex::Create(holding_thread, mutex_addr);
275 mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
276 }
277
278 ASSERT(holding_thread == mutex->GetHoldingThread());
279 263
280 return WaitSynchronization1(mutex, requesting_thread.get()); 264 return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
281} 265}
282 266
283/// Unlock a mutex 267/// Unlock a mutex
284static ResultCode ArbitrateUnlock(VAddr mutex_addr) { 268static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
285 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x%llx", mutex_addr); 269 NGLOG_TRACE(Kernel_SVC, "called mutex_addr={:#X}", mutex_addr);
286 270
287 SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); 271 return Mutex::Release(mutex_addr);
288 ASSERT(mutex);
289
290 return mutex->Release(GetCurrentThread());
291} 272}
292 273
293/// Break program execution 274/// Break program execution
294static void Break(u64 unk_0, u64 unk_1, u64 unk_2) { 275static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
295 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); 276 NGLOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
296 ASSERT(false); 277 ASSERT(false);
297} 278}
298 279
299/// Used to output a message on a debug hardware unit - does nothing on a retail unit 280/// Used to output a message on a debug hardware unit - does nothing on a retail unit
300static void OutputDebugString(VAddr address, s32 len) { 281static void OutputDebugString(VAddr address, s32 len) {
301 std::vector<char> string(len); 282 std::string str(len, '\0');
302 Memory::ReadBlock(address, string.data(), len); 283 Memory::ReadBlock(address, str.data(), str.size());
303 LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data()); 284 NGLOG_DEBUG(Debug_Emulated, "{}", str);
304} 285}
305 286
306/// Gets system/memory information for the current process 287/// Gets system/memory information for the current process
307static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) { 288static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) {
308 LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, 289 NGLOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id={:#X}, handle={:#010X}", info_id,
309 info_sub_id, handle); 290 info_sub_id, handle);
310 291
311 auto& vm_manager = Core::CurrentProcess()->vm_manager; 292 auto& vm_manager = Core::CurrentProcess()->vm_manager;
312 293
@@ -357,12 +338,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
357 *result = Core::CurrentProcess()->is_virtual_address_memory_enabled; 338 *result = Core::CurrentProcess()->is_virtual_address_memory_enabled;
358 break; 339 break;
359 case GetInfoType::TitleId: 340 case GetInfoType::TitleId:
360 LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); 341 NGLOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
361 *result = 0; 342 *result = 0;
362 break; 343 break;
363 case GetInfoType::PrivilegedProcessId: 344 case GetInfoType::PrivilegedProcessId:
364 LOG_WARNING(Kernel_SVC, 345 NGLOG_WARNING(Kernel_SVC,
365 "(STUBBED) Attempted to query priviledged process id bounds, returned 0"); 346 "(STUBBED) Attempted to query privileged process id bounds, returned 0");
366 *result = 0; 347 *result = 0;
367 break; 348 break;
368 default: 349 default:
@@ -374,13 +355,14 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
374 355
375/// Sets the thread activity 356/// Sets the thread activity
376static ResultCode SetThreadActivity(Handle handle, u32 unknown) { 357static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
377 LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, unknown=0x%08X", handle, unknown); 358 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, unknown={:#010X}", handle,
359 unknown);
378 return RESULT_SUCCESS; 360 return RESULT_SUCCESS;
379} 361}
380 362
381/// Gets the thread context 363/// Gets the thread context
382static ResultCode GetThreadContext(Handle handle, VAddr addr) { 364static ResultCode GetThreadContext(Handle handle, VAddr addr) {
383 LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, addr=0x%" PRIx64, handle, addr); 365 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, addr={:#X}", handle, addr);
384 return RESULT_SUCCESS; 366 return RESULT_SUCCESS;
385} 367}
386 368
@@ -412,11 +394,6 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
412 } 394 }
413 395
414 thread->SetPriority(priority); 396 thread->SetPriority(priority);
415 thread->UpdatePriority();
416
417 // Update the mutexes that this thread is waiting for
418 for (auto& mutex : thread->pending_mutexes)
419 mutex->UpdatePriority();
420 397
421 Core::System::GetInstance().PrepareReschedule(); 398 Core::System::GetInstance().PrepareReschedule();
422 return RESULT_SUCCESS; 399 return RESULT_SUCCESS;
@@ -424,15 +401,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
424 401
425/// Get which CPU core is executing the current thread 402/// Get which CPU core is executing the current thread
426static u32 GetCurrentProcessorNumber() { 403static u32 GetCurrentProcessorNumber() {
427 LOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0"); 404 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, defaulting to processor 0");
428 return 0; 405 return 0;
429} 406}
430 407
431static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, 408static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size,
432 u32 permissions) { 409 u32 permissions) {
433 LOG_TRACE(Kernel_SVC, 410 NGLOG_TRACE(Kernel_SVC,
434 "called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X", 411 "called, shared_memory_handle={:#X}, addr={:#X}, size={:#X}, permissions={:#010X}",
435 shared_memory_handle, addr, size, permissions); 412 shared_memory_handle, addr, size, permissions);
436 413
437 SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); 414 SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
438 if (!shared_memory) { 415 if (!shared_memory) {
@@ -452,16 +429,15 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
452 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type, 429 return shared_memory->Map(Core::CurrentProcess().get(), addr, permissions_type,
453 MemoryPermission::DontCare); 430 MemoryPermission::DontCare);
454 default: 431 default:
455 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 432 NGLOG_ERROR(Kernel_SVC, "unknown permissions={:#010X}", permissions);
456 } 433 }
457 434
458 return RESULT_SUCCESS; 435 return RESULT_SUCCESS;
459} 436}
460 437
461static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { 438static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) {
462 LOG_WARNING(Kernel_SVC, 439 NGLOG_WARNING(Kernel_SVC, "called, shared_memory_handle={:#010X}, addr={:#X}, size={:#X}",
463 "called, shared_memory_handle=0x%08X, addr=0x%" PRIx64 ", size=0x%" PRIx64 "", 440 shared_memory_handle, addr, size);
464 shared_memory_handle, addr, size);
465 441
466 SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); 442 SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
467 443
@@ -489,19 +465,19 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_i
489 memory_info->type = static_cast<u32>(vma->second.meminfo_state); 465 memory_info->type = static_cast<u32>(vma->second.meminfo_state);
490 } 466 }
491 467
492 LOG_TRACE(Kernel_SVC, "called process=0x%08X addr=%llx", process_handle, addr); 468 NGLOG_TRACE(Kernel_SVC, "called process={:#010X} addr={:X}", process_handle, addr);
493 return RESULT_SUCCESS; 469 return RESULT_SUCCESS;
494} 470}
495 471
496/// Query memory 472/// Query memory
497static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) { 473static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAddr addr) {
498 LOG_TRACE(Kernel_SVC, "called, addr=%llx", addr); 474 NGLOG_TRACE(Kernel_SVC, "called, addr={:X}", addr);
499 return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr); 475 return QueryProcessMemory(memory_info, page_info, CurrentProcess, addr);
500} 476}
501 477
502/// Exits the current process 478/// Exits the current process
503static void ExitProcess() { 479static void ExitProcess() {
504 LOG_INFO(Kernel_SVC, "Process %u exiting", Core::CurrentProcess()->process_id); 480 NGLOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id);
505 481
506 ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running, 482 ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running,
507 "Process has already exited"); 483 "Process has already exited");
@@ -558,9 +534,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
558 case THREADPROCESSORID_2: 534 case THREADPROCESSORID_2:
559 case THREADPROCESSORID_3: 535 case THREADPROCESSORID_3:
560 // TODO(bunnei): Implement support for other processor IDs 536 // TODO(bunnei): Implement support for other processor IDs
561 LOG_ERROR(Kernel_SVC, 537 NGLOG_ERROR(Kernel_SVC,
562 "Newly created thread must run in another thread (%u), unimplemented.", 538 "Newly created thread must run in another thread ({}), unimplemented.",
563 processor_id); 539 processor_id);
564 break; 540 break;
565 default: 541 default:
566 ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id); 542 ASSERT_MSG(false, "Unsupported thread processor ID: %d", processor_id);
@@ -575,17 +551,17 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
575 551
576 Core::System::GetInstance().PrepareReschedule(); 552 Core::System::GetInstance().PrepareReschedule();
577 553
578 LOG_TRACE(Kernel_SVC, 554 NGLOG_TRACE(Kernel_SVC,
579 "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 555 "called entrypoint={:#010X} ({}), arg={:#010X}, stacktop={:#010X}, "
580 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", 556 "threadpriority={:#010X}, processorid={:#010X} : created handle={:#010X}",
581 entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 557 entry_point, name, arg, stack_top, priority, processor_id, *out_handle);
582 558
583 return RESULT_SUCCESS; 559 return RESULT_SUCCESS;
584} 560}
585 561
586/// Starts the thread for the provided handle 562/// Starts the thread for the provided handle
587static ResultCode StartThread(Handle thread_handle) { 563static ResultCode StartThread(Handle thread_handle) {
588 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 564 NGLOG_TRACE(Kernel_SVC, "called thread={:#010X}", thread_handle);
589 565
590 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); 566 const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
591 if (!thread) { 567 if (!thread) {
@@ -599,7 +575,7 @@ static ResultCode StartThread(Handle thread_handle) {
599 575
600/// Called when a thread exits 576/// Called when a thread exits
601static void ExitThread() { 577static void ExitThread() {
602 LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::CPU().GetPC()); 578 NGLOG_TRACE(Kernel_SVC, "called, pc={:#010X}", Core::CPU().GetPC());
603 579
604 ExitCurrentThread(); 580 ExitCurrentThread();
605 Core::System::GetInstance().PrepareReschedule(); 581 Core::System::GetInstance().PrepareReschedule();
@@ -607,7 +583,7 @@ static void ExitThread() {
607 583
608/// Sleep the current thread 584/// Sleep the current thread
609static void SleepThread(s64 nanoseconds) { 585static void SleepThread(s64 nanoseconds) {
610 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); 586 NGLOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
611 587
612 // Don't attempt to yield execution if there are no available threads to run, 588 // Don't attempt to yield execution if there are no available threads to run,
613 // this way we avoid a useless reschedule to the idle thread. 589 // this way we avoid a useless reschedule to the idle thread.
@@ -626,111 +602,83 @@ static void SleepThread(s64 nanoseconds) {
626/// Signal process wide key atomic 602/// Signal process wide key atomic
627static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, 603static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
628 Handle thread_handle, s64 nano_seconds) { 604 Handle thread_handle, s64 nano_seconds) {
629 LOG_TRACE( 605 NGLOG_TRACE(
630 Kernel_SVC, 606 Kernel_SVC,
631 "called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d", 607 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle={:#010X}, timeout={}",
632 mutex_addr, condition_variable_addr, thread_handle, nano_seconds); 608 mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
633 609
634 SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); 610 SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
635 ASSERT(thread); 611 ASSERT(thread);
636 612
637 SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); 613 CASCADE_CODE(Mutex::Release(mutex_addr));
638 if (!mutex) {
639 // Create a new mutex for the specified address if one does not already exist
640 mutex = Mutex::Create(thread, mutex_addr);
641 mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
642 }
643 614
644 SharedPtr<ConditionVariable> condition_variable = 615 SharedPtr<Thread> current_thread = GetCurrentThread();
645 g_object_address_table.Get<ConditionVariable>(condition_variable_addr); 616 current_thread->condvar_wait_address = condition_variable_addr;
646 if (!condition_variable) { 617 current_thread->mutex_wait_address = mutex_addr;
647 // Create a new condition_variable for the specified address if one does not already exist 618 current_thread->wait_handle = thread_handle;
648 condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap(); 619 current_thread->status = THREADSTATUS_WAIT_MUTEX;
649 condition_variable->name = 620 current_thread->wakeup_callback = nullptr;
650 Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
651 }
652 621
653 if (condition_variable->mutex_addr) { 622 current_thread->WakeAfterDelay(nano_seconds);
654 // Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
655 // everything is correct
656 ASSERT(condition_variable->mutex_addr == mutex_addr);
657 } else {
658 // Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
659 // associated with it
660 condition_variable->mutex_addr = mutex_addr;
661 }
662 623
663 if (mutex->GetOwnerHandle()) { 624 // Note: Deliberately don't attempt to inherit the lock owner's priority.
664 // Release the mutex if the current thread is holding it
665 mutex->Release(thread.get());
666 }
667 625
668 auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, 626 Core::System::GetInstance().PrepareReschedule();
669 SharedPtr<Thread> thread, 627 return RESULT_SUCCESS;
670 SharedPtr<WaitObject> object, size_t index) { 628}
671 ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY);
672 629
673 if (reason == ThreadWakeupReason::Timeout) { 630/// Signal process wide key
674 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); 631static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
675 return true; 632 NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr={:#X}, target={:#010X}",
676 } 633 condition_variable_addr, target);
677 634
678 ASSERT(reason == ThreadWakeupReason::Signal); 635 u32 processed = 0;
636 auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList();
679 637
680 // Now try to acquire the mutex and don't resume if it's not available. 638 for (auto& thread : thread_list) {
681 if (!mutex->ShouldWait(thread.get())) { 639 if (thread->condvar_wait_address != condition_variable_addr)
682 mutex->Acquire(thread.get()); 640 continue;
683 thread->SetWaitSynchronizationResult(RESULT_SUCCESS);
684 return true;
685 }
686 641
687 if (nano_seconds == 0) { 642 // Only process up to 'target' threads, unless 'target' is -1, in which case process
688 thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); 643 // them all.
689 return true; 644 if (target != -1 && processed >= target)
690 } 645 break;
691 646
692 thread->wait_objects = {mutex}; 647 // If the mutex is not yet acquired, acquire it.
693 mutex->AddWaitingThread(thread); 648 u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
694 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
695 649
696 // Create an event to wake the thread up after the 650 if (mutex_val == 0) {
697 // specified nanosecond delay has passed 651 // We were able to acquire the mutex, resume this thread.
698 thread->WakeAfterDelay(nano_seconds); 652 Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
699 thread->wakeup_callback = DefaultThreadWakeupCallback; 653 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
654 thread->ResumeFromWait();
700 655
701 Core::System::GetInstance().PrepareReschedule(); 656 auto lock_owner = thread->lock_owner;
657 if (lock_owner)
658 lock_owner->RemoveMutexWaiter(thread);
702 659
703 return false; 660 thread->lock_owner = nullptr;
704 }; 661 thread->mutex_wait_address = 0;
705 CASCADE_CODE( 662 thread->condvar_wait_address = 0;
706 WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback)); 663 thread->wait_handle = 0;
664 } else {
665 // Couldn't acquire the mutex, block the thread.
666 Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
667 auto owner = g_handle_table.Get<Thread>(owner_handle);
668 ASSERT(owner);
669 ASSERT(thread->status != THREADSTATUS_RUNNING);
670 thread->status = THREADSTATUS_WAIT_MUTEX;
671 thread->wakeup_callback = nullptr;
707 672
708 return RESULT_SUCCESS; 673 // Signal that the mutex now has a waiting thread.
709} 674 Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
710 675
711/// Signal process wide key 676 owner->AddMutexWaiter(thread);
712static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
713 LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
714 condition_variable_addr, target);
715
716 // Wakeup all or one thread - Any other value is unimplemented
717 ASSERT(target == -1 || target == 1);
718
719 SharedPtr<ConditionVariable> condition_variable =
720 g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
721 if (!condition_variable) {
722 // Create a new condition_variable for the specified address if one does not already exist
723 condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
724 condition_variable->name =
725 Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
726 }
727 677
728 CASCADE_CODE(condition_variable->Release(target)); 678 Core::System::GetInstance().PrepareReschedule();
679 }
729 680
730 if (condition_variable->mutex_addr) { 681 ++processed;
731 // If a mutex was created for this condition_variable, wait the current thread on it
732 SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr);
733 return WaitSynchronization1(mutex, GetCurrentThread());
734 } 682 }
735 683
736 return RESULT_SUCCESS; 684 return RESULT_SUCCESS;
@@ -748,13 +696,13 @@ static u64 GetSystemTick() {
748 696
749/// Close a handle 697/// Close a handle
750static ResultCode CloseHandle(Handle handle) { 698static ResultCode CloseHandle(Handle handle) {
751 LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); 699 NGLOG_TRACE(Kernel_SVC, "Closing handle {:#010X}", handle);
752 return g_handle_table.Close(handle); 700 return g_handle_table.Close(handle);
753} 701}
754 702
755/// Reset an event 703/// Reset an event
756static ResultCode ResetSignal(Handle handle) { 704static ResultCode ResetSignal(Handle handle) {
757 LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x%08X", handle); 705 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called handle {:#010X}", handle);
758 auto event = g_handle_table.Get<Event>(handle); 706 auto event = g_handle_table.Get<Event>(handle);
759 ASSERT(event != nullptr); 707 ASSERT(event != nullptr);
760 event->Clear(); 708 event->Clear();
@@ -763,29 +711,29 @@ static ResultCode ResetSignal(Handle handle) {
763 711
764/// Creates a TransferMemory object 712/// Creates a TransferMemory object
765static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) { 713static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32 permissions) {
766 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%lx, size=0x%lx, perms=%08X", addr, size, 714 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called addr={:#X}, size={:#X}, perms={:010X}", addr, size,
767 permissions); 715 permissions);
768 *handle = 0; 716 *handle = 0;
769 return RESULT_SUCCESS; 717 return RESULT_SUCCESS;
770} 718}
771 719
772static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) { 720static ResultCode GetThreadCoreMask(Handle handle, u32* mask, u64* unknown) {
773 LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X", handle); 721 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:010X}", handle);
774 *mask = 0x0; 722 *mask = 0x0;
775 *unknown = 0xf; 723 *unknown = 0xf;
776 return RESULT_SUCCESS; 724 return RESULT_SUCCESS;
777} 725}
778 726
779static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) { 727static ResultCode SetThreadCoreMask(Handle handle, u32 mask, u64 unknown) {
780 LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x%08X, mask=0x%08X, unknown=0x%lx", handle, 728 NGLOG_WARNING(Kernel_SVC, "(STUBBED) called, handle={:#010X}, mask={:#010X}, unknown={:#X}",
781 mask, unknown); 729 handle, mask, unknown);
782 return RESULT_SUCCESS; 730 return RESULT_SUCCESS;
783} 731}
784 732
785static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions, 733static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
786 u32 remote_permissions) { 734 u32 remote_permissions) {
787 LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size, 735 NGLOG_TRACE(Kernel_SVC, "called, size={:#X}, localPerms={:#010X}, remotePerms={:#010X}", size,
788 local_permissions, remote_permissions); 736 local_permissions, remote_permissions);
789 auto sharedMemHandle = 737 auto sharedMemHandle =
790 SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size, 738 SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
791 static_cast<MemoryPermission>(local_permissions), 739 static_cast<MemoryPermission>(local_permissions),
@@ -796,7 +744,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
796} 744}
797 745
798static ResultCode ClearEvent(Handle handle) { 746static ResultCode ClearEvent(Handle handle) {
799 LOG_TRACE(Kernel_SVC, "called, event=0xX", handle); 747 NGLOG_TRACE(Kernel_SVC, "called, event={:010X}", handle);
800 748
801 SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); 749 SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
802 if (evt == nullptr) 750 if (evt == nullptr)
@@ -948,7 +896,7 @@ static const FunctionDef SVC_Table[] = {
948 896
949static const FunctionDef* GetSVCInfo(u32 func_num) { 897static const FunctionDef* GetSVCInfo(u32 func_num) {
950 if (func_num >= std::size(SVC_Table)) { 898 if (func_num >= std::size(SVC_Table)) {
951 LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num); 899 NGLOG_ERROR(Kernel_SVC, "Unknown svc={:#04X}", func_num);
952 return nullptr; 900 return nullptr;
953 } 901 }
954 return &SVC_Table[func_num]; 902 return &SVC_Table[func_num];
@@ -967,10 +915,10 @@ void CallSVC(u32 immediate) {
967 if (info->func) { 915 if (info->func) {
968 info->func(); 916 info->func();
969 } else { 917 } else {
970 LOG_CRITICAL(Kernel_SVC, "unimplemented SVC function %s(..)", info->name); 918 NGLOG_CRITICAL(Kernel_SVC, "Unimplemented SVC function {}(..)", info->name);
971 } 919 }
972 } else { 920 } else {
973 LOG_CRITICAL(Kernel_SVC, "unknown SVC function 0x%x", immediate); 921 NGLOG_CRITICAL(Kernel_SVC, "Unknown SVC function {:#X}", immediate);
974 } 922 }
975} 923}
976 924
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f3a8aa4aa..4cd57ab25 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -77,9 +77,6 @@ void Thread::Stop() {
77 } 77 }
78 wait_objects.clear(); 78 wait_objects.clear();
79 79
80 // Release all the mutexes that this thread holds
81 ReleaseThreadMutexes(this);
82
83 // Mark the TLS slot in the thread's page as free. 80 // Mark the TLS slot in the thread's page as free.
84 u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 81 u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
85 u64 tls_slot = 82 u64 tls_slot =
@@ -104,9 +101,10 @@ void ExitCurrentThread() {
104 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time 101 * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
105 */ 102 */
106static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { 103static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
107 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); 104 const auto proper_handle = static_cast<Handle>(thread_handle);
105 SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
108 if (thread == nullptr) { 106 if (thread == nullptr) {
109 LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", (Handle)thread_handle); 107 NGLOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
110 return; 108 return;
111 } 109 }
112 110
@@ -126,6 +124,19 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
126 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); 124 resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
127 } 125 }
128 126
127 if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
128 thread->wait_handle) {
129 ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
130 thread->mutex_wait_address = 0;
131 thread->condvar_wait_address = 0;
132 thread->wait_handle = 0;
133
134 auto lock_owner = thread->lock_owner;
135 // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
136 // and don't have a lock owner.
137 ASSERT(lock_owner == nullptr);
138 }
139
129 if (resume) 140 if (resume)
130 thread->ResumeFromWait(); 141 thread->ResumeFromWait();
131} 142}
@@ -151,6 +162,7 @@ void Thread::ResumeFromWait() {
151 case THREADSTATUS_WAIT_HLE_EVENT: 162 case THREADSTATUS_WAIT_HLE_EVENT:
152 case THREADSTATUS_WAIT_SLEEP: 163 case THREADSTATUS_WAIT_SLEEP:
153 case THREADSTATUS_WAIT_IPC: 164 case THREADSTATUS_WAIT_IPC:
165 case THREADSTATUS_WAIT_MUTEX:
154 break; 166 break;
155 167
156 case THREADSTATUS_READY: 168 case THREADSTATUS_READY:
@@ -227,19 +239,19 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
227 SharedPtr<Process> owner_process) { 239 SharedPtr<Process> owner_process) {
228 // Check if priority is in ranged. Lowest priority -> highest priority id. 240 // Check if priority is in ranged. Lowest priority -> highest priority id.
229 if (priority > THREADPRIO_LOWEST) { 241 if (priority > THREADPRIO_LOWEST) {
230 LOG_ERROR(Kernel_SVC, "Invalid thread priority: %u", priority); 242 NGLOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
231 return ERR_OUT_OF_RANGE; 243 return ERR_OUT_OF_RANGE;
232 } 244 }
233 245
234 if (processor_id > THREADPROCESSORID_MAX) { 246 if (processor_id > THREADPROCESSORID_MAX) {
235 LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id); 247 NGLOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
236 return ERR_OUT_OF_RANGE_KERNEL; 248 return ERR_OUT_OF_RANGE_KERNEL;
237 } 249 }
238 250
239 // TODO(yuriks): Other checks, returning 0xD9001BEA 251 // TODO(yuriks): Other checks, returning 0xD9001BEA
240 252
241 if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) { 253 if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
242 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %016" PRIx64, name.c_str(), entry_point); 254 NGLOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
243 // TODO (bunnei): Find the correct error code to use here 255 // TODO (bunnei): Find the correct error code to use here
244 return ResultCode(-1); 256 return ResultCode(-1);
245 } 257 }
@@ -256,7 +268,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
256 thread->last_running_ticks = CoreTiming::GetTicks(); 268 thread->last_running_ticks = CoreTiming::GetTicks();
257 thread->processor_id = processor_id; 269 thread->processor_id = processor_id;
258 thread->wait_objects.clear(); 270 thread->wait_objects.clear();
259 thread->wait_address = 0; 271 thread->mutex_wait_address = 0;
272 thread->condvar_wait_address = 0;
273 thread->wait_handle = 0;
260 thread->name = std::move(name); 274 thread->name = std::move(name);
261 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); 275 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
262 thread->owner_process = owner_process; 276 thread->owner_process = owner_process;
@@ -276,8 +290,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
276 auto& linheap_memory = memory_region->linear_heap_memory; 290 auto& linheap_memory = memory_region->linear_heap_memory;
277 291
278 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 292 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
279 LOG_ERROR(Kernel_SVC, 293 NGLOG_ERROR(Kernel_SVC,
280 "Not enough space in region to allocate a new TLS page for thread"); 294 "Not enough space in region to allocate a new TLS page for thread");
281 return ERR_OUT_OF_MEMORY; 295 return ERR_OUT_OF_MEMORY;
282 } 296 }
283 297
@@ -317,17 +331,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
317void Thread::SetPriority(u32 priority) { 331void Thread::SetPriority(u32 priority) {
318 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST, 332 ASSERT_MSG(priority <= THREADPRIO_LOWEST && priority >= THREADPRIO_HIGHEST,
319 "Invalid priority value."); 333 "Invalid priority value.");
320 Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); 334 nominal_priority = priority;
321 nominal_priority = current_priority = priority; 335 UpdatePriority();
322}
323
324void Thread::UpdatePriority() {
325 u32 best_priority = nominal_priority;
326 for (auto& mutex : held_mutexes) {
327 if (mutex->priority < best_priority)
328 best_priority = mutex->priority;
329 }
330 BoostPriority(best_priority);
331} 336}
332 337
333void Thread::BoostPriority(u32 priority) { 338void Thread::BoostPriority(u32 priority) {
@@ -377,6 +382,38 @@ VAddr Thread::GetCommandBufferAddress() const {
377 return GetTLSAddress() + CommandHeaderOffset; 382 return GetTLSAddress() + CommandHeaderOffset;
378} 383}
379 384
385void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
386 thread->lock_owner = this;
387 wait_mutex_threads.emplace_back(std::move(thread));
388 UpdatePriority();
389}
390
391void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
392 boost::remove_erase(wait_mutex_threads, thread);
393 thread->lock_owner = nullptr;
394 UpdatePriority();
395}
396
397void Thread::UpdatePriority() {
398 // Find the highest priority among all the threads that are waiting for this thread's lock
399 u32 new_priority = nominal_priority;
400 for (const auto& thread : wait_mutex_threads) {
401 if (thread->nominal_priority < new_priority)
402 new_priority = thread->nominal_priority;
403 }
404
405 if (new_priority == current_priority)
406 return;
407
408 Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority);
409
410 current_priority = new_priority;
411
412 // Recursively update the priority of the thread that depends on the priority of this one.
413 if (lock_owner)
414 lock_owner->UpdatePriority();
415}
416
380//////////////////////////////////////////////////////////////////////////////////////////////////// 417////////////////////////////////////////////////////////////////////////////////////////////////////
381 418
382/** 419/**
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index dbf47e269..e0a3c0934 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -18,7 +18,7 @@
18enum ThreadPriority : u32 { 18enum ThreadPriority : u32 {
19 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 19 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
20 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 20 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
21 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps 21 THREADPRIO_DEFAULT = 44, ///< Default thread priority for userland apps
22 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 22 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
23}; 23};
24 24
@@ -43,6 +43,7 @@ enum ThreadStatus {
43 THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request 43 THREADSTATUS_WAIT_IPC, ///< Waiting for the reply from an IPC request
44 THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false 44 THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
45 THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true 45 THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true
46 THREADSTATUS_WAIT_MUTEX, ///< Waiting due to an ArbitrateLock/WaitProcessWideKey svc
46 THREADSTATUS_DORMANT, ///< Created but not yet made ready 47 THREADSTATUS_DORMANT, ///< Created but not yet made ready
47 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 48 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
48}; 49};
@@ -54,7 +55,6 @@ enum class ThreadWakeupReason {
54 55
55namespace Kernel { 56namespace Kernel {
56 57
57class Mutex;
58class Process; 58class Process;
59 59
60class Thread final : public WaitObject { 60class Thread final : public WaitObject {
@@ -104,17 +104,20 @@ public:
104 void SetPriority(u32 priority); 104 void SetPriority(u32 priority);
105 105
106 /** 106 /**
107 * Boost's a thread's priority to the best priority among the thread's held mutexes.
108 * This prevents priority inversion via priority inheritance.
109 */
110 void UpdatePriority();
111
112 /**
113 * Temporarily boosts the thread's priority until the next time it is scheduled 107 * Temporarily boosts the thread's priority until the next time it is scheduled
114 * @param priority The new priority 108 * @param priority The new priority
115 */ 109 */
116 void BoostPriority(u32 priority); 110 void BoostPriority(u32 priority);
117 111
112 /// Adds a thread to the list of threads that are waiting for a lock held by this thread.
113 void AddMutexWaiter(SharedPtr<Thread> thread);
114
115 /// Removes a thread from the list of threads that are waiting for a lock held by this thread.
116 void RemoveMutexWaiter(SharedPtr<Thread> thread);
117
118 /// Recalculates the current priority taking into account priority inheritance.
119 void UpdatePriority();
120
118 /** 121 /**
119 * Gets the thread's thread ID 122 * Gets the thread's thread ID
120 * @return The thread's ID 123 * @return The thread's ID
@@ -205,19 +208,22 @@ public:
205 208
206 VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread 209 VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
207 210
208 /// Mutexes currently held by this thread, which will be released when it exits.
209 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
210
211 /// Mutexes that this thread is currently waiting for.
212 boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
213
214 SharedPtr<Process> owner_process; ///< Process that owns this thread 211 SharedPtr<Process> owner_process; ///< Process that owns this thread
215 212
216 /// Objects that the thread is waiting on, in the same order as they were 213 /// Objects that the thread is waiting on, in the same order as they were
217 // passed to WaitSynchronization1/N. 214 // passed to WaitSynchronization1/N.
218 std::vector<SharedPtr<WaitObject>> wait_objects; 215 std::vector<SharedPtr<WaitObject>> wait_objects;
219 216
220 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 217 /// List of threads that are waiting for a mutex that is held by this thread.
218 std::vector<SharedPtr<Thread>> wait_mutex_threads;
219
220 /// Thread that owns the lock that this thread is waiting for.
221 SharedPtr<Thread> lock_owner;
222
223 // If waiting on a ConditionVariable, this is the ConditionVariable address
224 VAddr condvar_wait_address;
225 VAddr mutex_wait_address; ///< If waiting on a Mutex, this is the mutex address
226 Handle wait_handle; ///< The handle used to wait for the mutex.
221 227
222 std::string name; 228 std::string name;
223 229
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 8da745634..ad58bf043 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -77,7 +77,7 @@ void Timer::WakeupAllWaitingThreads() {
77} 77}
78 78
79void Timer::Signal(int cycles_late) { 79void Timer::Signal(int cycles_late) {
80 LOG_TRACE(Kernel, "Timer %u fired", GetObjectId()); 80 NGLOG_TRACE(Kernel, "Timer {} fired", GetObjectId());
81 81
82 signaled = true; 82 signaled = true;
83 83
@@ -97,7 +97,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
97 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 97 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
98 98
99 if (timer == nullptr) { 99 if (timer == nullptr) {
100 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); 100 NGLOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
101 return; 101 return;
102 } 102 }
103 103
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index acd65ee68..eb2e35eed 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -379,22 +379,22 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
379} 379}
380 380
381u64 VMManager::GetTotalMemoryUsage() { 381u64 VMManager::GetTotalMemoryUsage() {
382 LOG_WARNING(Kernel, "(STUBBED) called"); 382 NGLOG_WARNING(Kernel, "(STUBBED) called");
383 return 0xF8000000; 383 return 0xF8000000;
384} 384}
385 385
386u64 VMManager::GetTotalHeapUsage() { 386u64 VMManager::GetTotalHeapUsage() {
387 LOG_WARNING(Kernel, "(STUBBED) called"); 387 NGLOG_WARNING(Kernel, "(STUBBED) called");
388 return 0x0; 388 return 0x0;
389} 389}
390 390
391VAddr VMManager::GetAddressSpaceBaseAddr() { 391VAddr VMManager::GetAddressSpaceBaseAddr() {
392 LOG_WARNING(Kernel, "(STUBBED) called"); 392 NGLOG_WARNING(Kernel, "(STUBBED) called");
393 return 0x8000000; 393 return 0x8000000;
394} 394}
395 395
396u64 VMManager::GetAddressSpaceSize() { 396u64 VMManager::GetAddressSpaceSize() {
397 LOG_WARNING(Kernel, "(STUBBED) called"); 397 NGLOG_WARNING(Kernel, "(STUBBED) called");
398 return MAX_ADDRESS; 398 return MAX_ADDRESS;
399} 399}
400 400
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 6bafb2dce..f2fffa760 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -47,7 +47,7 @@ public:
47 47
48private: 48private:
49 void GetBase(Kernel::HLERequestContext& ctx) { 49 void GetBase(Kernel::HLERequestContext& ctx) {
50 LOG_WARNING(Service_ACC, "(STUBBED) called"); 50 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
51 ProfileBase profile_base{}; 51 ProfileBase profile_base{};
52 IPC::ResponseBuilder rb{ctx, 16}; 52 IPC::ResponseBuilder rb{ctx, 16};
53 rb.Push(RESULT_SUCCESS); 53 rb.Push(RESULT_SUCCESS);
@@ -72,14 +72,14 @@ public:
72 72
73private: 73private:
74 void CheckAvailability(Kernel::HLERequestContext& ctx) { 74 void CheckAvailability(Kernel::HLERequestContext& ctx) {
75 LOG_WARNING(Service_ACC, "(STUBBED) called"); 75 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
76 IPC::ResponseBuilder rb{ctx, 3}; 76 IPC::ResponseBuilder rb{ctx, 3};
77 rb.Push(RESULT_SUCCESS); 77 rb.Push(RESULT_SUCCESS);
78 rb.Push(true); // TODO: Check when this is supposed to return true and when not 78 rb.Push(true); // TODO: Check when this is supposed to return true and when not
79 } 79 }
80 80
81 void GetAccountId(Kernel::HLERequestContext& ctx) { 81 void GetAccountId(Kernel::HLERequestContext& ctx) {
82 LOG_WARNING(Service_ACC, "(STUBBED) called"); 82 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
83 IPC::ResponseBuilder rb{ctx, 4}; 83 IPC::ResponseBuilder rb{ctx, 4};
84 rb.Push(RESULT_SUCCESS); 84 rb.Push(RESULT_SUCCESS);
85 rb.Push<u64>(0x12345678ABCDEF); 85 rb.Push<u64>(0x12345678ABCDEF);
@@ -87,14 +87,14 @@ private:
87}; 87};
88 88
89void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { 89void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
90 LOG_WARNING(Service_ACC, "(STUBBED) called"); 90 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
91 IPC::ResponseBuilder rb{ctx, 3}; 91 IPC::ResponseBuilder rb{ctx, 3};
92 rb.Push(RESULT_SUCCESS); 92 rb.Push(RESULT_SUCCESS);
93 rb.Push(true); // TODO: Check when this is supposed to return true and when not 93 rb.Push(true); // TODO: Check when this is supposed to return true and when not
94} 94}
95 95
96void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) { 96void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
97 LOG_WARNING(Service_ACC, "(STUBBED) called"); 97 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
98 constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; 98 constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
99 ctx.WriteBuffer(user_ids.data(), user_ids.size()); 99 ctx.WriteBuffer(user_ids.data(), user_ids.size());
100 IPC::ResponseBuilder rb{ctx, 2}; 100 IPC::ResponseBuilder rb{ctx, 2};
@@ -102,7 +102,7 @@ void Module::Interface::ListAllUsers(Kernel::HLERequestContext& ctx) {
102} 102}
103 103
104void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) { 104void Module::Interface::ListOpenUsers(Kernel::HLERequestContext& ctx) {
105 LOG_WARNING(Service_ACC, "(STUBBED) called"); 105 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
106 constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID}; 106 constexpr std::array<u128, 10> user_ids{DEFAULT_USER_ID};
107 ctx.WriteBuffer(user_ids.data(), user_ids.size()); 107 ctx.WriteBuffer(user_ids.data(), user_ids.size());
108 IPC::ResponseBuilder rb{ctx, 2}; 108 IPC::ResponseBuilder rb{ctx, 2};
@@ -113,11 +113,11 @@ void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) {
113 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 113 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
114 rb.Push(RESULT_SUCCESS); 114 rb.Push(RESULT_SUCCESS);
115 rb.PushIpcInterface<IProfile>(); 115 rb.PushIpcInterface<IProfile>();
116 LOG_DEBUG(Service_ACC, "called"); 116 NGLOG_DEBUG(Service_ACC, "called");
117} 117}
118 118
119void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { 119void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
120 LOG_WARNING(Service_ACC, "(STUBBED) called"); 120 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
121 IPC::ResponseBuilder rb{ctx, 2}; 121 IPC::ResponseBuilder rb{ctx, 2};
122 rb.Push(RESULT_SUCCESS); 122 rb.Push(RESULT_SUCCESS);
123} 123}
@@ -126,11 +126,11 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
126 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 126 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
127 rb.Push(RESULT_SUCCESS); 127 rb.Push(RESULT_SUCCESS);
128 rb.PushIpcInterface<IManagerForApplication>(); 128 rb.PushIpcInterface<IManagerForApplication>();
129 LOG_DEBUG(Service_ACC, "called"); 129 NGLOG_DEBUG(Service_ACC, "called");
130} 130}
131 131
132void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { 132void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) {
133 LOG_WARNING(Service_ACC, "(STUBBED) called"); 133 NGLOG_WARNING(Service_ACC, "(STUBBED) called");
134 IPC::ResponseBuilder rb{ctx, 6}; 134 IPC::ResponseBuilder rb{ctx, 6};
135 rb.Push(RESULT_SUCCESS); 135 rb.Push(RESULT_SUCCESS);
136 rb.PushRaw(DEFAULT_USER_ID); 136 rb.PushRaw(DEFAULT_USER_ID);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index f41a59afe..19fadcb8e 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -28,14 +28,14 @@ IWindowController::IWindowController() : ServiceFramework("IWindowController") {
28} 28}
29 29
30void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { 30void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
31 LOG_WARNING(Service_AM, "(STUBBED) called"); 31 NGLOG_WARNING(Service_AM, "(STUBBED) called");
32 IPC::ResponseBuilder rb{ctx, 4}; 32 IPC::ResponseBuilder rb{ctx, 4};
33 rb.Push(RESULT_SUCCESS); 33 rb.Push(RESULT_SUCCESS);
34 rb.Push<u64>(0); 34 rb.Push<u64>(0);
35} 35}
36 36
37void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) { 37void IWindowController::AcquireForegroundRights(Kernel::HLERequestContext& ctx) {
38 LOG_WARNING(Service_AM, "(STUBBED) called"); 38 NGLOG_WARNING(Service_AM, "(STUBBED) called");
39 IPC::ResponseBuilder rb{ctx, 2}; 39 IPC::ResponseBuilder rb{ctx, 2};
40 rb.Push(RESULT_SUCCESS); 40 rb.Push(RESULT_SUCCESS);
41} 41}
@@ -54,20 +54,20 @@ IAudioController::IAudioController() : ServiceFramework("IAudioController") {
54} 54}
55 55
56void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { 56void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
57 LOG_WARNING(Service_AM, "(STUBBED) called"); 57 NGLOG_WARNING(Service_AM, "(STUBBED) called");
58 IPC::ResponseBuilder rb{ctx, 2}; 58 IPC::ResponseBuilder rb{ctx, 2};
59 rb.Push(RESULT_SUCCESS); 59 rb.Push(RESULT_SUCCESS);
60} 60}
61 61
62void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { 62void IAudioController::GetMainAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
63 LOG_WARNING(Service_AM, "(STUBBED) called"); 63 NGLOG_WARNING(Service_AM, "(STUBBED) called");
64 IPC::ResponseBuilder rb{ctx, 3}; 64 IPC::ResponseBuilder rb{ctx, 3};
65 rb.Push(RESULT_SUCCESS); 65 rb.Push(RESULT_SUCCESS);
66 rb.Push(volume); 66 rb.Push(volume);
67} 67}
68 68
69void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) { 69void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
70 LOG_WARNING(Service_AM, "(STUBBED) called"); 70 NGLOG_WARNING(Service_AM, "(STUBBED) called");
71 IPC::ResponseBuilder rb{ctx, 3}; 71 IPC::ResponseBuilder rb{ctx, 3};
72 rb.Push(RESULT_SUCCESS); 72 rb.Push(RESULT_SUCCESS);
73 rb.Push(volume); 73 rb.Push(volume);
@@ -139,14 +139,14 @@ void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
139 IPC::ResponseBuilder rb{ctx, 2}; 139 IPC::ResponseBuilder rb{ctx, 2};
140 rb.Push(RESULT_SUCCESS); 140 rb.Push(RESULT_SUCCESS);
141 141
142 LOG_WARNING(Service_AM, "(STUBBED) called"); 142 NGLOG_WARNING(Service_AM, "(STUBBED) called");
143} 143}
144 144
145void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { 145void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
146 IPC::ResponseBuilder rb{ctx, 2}; 146 IPC::ResponseBuilder rb{ctx, 2};
147 rb.Push(RESULT_SUCCESS); 147 rb.Push(RESULT_SUCCESS);
148 148
149 LOG_WARNING(Service_AM, "(STUBBED) called"); 149 NGLOG_WARNING(Service_AM, "(STUBBED) called");
150} 150}
151 151
152void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { 152void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -157,14 +157,14 @@ void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestCo
157 IPC::ResponseBuilder rb{ctx, 2}; 157 IPC::ResponseBuilder rb{ctx, 2};
158 rb.Push(RESULT_SUCCESS); 158 rb.Push(RESULT_SUCCESS);
159 159
160 LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); 160 NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
161} 161}
162 162
163void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { 163void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) {
164 IPC::ResponseBuilder rb{ctx, 2}; 164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(RESULT_SUCCESS); 165 rb.Push(RESULT_SUCCESS);
166 166
167 LOG_WARNING(Service_AM, "(STUBBED) called"); 167 NGLOG_WARNING(Service_AM, "(STUBBED) called");
168} 168}
169 169
170void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { 170void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
@@ -175,7 +175,7 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont
175 IPC::ResponseBuilder rb{ctx, 2}; 175 IPC::ResponseBuilder rb{ctx, 2};
176 rb.Push(RESULT_SUCCESS); 176 rb.Push(RESULT_SUCCESS);
177 177
178 LOG_WARNING(Service_AM, "(STUBBED) called flag=%u", static_cast<u32>(flag)); 178 NGLOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag);
179} 179}
180 180
181void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { 181void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
@@ -188,21 +188,21 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext&
188 IPC::ResponseBuilder rb{ctx, 2}; 188 IPC::ResponseBuilder rb{ctx, 2};
189 rb.Push(RESULT_SUCCESS); 189 rb.Push(RESULT_SUCCESS);
190 190
191 LOG_WARNING(Service_AM, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); 191 NGLOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled);
192} 192}
193 193
194void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { 194void ISelfController::LockExit(Kernel::HLERequestContext& ctx) {
195 IPC::ResponseBuilder rb{ctx, 2}; 195 IPC::ResponseBuilder rb{ctx, 2};
196 rb.Push(RESULT_SUCCESS); 196 rb.Push(RESULT_SUCCESS);
197 197
198 LOG_WARNING(Service_AM, "(STUBBED) called"); 198 NGLOG_WARNING(Service_AM, "(STUBBED) called");
199} 199}
200 200
201void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { 201void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) {
202 IPC::ResponseBuilder rb{ctx, 2}; 202 IPC::ResponseBuilder rb{ctx, 2};
203 rb.Push(RESULT_SUCCESS); 203 rb.Push(RESULT_SUCCESS);
204 204
205 LOG_WARNING(Service_AM, "(STUBBED) called"); 205 NGLOG_WARNING(Service_AM, "(STUBBED) called");
206} 206}
207 207
208void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { 208void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) {
@@ -212,7 +212,7 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
212 rb.Push(RESULT_SUCCESS); 212 rb.Push(RESULT_SUCCESS);
213 rb.PushCopyObjects(launchable_event); 213 rb.PushCopyObjects(launchable_event);
214 214
215 LOG_WARNING(Service_AM, "(STUBBED) called"); 215 NGLOG_WARNING(Service_AM, "(STUBBED) called");
216} 216}
217 217
218void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) { 218void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
@@ -225,7 +225,7 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
225 rb.Push(RESULT_SUCCESS); 225 rb.Push(RESULT_SUCCESS);
226 rb.Push(layer_id); 226 rb.Push(layer_id);
227 227
228 LOG_WARNING(Service_AM, "(STUBBED) called"); 228 NGLOG_WARNING(Service_AM, "(STUBBED) called");
229} 229}
230 230
231ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") { 231ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
@@ -269,7 +269,7 @@ void ICommonStateGetter::GetEventHandle(Kernel::HLERequestContext& ctx) {
269 rb.Push(RESULT_SUCCESS); 269 rb.Push(RESULT_SUCCESS);
270 rb.PushCopyObjects(event); 270 rb.PushCopyObjects(event);
271 271
272 LOG_WARNING(Service_AM, "(STUBBED) called"); 272 NGLOG_WARNING(Service_AM, "(STUBBED) called");
273} 273}
274 274
275void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) { 275void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
@@ -277,7 +277,7 @@ void ICommonStateGetter::ReceiveMessage(Kernel::HLERequestContext& ctx) {
277 rb.Push(RESULT_SUCCESS); 277 rb.Push(RESULT_SUCCESS);
278 rb.Push<u32>(15); 278 rb.Push<u32>(15);
279 279
280 LOG_WARNING(Service_AM, "(STUBBED) called"); 280 NGLOG_WARNING(Service_AM, "(STUBBED) called");
281} 281}
282 282
283void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { 283void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
@@ -285,7 +285,7 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
285 rb.Push(RESULT_SUCCESS); 285 rb.Push(RESULT_SUCCESS);
286 rb.Push(static_cast<u8>(FocusState::InFocus)); 286 rb.Push(static_cast<u8>(FocusState::InFocus));
287 287
288 LOG_WARNING(Service_AM, "(STUBBED) called"); 288 NGLOG_WARNING(Service_AM, "(STUBBED) called");
289} 289}
290 290
291void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { 291void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
@@ -294,7 +294,7 @@ void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
294 rb.Push(RESULT_SUCCESS); 294 rb.Push(RESULT_SUCCESS);
295 rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld)); 295 rb.Push(static_cast<u8>(use_docked_mode ? OperationMode::Docked : OperationMode::Handheld));
296 296
297 LOG_WARNING(Service_AM, "(STUBBED) called"); 297 NGLOG_WARNING(Service_AM, "(STUBBED) called");
298} 298}
299 299
300void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) { 300void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
@@ -304,7 +304,7 @@ void ICommonStateGetter::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
304 rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked 304 rb.Push(static_cast<u32>(use_docked_mode ? APM::PerformanceMode::Docked
305 : APM::PerformanceMode::Handheld)); 305 : APM::PerformanceMode::Handheld));
306 306
307 LOG_WARNING(Service_AM, "(STUBBED) called"); 307 NGLOG_WARNING(Service_AM, "(STUBBED) called");
308} 308}
309 309
310class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> { 310class ILibraryAppletAccessor final : public ServiceFramework<ILibraryAppletAccessor> {
@@ -344,7 +344,7 @@ private:
344 rb.Push(RESULT_SUCCESS); 344 rb.Push(RESULT_SUCCESS);
345 rb.PushCopyObjects(state_changed_event); 345 rb.PushCopyObjects(state_changed_event);
346 346
347 LOG_WARNING(Service_AM, "(STUBBED) called"); 347 NGLOG_WARNING(Service_AM, "(STUBBED) called");
348 } 348 }
349 349
350 Kernel::SharedPtr<Kernel::Event> state_changed_event; 350 Kernel::SharedPtr<Kernel::Event> state_changed_event;
@@ -368,7 +368,7 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
368 rb.Push(RESULT_SUCCESS); 368 rb.Push(RESULT_SUCCESS);
369 rb.PushIpcInterface<AM::ILibraryAppletAccessor>(); 369 rb.PushIpcInterface<AM::ILibraryAppletAccessor>();
370 370
371 LOG_DEBUG(Service_AM, "called"); 371 NGLOG_DEBUG(Service_AM, "called");
372} 372}
373 373
374class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { 374class IStorageAccessor final : public ServiceFramework<IStorageAccessor> {
@@ -392,7 +392,7 @@ private:
392 rb.Push(RESULT_SUCCESS); 392 rb.Push(RESULT_SUCCESS);
393 rb.Push(static_cast<u64>(buffer.size())); 393 rb.Push(static_cast<u64>(buffer.size()));
394 394
395 LOG_DEBUG(Service_AM, "called"); 395 NGLOG_DEBUG(Service_AM, "called");
396 } 396 }
397 397
398 void Read(Kernel::HLERequestContext& ctx) { 398 void Read(Kernel::HLERequestContext& ctx) {
@@ -410,7 +410,7 @@ private:
410 410
411 rb.Push(RESULT_SUCCESS); 411 rb.Push(RESULT_SUCCESS);
412 412
413 LOG_DEBUG(Service_AM, "called"); 413 NGLOG_DEBUG(Service_AM, "called");
414 } 414 }
415}; 415};
416 416
@@ -434,7 +434,7 @@ private:
434 rb.Push(RESULT_SUCCESS); 434 rb.Push(RESULT_SUCCESS);
435 rb.PushIpcInterface<AM::IStorageAccessor>(buffer); 435 rb.PushIpcInterface<AM::IStorageAccessor>(buffer);
436 436
437 LOG_DEBUG(Service_AM, "called"); 437 NGLOG_DEBUG(Service_AM, "called");
438 } 438 }
439}; 439};
440 440
@@ -498,14 +498,14 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
498 rb.Push(RESULT_SUCCESS); 498 rb.Push(RESULT_SUCCESS);
499 rb.PushIpcInterface<AM::IStorage>(buffer); 499 rb.PushIpcInterface<AM::IStorage>(buffer);
500 500
501 LOG_DEBUG(Service_AM, "called"); 501 NGLOG_DEBUG(Service_AM, "called");
502} 502}
503 503
504void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { 504void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
505 IPC::RequestParser rp{ctx}; 505 IPC::RequestParser rp{ctx};
506 u128 uid = rp.PopRaw<u128>(); 506 u128 uid = rp.PopRaw<u128>();
507 507
508 LOG_WARNING(Service, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); 508 NGLOG_WARNING(Service, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
509 509
510 IPC::ResponseBuilder rb{ctx, 4}; 510 IPC::ResponseBuilder rb{ctx, 4};
511 511
@@ -533,27 +533,27 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
533 IPC::ResponseBuilder rb{ctx, 2}; 533 IPC::ResponseBuilder rb{ctx, 2};
534 rb.Push(RESULT_SUCCESS); 534 rb.Push(RESULT_SUCCESS);
535 535
536 LOG_WARNING(Service_AM, "(STUBBED) called, result=0x%08X", result); 536 NGLOG_WARNING(Service_AM, "(STUBBED) called, result={:#010}", result);
537} 537}
538 538
539void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { 539void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
540 IPC::ResponseBuilder rb{ctx, 4}; 540 IPC::ResponseBuilder rb{ctx, 4};
541 rb.Push(RESULT_SUCCESS); 541 rb.Push(RESULT_SUCCESS);
542 rb.Push<u64>(SystemLanguage::English); 542 rb.Push<u64>(SystemLanguage::English);
543 LOG_WARNING(Service_AM, "(STUBBED) called"); 543 NGLOG_WARNING(Service_AM, "(STUBBED) called");
544} 544}
545 545
546void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { 546void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
547 IPC::ResponseBuilder rb{ctx, 2}; 547 IPC::ResponseBuilder rb{ctx, 2};
548 rb.Push(RESULT_SUCCESS); 548 rb.Push(RESULT_SUCCESS);
549 LOG_WARNING(Service_AM, "(STUBBED) called"); 549 NGLOG_WARNING(Service_AM, "(STUBBED) called");
550} 550}
551 551
552void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { 552void IApplicationFunctions::SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
553 IPC::ResponseBuilder rb{ctx, 2}; 553 IPC::ResponseBuilder rb{ctx, 2};
554 rb.Push(RESULT_SUCCESS); 554 rb.Push(RESULT_SUCCESS);
555 555
556 LOG_WARNING(Service_AM, "(STUBBED) called"); 556 NGLOG_WARNING(Service_AM, "(STUBBED) called");
557} 557}
558 558
559void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) { 559void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
@@ -561,7 +561,7 @@ void IApplicationFunctions::NotifyRunning(Kernel::HLERequestContext& ctx) {
561 rb.Push(RESULT_SUCCESS); 561 rb.Push(RESULT_SUCCESS);
562 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes 562 rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
563 563
564 LOG_WARNING(Service_AM, "(STUBBED) called"); 564 NGLOG_WARNING(Service_AM, "(STUBBED) called");
565} 565}
566 566
567void InstallInterfaces(SM::ServiceManager& service_manager, 567void InstallInterfaces(SM::ServiceManager& service_manager,
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index 4f0698a8a..8951980cf 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -33,56 +33,56 @@ private:
33 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 33 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
34 rb.Push(RESULT_SUCCESS); 34 rb.Push(RESULT_SUCCESS);
35 rb.PushIpcInterface<ICommonStateGetter>(); 35 rb.PushIpcInterface<ICommonStateGetter>();
36 LOG_DEBUG(Service_AM, "called"); 36 NGLOG_DEBUG(Service_AM, "called");
37 } 37 }
38 38
39 void GetSelfController(Kernel::HLERequestContext& ctx) { 39 void GetSelfController(Kernel::HLERequestContext& ctx) {
40 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 40 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
41 rb.Push(RESULT_SUCCESS); 41 rb.Push(RESULT_SUCCESS);
42 rb.PushIpcInterface<ISelfController>(nvflinger); 42 rb.PushIpcInterface<ISelfController>(nvflinger);
43 LOG_DEBUG(Service_AM, "called"); 43 NGLOG_DEBUG(Service_AM, "called");
44 } 44 }
45 45
46 void GetWindowController(Kernel::HLERequestContext& ctx) { 46 void GetWindowController(Kernel::HLERequestContext& ctx) {
47 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 47 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
48 rb.Push(RESULT_SUCCESS); 48 rb.Push(RESULT_SUCCESS);
49 rb.PushIpcInterface<IWindowController>(); 49 rb.PushIpcInterface<IWindowController>();
50 LOG_DEBUG(Service_AM, "called"); 50 NGLOG_DEBUG(Service_AM, "called");
51 } 51 }
52 52
53 void GetAudioController(Kernel::HLERequestContext& ctx) { 53 void GetAudioController(Kernel::HLERequestContext& ctx) {
54 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 54 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
55 rb.Push(RESULT_SUCCESS); 55 rb.Push(RESULT_SUCCESS);
56 rb.PushIpcInterface<IAudioController>(); 56 rb.PushIpcInterface<IAudioController>();
57 LOG_DEBUG(Service_AM, "called"); 57 NGLOG_DEBUG(Service_AM, "called");
58 } 58 }
59 59
60 void GetDisplayController(Kernel::HLERequestContext& ctx) { 60 void GetDisplayController(Kernel::HLERequestContext& ctx) {
61 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 61 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
62 rb.Push(RESULT_SUCCESS); 62 rb.Push(RESULT_SUCCESS);
63 rb.PushIpcInterface<IDisplayController>(); 63 rb.PushIpcInterface<IDisplayController>();
64 LOG_DEBUG(Service_AM, "called"); 64 NGLOG_DEBUG(Service_AM, "called");
65 } 65 }
66 66
67 void GetDebugFunctions(Kernel::HLERequestContext& ctx) { 67 void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
68 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 68 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
69 rb.Push(RESULT_SUCCESS); 69 rb.Push(RESULT_SUCCESS);
70 rb.PushIpcInterface<IDebugFunctions>(); 70 rb.PushIpcInterface<IDebugFunctions>();
71 LOG_DEBUG(Service_AM, "called"); 71 NGLOG_DEBUG(Service_AM, "called");
72 } 72 }
73 73
74 void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { 74 void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
75 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 75 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
76 rb.Push(RESULT_SUCCESS); 76 rb.Push(RESULT_SUCCESS);
77 rb.PushIpcInterface<ILibraryAppletCreator>(); 77 rb.PushIpcInterface<ILibraryAppletCreator>();
78 LOG_DEBUG(Service_AM, "called"); 78 NGLOG_DEBUG(Service_AM, "called");
79 } 79 }
80 80
81 void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { 81 void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
82 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 82 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
83 rb.Push(RESULT_SUCCESS); 83 rb.Push(RESULT_SUCCESS);
84 rb.PushIpcInterface<IApplicationFunctions>(); 84 rb.PushIpcInterface<IApplicationFunctions>();
85 LOG_DEBUG(Service_AM, "called"); 85 NGLOG_DEBUG(Service_AM, "called");
86 } 86 }
87 87
88 std::shared_ptr<NVFlinger::NVFlinger> nvflinger; 88 std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -92,7 +92,7 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
92 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 92 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
93 rb.Push(RESULT_SUCCESS); 93 rb.Push(RESULT_SUCCESS);
94 rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger); 94 rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger);
95 LOG_DEBUG(Service_AM, "called"); 95 NGLOG_DEBUG(Service_AM, "called");
96} 96}
97 97
98AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) 98AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index 674b4d753..68388bf5e 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -33,56 +33,56 @@ private:
33 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 33 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
34 rb.Push(RESULT_SUCCESS); 34 rb.Push(RESULT_SUCCESS);
35 rb.PushIpcInterface<IAudioController>(); 35 rb.PushIpcInterface<IAudioController>();
36 LOG_DEBUG(Service_AM, "called"); 36 NGLOG_DEBUG(Service_AM, "called");
37 } 37 }
38 38
39 void GetDisplayController(Kernel::HLERequestContext& ctx) { 39 void GetDisplayController(Kernel::HLERequestContext& ctx) {
40 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 40 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
41 rb.Push(RESULT_SUCCESS); 41 rb.Push(RESULT_SUCCESS);
42 rb.PushIpcInterface<IDisplayController>(); 42 rb.PushIpcInterface<IDisplayController>();
43 LOG_DEBUG(Service_AM, "called"); 43 NGLOG_DEBUG(Service_AM, "called");
44 } 44 }
45 45
46 void GetDebugFunctions(Kernel::HLERequestContext& ctx) { 46 void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
47 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 47 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
48 rb.Push(RESULT_SUCCESS); 48 rb.Push(RESULT_SUCCESS);
49 rb.PushIpcInterface<IDebugFunctions>(); 49 rb.PushIpcInterface<IDebugFunctions>();
50 LOG_DEBUG(Service_AM, "called"); 50 NGLOG_DEBUG(Service_AM, "called");
51 } 51 }
52 52
53 void GetWindowController(Kernel::HLERequestContext& ctx) { 53 void GetWindowController(Kernel::HLERequestContext& ctx) {
54 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 54 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
55 rb.Push(RESULT_SUCCESS); 55 rb.Push(RESULT_SUCCESS);
56 rb.PushIpcInterface<IWindowController>(); 56 rb.PushIpcInterface<IWindowController>();
57 LOG_DEBUG(Service_AM, "called"); 57 NGLOG_DEBUG(Service_AM, "called");
58 } 58 }
59 59
60 void GetSelfController(Kernel::HLERequestContext& ctx) { 60 void GetSelfController(Kernel::HLERequestContext& ctx) {
61 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 61 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
62 rb.Push(RESULT_SUCCESS); 62 rb.Push(RESULT_SUCCESS);
63 rb.PushIpcInterface<ISelfController>(nvflinger); 63 rb.PushIpcInterface<ISelfController>(nvflinger);
64 LOG_DEBUG(Service_AM, "called"); 64 NGLOG_DEBUG(Service_AM, "called");
65 } 65 }
66 66
67 void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { 67 void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
68 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 68 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
69 rb.Push(RESULT_SUCCESS); 69 rb.Push(RESULT_SUCCESS);
70 rb.PushIpcInterface<ICommonStateGetter>(); 70 rb.PushIpcInterface<ICommonStateGetter>();
71 LOG_DEBUG(Service_AM, "called"); 71 NGLOG_DEBUG(Service_AM, "called");
72 } 72 }
73 73
74 void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { 74 void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
75 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 75 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
76 rb.Push(RESULT_SUCCESS); 76 rb.Push(RESULT_SUCCESS);
77 rb.PushIpcInterface<ILibraryAppletCreator>(); 77 rb.PushIpcInterface<ILibraryAppletCreator>();
78 LOG_DEBUG(Service_AM, "called"); 78 NGLOG_DEBUG(Service_AM, "called");
79 } 79 }
80 80
81 void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { 81 void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
82 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 82 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
83 rb.Push(RESULT_SUCCESS); 83 rb.Push(RESULT_SUCCESS);
84 rb.PushIpcInterface<IApplicationFunctions>(); 84 rb.PushIpcInterface<IApplicationFunctions>();
85 LOG_DEBUG(Service_AM, "called"); 85 NGLOG_DEBUG(Service_AM, "called");
86 } 86 }
87 87
88 std::shared_ptr<NVFlinger::NVFlinger> nvflinger; 88 std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
@@ -92,7 +92,7 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
92 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 92 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
93 rb.Push(RESULT_SUCCESS); 93 rb.Push(RESULT_SUCCESS);
94 rb.PushIpcInterface<IApplicationProxy>(nvflinger); 94 rb.PushIpcInterface<IApplicationProxy>(nvflinger);
95 LOG_DEBUG(Service_AM, "called"); 95 NGLOG_DEBUG(Service_AM, "called");
96} 96}
97 97
98AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) 98AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 6e7438580..5b6dfb48f 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -27,14 +27,14 @@ void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
27 IPC::ResponseBuilder rb{ctx, 4}; 27 IPC::ResponseBuilder rb{ctx, 4};
28 rb.Push(RESULT_SUCCESS); 28 rb.Push(RESULT_SUCCESS);
29 rb.Push<u64>(0); 29 rb.Push<u64>(0);
30 LOG_WARNING(Service_AOC, "(STUBBED) called"); 30 NGLOG_WARNING(Service_AOC, "(STUBBED) called");
31} 31}
32 32
33void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) { 33void AOC_U::ListAddOnContent(Kernel::HLERequestContext& ctx) {
34 IPC::ResponseBuilder rb{ctx, 4}; 34 IPC::ResponseBuilder rb{ctx, 4};
35 rb.Push(RESULT_SUCCESS); 35 rb.Push(RESULT_SUCCESS);
36 rb.Push<u64>(0); 36 rb.Push<u64>(0);
37 LOG_WARNING(Service_AOC, "(STUBBED) called"); 37 NGLOG_WARNING(Service_AOC, "(STUBBED) called");
38} 38}
39 39
40void InstallInterfaces(SM::ServiceManager& service_manager) { 40void InstallInterfaces(SM::ServiceManager& service_manager) {
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index 4e11f3f14..3a03188ce 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -29,8 +29,8 @@ private:
29 IPC::ResponseBuilder rb{ctx, 2}; 29 IPC::ResponseBuilder rb{ctx, 2};
30 rb.Push(RESULT_SUCCESS); 30 rb.Push(RESULT_SUCCESS);
31 31
32 LOG_WARNING(Service_APM, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), 32 NGLOG_WARNING(Service_APM, "(STUBBED) called mode={} config={}", static_cast<u32>(mode),
33 config); 33 config);
34 } 34 }
35 35
36 void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { 36 void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
@@ -42,7 +42,7 @@ private:
42 rb.Push(RESULT_SUCCESS); 42 rb.Push(RESULT_SUCCESS);
43 rb.Push<u32>(0); // Performance configuration 43 rb.Push<u32>(0); // Performance configuration
44 44
45 LOG_WARNING(Service_APM, "(STUBBED) called mode=%u", static_cast<u32>(mode)); 45 NGLOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
46 } 46 }
47}; 47};
48 48
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 2d7f8cb04..6297dc450 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -60,14 +60,14 @@ public:
60 60
61private: 61private:
62 void GetAudioOutState(Kernel::HLERequestContext& ctx) { 62 void GetAudioOutState(Kernel::HLERequestContext& ctx) {
63 LOG_DEBUG(Service_Audio, "called"); 63 NGLOG_DEBUG(Service_Audio, "called");
64 IPC::ResponseBuilder rb{ctx, 3}; 64 IPC::ResponseBuilder rb{ctx, 3};
65 rb.Push(RESULT_SUCCESS); 65 rb.Push(RESULT_SUCCESS);
66 rb.Push(static_cast<u32>(audio_out_state)); 66 rb.Push(static_cast<u32>(audio_out_state));
67 } 67 }
68 68
69 void StartAudioOut(Kernel::HLERequestContext& ctx) { 69 void StartAudioOut(Kernel::HLERequestContext& ctx) {
70 LOG_WARNING(Service_Audio, "(STUBBED) called"); 70 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
71 71
72 // Start audio 72 // Start audio
73 audio_out_state = AudioState::Started; 73 audio_out_state = AudioState::Started;
@@ -77,7 +77,7 @@ private:
77 } 77 }
78 78
79 void StopAudioOut(Kernel::HLERequestContext& ctx) { 79 void StopAudioOut(Kernel::HLERequestContext& ctx) {
80 LOG_WARNING(Service_Audio, "(STUBBED) called"); 80 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
81 81
82 // Stop audio 82 // Stop audio
83 audio_out_state = AudioState::Stopped; 83 audio_out_state = AudioState::Stopped;
@@ -89,7 +89,7 @@ private:
89 } 89 }
90 90
91 void RegisterBufferEvent(Kernel::HLERequestContext& ctx) { 91 void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
92 LOG_WARNING(Service_Audio, "(STUBBED) called"); 92 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
93 93
94 IPC::ResponseBuilder rb{ctx, 2, 1}; 94 IPC::ResponseBuilder rb{ctx, 2, 1};
95 rb.Push(RESULT_SUCCESS); 95 rb.Push(RESULT_SUCCESS);
@@ -97,7 +97,7 @@ private:
97 } 97 }
98 98
99 void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) { 99 void AppendAudioOutBuffer(Kernel::HLERequestContext& ctx) {
100 LOG_WARNING(Service_Audio, "(STUBBED) called"); 100 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
101 IPC::RequestParser rp{ctx}; 101 IPC::RequestParser rp{ctx};
102 102
103 const u64 key{rp.Pop<u64>()}; 103 const u64 key{rp.Pop<u64>()};
@@ -108,7 +108,7 @@ private:
108 } 108 }
109 109
110 void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) { 110 void GetReleasedAudioOutBuffer(Kernel::HLERequestContext& ctx) {
111 LOG_WARNING(Service_Audio, "(STUBBED) called"); 111 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
112 112
113 // TODO(st4rk): This is how libtransistor currently implements the 113 // TODO(st4rk): This is how libtransistor currently implements the
114 // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address 114 // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
@@ -164,7 +164,7 @@ private:
164}; 164};
165 165
166void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { 166void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
167 LOG_WARNING(Service_Audio, "(STUBBED) called"); 167 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
168 IPC::RequestParser rp{ctx}; 168 IPC::RequestParser rp{ctx};
169 169
170 const std::string audio_interface = "AudioInterface"; 170 const std::string audio_interface = "AudioInterface";
@@ -180,7 +180,7 @@ void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) {
180} 180}
181 181
182void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) { 182void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
183 LOG_WARNING(Service_Audio, "(STUBBED) called"); 183 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
184 184
185 if (!audio_out_interface) { 185 if (!audio_out_interface) {
186 audio_out_interface = std::make_shared<IAudioOut>(); 186 audio_out_interface = std::make_shared<IAudioOut>();
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index a9360614c..291885db8 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -56,7 +56,7 @@ private:
56 } 56 }
57 57
58 void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) { 58 void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
59 LOG_DEBUG(Service_Audio, "%s", ctx.Description().c_str()); 59 NGLOG_DEBUG(Service_Audio, "{}", ctx.Description());
60 AudioRendererResponseData response_data{}; 60 AudioRendererResponseData response_data{};
61 61
62 response_data.section_0_size = 62 response_data.section_0_size =
@@ -79,7 +79,7 @@ private:
79 79
80 rb.Push(RESULT_SUCCESS); 80 rb.Push(RESULT_SUCCESS);
81 81
82 LOG_WARNING(Service_Audio, "(STUBBED) called"); 82 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
83 } 83 }
84 84
85 void StartAudioRenderer(Kernel::HLERequestContext& ctx) { 85 void StartAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -87,7 +87,7 @@ private:
87 87
88 rb.Push(RESULT_SUCCESS); 88 rb.Push(RESULT_SUCCESS);
89 89
90 LOG_WARNING(Service_Audio, "(STUBBED) called"); 90 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
91 } 91 }
92 92
93 void StopAudioRenderer(Kernel::HLERequestContext& ctx) { 93 void StopAudioRenderer(Kernel::HLERequestContext& ctx) {
@@ -95,7 +95,7 @@ private:
95 95
96 rb.Push(RESULT_SUCCESS); 96 rb.Push(RESULT_SUCCESS);
97 97
98 LOG_WARNING(Service_Audio, "(STUBBED) called"); 98 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
99 } 99 }
100 100
101 void QuerySystemEvent(Kernel::HLERequestContext& ctx) { 101 void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
@@ -105,7 +105,7 @@ private:
105 rb.Push(RESULT_SUCCESS); 105 rb.Push(RESULT_SUCCESS);
106 rb.PushCopyObjects(system_event); 106 rb.PushCopyObjects(system_event);
107 107
108 LOG_WARNING(Service_Audio, "(STUBBED) called"); 108 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
109 } 109 }
110 110
111 struct AudioRendererStateEntry { 111 struct AudioRendererStateEntry {
@@ -177,7 +177,7 @@ public:
177 177
178private: 178private:
179 void ListAudioDeviceName(Kernel::HLERequestContext& ctx) { 179 void ListAudioDeviceName(Kernel::HLERequestContext& ctx) {
180 LOG_WARNING(Service_Audio, "(STUBBED) called"); 180 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
181 IPC::RequestParser rp{ctx}; 181 IPC::RequestParser rp{ctx};
182 182
183 const std::string audio_interface = "AudioInterface"; 183 const std::string audio_interface = "AudioInterface";
@@ -189,7 +189,7 @@ private:
189 } 189 }
190 190
191 void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { 191 void SetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
192 LOG_WARNING(Service_Audio, "(STUBBED) called"); 192 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
193 193
194 IPC::RequestParser rp{ctx}; 194 IPC::RequestParser rp{ctx};
195 f32 volume = static_cast<f32>(rp.Pop<u32>()); 195 f32 volume = static_cast<f32>(rp.Pop<u32>());
@@ -202,7 +202,7 @@ private:
202 } 202 }
203 203
204 void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) { 204 void GetActiveAudioDeviceName(Kernel::HLERequestContext& ctx) {
205 LOG_WARNING(Service_Audio, "(STUBBED) called"); 205 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
206 IPC::RequestParser rp{ctx}; 206 IPC::RequestParser rp{ctx};
207 207
208 const std::string audio_interface = "AudioDevice"; 208 const std::string audio_interface = "AudioDevice";
@@ -214,7 +214,7 @@ private:
214 } 214 }
215 215
216 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { 216 void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) {
217 LOG_WARNING(Service_Audio, "(STUBBED) called"); 217 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
218 218
219 buffer_event->Signal(); 219 buffer_event->Signal();
220 220
@@ -224,7 +224,7 @@ private:
224 } 224 }
225 225
226 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { 226 void GetActiveChannelCount(Kernel::HLERequestContext& ctx) {
227 LOG_WARNING(Service_Audio, "(STUBBED) called"); 227 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
228 IPC::ResponseBuilder rb{ctx, 3}; 228 IPC::ResponseBuilder rb{ctx, 3};
229 rb.Push(RESULT_SUCCESS); 229 rb.Push(RESULT_SUCCESS);
230 rb.Push<u32>(1); 230 rb.Push<u32>(1);
@@ -251,7 +251,7 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
251 rb.Push(RESULT_SUCCESS); 251 rb.Push(RESULT_SUCCESS);
252 rb.PushIpcInterface<Audio::IAudioRenderer>(); 252 rb.PushIpcInterface<Audio::IAudioRenderer>();
253 253
254 LOG_DEBUG(Service_Audio, "called"); 254 NGLOG_DEBUG(Service_Audio, "called");
255} 255}
256 256
257void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { 257void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
@@ -260,7 +260,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
260 rb.Push(RESULT_SUCCESS); 260 rb.Push(RESULT_SUCCESS);
261 rb.Push<u64>(0x4000); 261 rb.Push<u64>(0x4000);
262 262
263 LOG_WARNING(Service_Audio, "(STUBBED) called"); 263 NGLOG_WARNING(Service_Audio, "(STUBBED) called");
264} 264}
265 265
266void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { 266void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@@ -269,7 +269,7 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
269 rb.Push(RESULT_SUCCESS); 269 rb.Push(RESULT_SUCCESS);
270 rb.PushIpcInterface<Audio::IAudioDevice>(); 270 rb.PushIpcInterface<Audio::IAudioDevice>();
271 271
272 LOG_DEBUG(Service_Audio, "called"); 272 NGLOG_DEBUG(Service_Audio, "called");
273} 273}
274 274
275} // namespace Service::Audio 275} // namespace Service::Audio
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 41d58f999..d7ad0600a 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -16,13 +16,13 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
16void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) { 16void Module::Interface::FatalSimple(Kernel::HLERequestContext& ctx) {
17 IPC::RequestParser rp(ctx); 17 IPC::RequestParser rp(ctx);
18 u32 error_code = rp.Pop<u32>(); 18 u32 error_code = rp.Pop<u32>();
19 LOG_WARNING(Service_Fatal, "(STUBBED) called, error_code=0x%X", error_code); 19 NGLOG_WARNING(Service_Fatal, "(STUBBED) called, error_code={:#X}", error_code);
20 IPC::ResponseBuilder rb{ctx, 2}; 20 IPC::ResponseBuilder rb{ctx, 2};
21 rb.Push(RESULT_SUCCESS); 21 rb.Push(RESULT_SUCCESS);
22} 22}
23 23
24void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) { 24void Module::Interface::TransitionToFatalError(Kernel::HLERequestContext& ctx) {
25 LOG_WARNING(Service_Fatal, "(STUBBED) called"); 25 NGLOG_WARNING(Service_Fatal, "(STUBBED) called");
26 IPC::ResponseBuilder rb{ctx, 2}; 26 IPC::ResponseBuilder rb{ctx, 2};
27 rb.Push(RESULT_SUCCESS); 27 rb.Push(RESULT_SUCCESS);
28} 28}
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 9e504992f..c2951c560 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -25,14 +25,14 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact
25 ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); 25 ASSERT_MSG(inserted, "Tried to register more than one system with same id code");
26 26
27 auto& filesystem = result.first->second; 27 auto& filesystem = result.first->second;
28 LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X", 28 NGLOG_DEBUG(Service_FS, "Registered file system {} with id code {:#010X}",
29 filesystem->GetName().c_str(), static_cast<u32>(type)); 29 filesystem->GetName(), static_cast<u32>(type));
30 return RESULT_SUCCESS; 30 return RESULT_SUCCESS;
31} 31}
32 32
33ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, 33ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
34 FileSys::Path& path) { 34 FileSys::Path& path) {
35 LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type); 35 NGLOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type));
36 36
37 auto itr = filesystem_map.find(type); 37 auto itr = filesystem_map.find(type);
38 if (itr == filesystem_map.end()) { 38 if (itr == filesystem_map.end()) {
@@ -44,7 +44,7 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type,
44} 44}
45 45
46ResultCode FormatFileSystem(Type type) { 46ResultCode FormatFileSystem(Type type) {
47 LOG_TRACE(Service_FS, "Formatting FileSystem with type=%d", type); 47 NGLOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast<u32>(type));
48 48
49 auto itr = filesystem_map.find(type); 49 auto itr = filesystem_map.find(type);
50 if (itr == filesystem_map.end()) { 50 if (itr == filesystem_map.end()) {
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 2f476c869..ed9f2ef72 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -35,7 +35,7 @@ private:
35 const s64 offset = rp.Pop<s64>(); 35 const s64 offset = rp.Pop<s64>();
36 const s64 length = rp.Pop<s64>(); 36 const s64 length = rp.Pop<s64>();
37 37
38 LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); 38 NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
39 39
40 // Error checking 40 // Error checking
41 if (length < 0) { 41 if (length < 0) {
@@ -87,7 +87,7 @@ private:
87 const s64 offset = rp.Pop<s64>(); 87 const s64 offset = rp.Pop<s64>();
88 const s64 length = rp.Pop<s64>(); 88 const s64 length = rp.Pop<s64>();
89 89
90 LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); 90 NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
91 91
92 // Error checking 92 // Error checking
93 if (length < 0) { 93 if (length < 0) {
@@ -124,7 +124,7 @@ private:
124 const s64 offset = rp.Pop<s64>(); 124 const s64 offset = rp.Pop<s64>();
125 const s64 length = rp.Pop<s64>(); 125 const s64 length = rp.Pop<s64>();
126 126
127 LOG_DEBUG(Service_FS, "called, offset=0x%ld, length=0x%ld", offset, length); 127 NGLOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
128 128
129 // Error checking 129 // Error checking
130 if (length < 0) { 130 if (length < 0) {
@@ -152,7 +152,7 @@ private:
152 } 152 }
153 153
154 void Flush(Kernel::HLERequestContext& ctx) { 154 void Flush(Kernel::HLERequestContext& ctx) {
155 LOG_DEBUG(Service_FS, "called"); 155 NGLOG_DEBUG(Service_FS, "called");
156 backend->Flush(); 156 backend->Flush();
157 157
158 IPC::ResponseBuilder rb{ctx, 2}; 158 IPC::ResponseBuilder rb{ctx, 2};
@@ -163,7 +163,7 @@ private:
163 IPC::RequestParser rp{ctx}; 163 IPC::RequestParser rp{ctx};
164 const u64 size = rp.Pop<u64>(); 164 const u64 size = rp.Pop<u64>();
165 backend->SetSize(size); 165 backend->SetSize(size);
166 LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); 166 NGLOG_DEBUG(Service_FS, "called, size={}", size);
167 167
168 IPC::ResponseBuilder rb{ctx, 2}; 168 IPC::ResponseBuilder rb{ctx, 2};
169 rb.Push(RESULT_SUCCESS); 169 rb.Push(RESULT_SUCCESS);
@@ -171,7 +171,7 @@ private:
171 171
172 void GetSize(Kernel::HLERequestContext& ctx) { 172 void GetSize(Kernel::HLERequestContext& ctx) {
173 const u64 size = backend->GetSize(); 173 const u64 size = backend->GetSize();
174 LOG_DEBUG(Service_FS, "called, size=%" PRIu64, size); 174 NGLOG_DEBUG(Service_FS, "called, size={}", size);
175 175
176 IPC::ResponseBuilder rb{ctx, 4}; 176 IPC::ResponseBuilder rb{ctx, 4};
177 rb.Push(RESULT_SUCCESS); 177 rb.Push(RESULT_SUCCESS);
@@ -197,7 +197,7 @@ private:
197 IPC::RequestParser rp{ctx}; 197 IPC::RequestParser rp{ctx};
198 const u64 unk = rp.Pop<u64>(); 198 const u64 unk = rp.Pop<u64>();
199 199
200 LOG_DEBUG(Service_FS, "called, unk=0x%llx", unk); 200 NGLOG_DEBUG(Service_FS, "called, unk={:#X}", unk);
201 201
202 // Calculate how many entries we can fit in the output buffer 202 // Calculate how many entries we can fit in the output buffer
203 u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); 203 u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry);
@@ -219,7 +219,7 @@ private:
219 } 219 }
220 220
221 void GetEntryCount(Kernel::HLERequestContext& ctx) { 221 void GetEntryCount(Kernel::HLERequestContext& ctx) {
222 LOG_DEBUG(Service_FS, "called"); 222 NGLOG_DEBUG(Service_FS, "called");
223 223
224 u64 count = backend->GetEntryCount(); 224 u64 count = backend->GetEntryCount();
225 225
@@ -239,7 +239,7 @@ public:
239 {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, 239 {2, &IFileSystem::CreateDirectory, "CreateDirectory"},
240 {3, nullptr, "DeleteDirectory"}, 240 {3, nullptr, "DeleteDirectory"},
241 {4, nullptr, "DeleteDirectoryRecursively"}, 241 {4, nullptr, "DeleteDirectoryRecursively"},
242 {5, nullptr, "RenameFile"}, 242 {5, &IFileSystem::RenameFile, "RenameFile"},
243 {6, nullptr, "RenameDirectory"}, 243 {6, nullptr, "RenameDirectory"},
244 {7, &IFileSystem::GetEntryType, "GetEntryType"}, 244 {7, &IFileSystem::GetEntryType, "GetEntryType"},
245 {8, &IFileSystem::OpenFile, "OpenFile"}, 245 {8, &IFileSystem::OpenFile, "OpenFile"},
@@ -265,8 +265,7 @@ public:
265 u64 mode = rp.Pop<u64>(); 265 u64 mode = rp.Pop<u64>();
266 u32 size = rp.Pop<u32>(); 266 u32 size = rp.Pop<u32>();
267 267
268 LOG_DEBUG(Service_FS, "called file %s mode 0x%" PRIX64 " size 0x%08X", name.c_str(), mode, 268 NGLOG_DEBUG(Service_FS, "called file {} mode {:#X} size {:#010X}", name, mode, size);
269 size);
270 269
271 IPC::ResponseBuilder rb{ctx, 2}; 270 IPC::ResponseBuilder rb{ctx, 2};
272 rb.Push(backend->CreateFile(name, size)); 271 rb.Push(backend->CreateFile(name, size));
@@ -280,7 +279,7 @@ public:
280 279
281 std::string name(file_buffer.begin(), end); 280 std::string name(file_buffer.begin(), end);
282 281
283 LOG_DEBUG(Service_FS, "called file %s", name.c_str()); 282 NGLOG_DEBUG(Service_FS, "called file {}", name);
284 283
285 IPC::ResponseBuilder rb{ctx, 2}; 284 IPC::ResponseBuilder rb{ctx, 2};
286 rb.Push(backend->DeleteFile(name)); 285 rb.Push(backend->DeleteFile(name));
@@ -294,12 +293,32 @@ public:
294 293
295 std::string name(file_buffer.begin(), end); 294 std::string name(file_buffer.begin(), end);
296 295
297 LOG_DEBUG(Service_FS, "called directory %s", name.c_str()); 296 NGLOG_DEBUG(Service_FS, "called directory {}", name);
298 297
299 IPC::ResponseBuilder rb{ctx, 2}; 298 IPC::ResponseBuilder rb{ctx, 2};
300 rb.Push(backend->CreateDirectory(name)); 299 rb.Push(backend->CreateDirectory(name));
301 } 300 }
302 301
302 void RenameFile(Kernel::HLERequestContext& ctx) {
303 IPC::RequestParser rp{ctx};
304
305 std::vector<u8> buffer;
306 buffer.resize(ctx.BufferDescriptorX()[0].Size());
307 Memory::ReadBlock(ctx.BufferDescriptorX()[0].Address(), buffer.data(), buffer.size());
308 auto end = std::find(buffer.begin(), buffer.end(), '\0');
309 std::string src_name(buffer.begin(), end);
310
311 buffer.resize(ctx.BufferDescriptorX()[1].Size());
312 Memory::ReadBlock(ctx.BufferDescriptorX()[1].Address(), buffer.data(), buffer.size());
313 end = std::find(buffer.begin(), buffer.end(), '\0');
314 std::string dst_name(buffer.begin(), end);
315
316 NGLOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name);
317
318 IPC::ResponseBuilder rb{ctx, 2};
319 rb.Push(backend->RenameFile(src_name, dst_name));
320 }
321
303 void OpenFile(Kernel::HLERequestContext& ctx) { 322 void OpenFile(Kernel::HLERequestContext& ctx) {
304 IPC::RequestParser rp{ctx}; 323 IPC::RequestParser rp{ctx};
305 324
@@ -310,7 +329,7 @@ public:
310 329
311 auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>()); 330 auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>());
312 331
313 LOG_DEBUG(Service_FS, "called file %s mode %u", name.c_str(), static_cast<u32>(mode)); 332 NGLOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode));
314 333
315 auto result = backend->OpenFile(name, mode); 334 auto result = backend->OpenFile(name, mode);
316 if (result.Failed()) { 335 if (result.Failed()) {
@@ -337,7 +356,7 @@ public:
337 // TODO(Subv): Implement this filter. 356 // TODO(Subv): Implement this filter.
338 u32 filter_flags = rp.Pop<u32>(); 357 u32 filter_flags = rp.Pop<u32>();
339 358
340 LOG_DEBUG(Service_FS, "called directory %s filter %u", name.c_str(), filter_flags); 359 NGLOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags);
341 360
342 auto result = backend->OpenDirectory(name); 361 auto result = backend->OpenDirectory(name);
343 if (result.Failed()) { 362 if (result.Failed()) {
@@ -361,7 +380,7 @@ public:
361 380
362 std::string name(file_buffer.begin(), end); 381 std::string name(file_buffer.begin(), end);
363 382
364 LOG_DEBUG(Service_FS, "called file %s", name.c_str()); 383 NGLOG_DEBUG(Service_FS, "called file {}", name);
365 384
366 auto result = backend->GetEntryType(name); 385 auto result = backend->GetEntryType(name);
367 if (result.Failed()) { 386 if (result.Failed()) {
@@ -376,7 +395,7 @@ public:
376 } 395 }
377 396
378 void Commit(Kernel::HLERequestContext& ctx) { 397 void Commit(Kernel::HLERequestContext& ctx) {
379 LOG_WARNING(Service_FS, "(STUBBED) called"); 398 NGLOG_WARNING(Service_FS, "(STUBBED) called");
380 399
381 IPC::ResponseBuilder rb{ctx, 2}; 400 IPC::ResponseBuilder rb{ctx, 2};
382 rb.Push(RESULT_SUCCESS); 401 rb.Push(RESULT_SUCCESS);
@@ -492,14 +511,14 @@ void FSP_SRV::TryLoadRomFS() {
492} 511}
493 512
494void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { 513void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
495 LOG_WARNING(Service_FS, "(STUBBED) called"); 514 NGLOG_WARNING(Service_FS, "(STUBBED) called");
496 515
497 IPC::ResponseBuilder rb{ctx, 2}; 516 IPC::ResponseBuilder rb{ctx, 2};
498 rb.Push(RESULT_SUCCESS); 517 rb.Push(RESULT_SUCCESS);
499} 518}
500 519
501void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { 520void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
502 LOG_DEBUG(Service_FS, "called"); 521 NGLOG_DEBUG(Service_FS, "called");
503 522
504 FileSys::Path unused; 523 FileSys::Path unused;
505 auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); 524 auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap();
@@ -516,14 +535,14 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
516 auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>(); 535 auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
517 u128 uid = rp.PopRaw<u128>(); 536 u128 uid = rp.PopRaw<u128>();
518 537
519 LOG_WARNING(Service_FS, "(STUBBED) called uid = %016" PRIX64 "%016" PRIX64, uid[1], uid[0]); 538 NGLOG_WARNING(Service_FS, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]);
520 539
521 IPC::ResponseBuilder rb{ctx, 2}; 540 IPC::ResponseBuilder rb{ctx, 2};
522 rb.Push(RESULT_SUCCESS); 541 rb.Push(RESULT_SUCCESS);
523} 542}
524 543
525void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { 544void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
526 LOG_WARNING(Service_FS, "(STUBBED) called"); 545 NGLOG_WARNING(Service_FS, "(STUBBED) called");
527 546
528 FileSys::Path unused; 547 FileSys::Path unused;
529 auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap(); 548 auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap();
@@ -534,7 +553,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
534} 553}
535 554
536void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { 555void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
537 LOG_WARNING(Service_FS, "(STUBBED) called"); 556 NGLOG_WARNING(Service_FS, "(STUBBED) called");
538 557
539 IPC::ResponseBuilder rb{ctx, 3}; 558 IPC::ResponseBuilder rb{ctx, 3};
540 rb.Push(RESULT_SUCCESS); 559 rb.Push(RESULT_SUCCESS);
@@ -542,12 +561,12 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
542} 561}
543 562
544void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { 563void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
545 LOG_DEBUG(Service_FS, "called"); 564 NGLOG_DEBUG(Service_FS, "called");
546 565
547 TryLoadRomFS(); 566 TryLoadRomFS();
548 if (!romfs) { 567 if (!romfs) {
549 // TODO (bunnei): Find the right error code to use here 568 // TODO (bunnei): Find the right error code to use here
550 LOG_CRITICAL(Service_FS, "no file system interface available!"); 569 NGLOG_CRITICAL(Service_FS, "no file system interface available!");
551 IPC::ResponseBuilder rb{ctx, 2}; 570 IPC::ResponseBuilder rb{ctx, 2};
552 rb.Push(ResultCode(-1)); 571 rb.Push(ResultCode(-1));
553 return; 572 return;
@@ -556,7 +575,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
556 // Attempt to open a StorageBackend interface to the RomFS 575 // Attempt to open a StorageBackend interface to the RomFS
557 auto storage = romfs->OpenFile({}, {}); 576 auto storage = romfs->OpenFile({}, {});
558 if (storage.Failed()) { 577 if (storage.Failed()) {
559 LOG_CRITICAL(Service_FS, "no storage interface available!"); 578 NGLOG_CRITICAL(Service_FS, "no storage interface available!");
560 IPC::ResponseBuilder rb{ctx, 2}; 579 IPC::ResponseBuilder rb{ctx, 2};
561 rb.Push(storage.Code()); 580 rb.Push(storage.Code());
562 return; 581 return;
@@ -568,7 +587,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
568} 587}
569 588
570void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { 589void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
571 LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess"); 590 NGLOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess");
572 OpenDataStorageByCurrentProcess(ctx); 591 OpenDataStorageByCurrentProcess(ctx);
573} 592}
574 593
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index c98a46e05..94d9fbf25 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -13,7 +13,7 @@ namespace Service::Friend {
13void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { 13void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
14 IPC::ResponseBuilder rb{ctx, 2}; 14 IPC::ResponseBuilder rb{ctx, 2};
15 rb.Push(RESULT_SUCCESS); 15 rb.Push(RESULT_SUCCESS);
16 LOG_WARNING(Service_Friend, "(STUBBED) called"); 16 NGLOG_WARNING(Service_Friend, "(STUBBED) called");
17} 17}
18 18
19Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 19Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index aad5e688b..736180b63 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -53,7 +53,7 @@ private:
53 IPC::ResponseBuilder rb{ctx, 2, 1}; 53 IPC::ResponseBuilder rb{ctx, 2, 1};
54 rb.Push(RESULT_SUCCESS); 54 rb.Push(RESULT_SUCCESS);
55 rb.PushCopyObjects(shared_mem); 55 rb.PushCopyObjects(shared_mem);
56 LOG_DEBUG(Service_HID, "called"); 56 NGLOG_DEBUG(Service_HID, "called");
57 } 57 }
58 58
59 void LoadInputDevices() { 59 void LoadInputDevices() {
@@ -184,7 +184,7 @@ private:
184 void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) { 184 void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
185 IPC::ResponseBuilder rb{ctx, 2}; 185 IPC::ResponseBuilder rb{ctx, 2};
186 rb.Push(RESULT_SUCCESS); 186 rb.Push(RESULT_SUCCESS);
187 LOG_WARNING(Service_HID, "(STUBBED) called"); 187 NGLOG_WARNING(Service_HID, "(STUBBED) called");
188 } 188 }
189}; 189};
190 190
@@ -286,144 +286,144 @@ private:
286 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 286 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
287 rb.Push(RESULT_SUCCESS); 287 rb.Push(RESULT_SUCCESS);
288 rb.PushIpcInterface<IAppletResource>(applet_resource); 288 rb.PushIpcInterface<IAppletResource>(applet_resource);
289 LOG_DEBUG(Service_HID, "called"); 289 NGLOG_DEBUG(Service_HID, "called");
290 } 290 }
291 291
292 void ActivateDebugPad(Kernel::HLERequestContext& ctx) { 292 void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
293 IPC::ResponseBuilder rb{ctx, 2}; 293 IPC::ResponseBuilder rb{ctx, 2};
294 rb.Push(RESULT_SUCCESS); 294 rb.Push(RESULT_SUCCESS);
295 LOG_WARNING(Service_HID, "(STUBBED) called"); 295 NGLOG_WARNING(Service_HID, "(STUBBED) called");
296 } 296 }
297 297
298 void ActivateTouchScreen(Kernel::HLERequestContext& ctx) { 298 void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
299 IPC::ResponseBuilder rb{ctx, 2}; 299 IPC::ResponseBuilder rb{ctx, 2};
300 rb.Push(RESULT_SUCCESS); 300 rb.Push(RESULT_SUCCESS);
301 LOG_WARNING(Service_HID, "(STUBBED) called"); 301 NGLOG_WARNING(Service_HID, "(STUBBED) called");
302 } 302 }
303 303
304 void ActivateMouse(Kernel::HLERequestContext& ctx) { 304 void ActivateMouse(Kernel::HLERequestContext& ctx) {
305 IPC::ResponseBuilder rb{ctx, 2}; 305 IPC::ResponseBuilder rb{ctx, 2};
306 rb.Push(RESULT_SUCCESS); 306 rb.Push(RESULT_SUCCESS);
307 LOG_WARNING(Service_HID, "(STUBBED) called"); 307 NGLOG_WARNING(Service_HID, "(STUBBED) called");
308 } 308 }
309 309
310 void ActivateKeyboard(Kernel::HLERequestContext& ctx) { 310 void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
311 IPC::ResponseBuilder rb{ctx, 2}; 311 IPC::ResponseBuilder rb{ctx, 2};
312 rb.Push(RESULT_SUCCESS); 312 rb.Push(RESULT_SUCCESS);
313 LOG_WARNING(Service_HID, "(STUBBED) called"); 313 NGLOG_WARNING(Service_HID, "(STUBBED) called");
314 } 314 }
315 315
316 void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { 316 void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
317 IPC::ResponseBuilder rb{ctx, 2}; 317 IPC::ResponseBuilder rb{ctx, 2};
318 rb.Push(RESULT_SUCCESS); 318 rb.Push(RESULT_SUCCESS);
319 LOG_WARNING(Service_HID, "(STUBBED) called"); 319 NGLOG_WARNING(Service_HID, "(STUBBED) called");
320 } 320 }
321 321
322 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 322 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
323 IPC::ResponseBuilder rb{ctx, 2}; 323 IPC::ResponseBuilder rb{ctx, 2};
324 rb.Push(RESULT_SUCCESS); 324 rb.Push(RESULT_SUCCESS);
325 LOG_WARNING(Service_HID, "(STUBBED) called"); 325 NGLOG_WARNING(Service_HID, "(STUBBED) called");
326 } 326 }
327 327
328 void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { 328 void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
329 IPC::ResponseBuilder rb{ctx, 2}; 329 IPC::ResponseBuilder rb{ctx, 2};
330 rb.Push(RESULT_SUCCESS); 330 rb.Push(RESULT_SUCCESS);
331 LOG_WARNING(Service_HID, "(STUBBED) called"); 331 NGLOG_WARNING(Service_HID, "(STUBBED) called");
332 } 332 }
333 333
334 void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { 334 void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
335 IPC::ResponseBuilder rb{ctx, 3}; 335 IPC::ResponseBuilder rb{ctx, 3};
336 rb.Push(RESULT_SUCCESS); 336 rb.Push(RESULT_SUCCESS);
337 rb.Push<u32>(0); 337 rb.Push<u32>(0);
338 LOG_WARNING(Service_HID, "(STUBBED) called"); 338 NGLOG_WARNING(Service_HID, "(STUBBED) called");
339 } 339 }
340 340
341 void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { 341 void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
342 IPC::ResponseBuilder rb{ctx, 2}; 342 IPC::ResponseBuilder rb{ctx, 2};
343 rb.Push(RESULT_SUCCESS); 343 rb.Push(RESULT_SUCCESS);
344 LOG_WARNING(Service_HID, "(STUBBED) called"); 344 NGLOG_WARNING(Service_HID, "(STUBBED) called");
345 } 345 }
346 346
347 void ActivateNpad(Kernel::HLERequestContext& ctx) { 347 void ActivateNpad(Kernel::HLERequestContext& ctx) {
348 IPC::ResponseBuilder rb{ctx, 2}; 348 IPC::ResponseBuilder rb{ctx, 2};
349 rb.Push(RESULT_SUCCESS); 349 rb.Push(RESULT_SUCCESS);
350 LOG_WARNING(Service_HID, "(STUBBED) called"); 350 NGLOG_WARNING(Service_HID, "(STUBBED) called");
351 } 351 }
352 352
353 void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { 353 void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
354 IPC::ResponseBuilder rb{ctx, 2, 1}; 354 IPC::ResponseBuilder rb{ctx, 2, 1};
355 rb.Push(RESULT_SUCCESS); 355 rb.Push(RESULT_SUCCESS);
356 rb.PushCopyObjects(event); 356 rb.PushCopyObjects(event);
357 LOG_WARNING(Service_HID, "(STUBBED) called"); 357 NGLOG_WARNING(Service_HID, "(STUBBED) called");
358 } 358 }
359 359
360 void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { 360 void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
361 IPC::ResponseBuilder rb{ctx, 2}; 361 IPC::ResponseBuilder rb{ctx, 2};
362 rb.Push(RESULT_SUCCESS); 362 rb.Push(RESULT_SUCCESS);
363 LOG_WARNING(Service_HID, "(STUBBED) called"); 363 NGLOG_WARNING(Service_HID, "(STUBBED) called");
364 } 364 }
365 365
366 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { 366 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
367 IPC::ResponseBuilder rb{ctx, 2}; 367 IPC::ResponseBuilder rb{ctx, 2};
368 rb.Push(RESULT_SUCCESS); 368 rb.Push(RESULT_SUCCESS);
369 LOG_WARNING(Service_HID, "(STUBBED) called"); 369 NGLOG_WARNING(Service_HID, "(STUBBED) called");
370 } 370 }
371 371
372 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { 372 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
373 IPC::ResponseBuilder rb{ctx, 3}; 373 IPC::ResponseBuilder rb{ctx, 3};
374 rb.Push(RESULT_SUCCESS); 374 rb.Push(RESULT_SUCCESS);
375 rb.Push(joy_hold_type); 375 rb.Push(joy_hold_type);
376 LOG_WARNING(Service_HID, "(STUBBED) called"); 376 NGLOG_WARNING(Service_HID, "(STUBBED) called");
377 } 377 }
378 378
379 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { 379 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
380 IPC::ResponseBuilder rb{ctx, 2}; 380 IPC::ResponseBuilder rb{ctx, 2};
381 rb.Push(RESULT_SUCCESS); 381 rb.Push(RESULT_SUCCESS);
382 LOG_WARNING(Service_HID, "(STUBBED) called"); 382 NGLOG_WARNING(Service_HID, "(STUBBED) called");
383 } 383 }
384 384
385 void SendVibrationValue(Kernel::HLERequestContext& ctx) { 385 void SendVibrationValue(Kernel::HLERequestContext& ctx) {
386 IPC::ResponseBuilder rb{ctx, 2}; 386 IPC::ResponseBuilder rb{ctx, 2};
387 rb.Push(RESULT_SUCCESS); 387 rb.Push(RESULT_SUCCESS);
388 LOG_WARNING(Service_HID, "(STUBBED) called"); 388 NGLOG_WARNING(Service_HID, "(STUBBED) called");
389 } 389 }
390 390
391 void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { 391 void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
392 IPC::ResponseBuilder rb{ctx, 2}; 392 IPC::ResponseBuilder rb{ctx, 2};
393 rb.Push(RESULT_SUCCESS); 393 rb.Push(RESULT_SUCCESS);
394 LOG_WARNING(Service_HID, "(STUBBED) called"); 394 NGLOG_WARNING(Service_HID, "(STUBBED) called");
395 } 395 }
396 396
397 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { 397 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
398 IPC::ResponseBuilder rb{ctx, 2}; 398 IPC::ResponseBuilder rb{ctx, 2};
399 rb.Push(RESULT_SUCCESS); 399 rb.Push(RESULT_SUCCESS);
400 LOG_WARNING(Service_HID, "(STUBBED) called"); 400 NGLOG_WARNING(Service_HID, "(STUBBED) called");
401 } 401 }
402 402
403 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { 403 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
404 IPC::ResponseBuilder rb{ctx, 2}; 404 IPC::ResponseBuilder rb{ctx, 2};
405 rb.Push(RESULT_SUCCESS); 405 rb.Push(RESULT_SUCCESS);
406 LOG_WARNING(Service_HID, "(STUBBED) called"); 406 NGLOG_WARNING(Service_HID, "(STUBBED) called");
407 } 407 }
408 408
409 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 409 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
410 IPC::ResponseBuilder rb{ctx, 4}; 410 IPC::ResponseBuilder rb{ctx, 4};
411 rb.Push(RESULT_SUCCESS); 411 rb.Push(RESULT_SUCCESS);
412 rb.Push<u64>(0); 412 rb.Push<u64>(0);
413 LOG_WARNING(Service_HID, "(STUBBED) called"); 413 NGLOG_WARNING(Service_HID, "(STUBBED) called");
414 } 414 }
415 415
416 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { 416 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
417 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 417 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
418 rb.Push(RESULT_SUCCESS); 418 rb.Push(RESULT_SUCCESS);
419 rb.PushIpcInterface<IActiveVibrationDeviceList>(); 419 rb.PushIpcInterface<IActiveVibrationDeviceList>();
420 LOG_DEBUG(Service_HID, "called"); 420 NGLOG_DEBUG(Service_HID, "called");
421 } 421 }
422 422
423 void SendVibrationValues(Kernel::HLERequestContext& ctx) { 423 void SendVibrationValues(Kernel::HLERequestContext& ctx) {
424 IPC::ResponseBuilder rb{ctx, 2}; 424 IPC::ResponseBuilder rb{ctx, 2};
425 rb.Push(RESULT_SUCCESS); 425 rb.Push(RESULT_SUCCESS);
426 LOG_WARNING(Service_HID, "(STUBBED) called"); 426 NGLOG_WARNING(Service_HID, "(STUBBED) called");
427 } 427 }
428}; 428};
429 429
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index b87172dff..46194643e 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -141,19 +141,19 @@ private:
141 if (header.IsTailLog()) { 141 if (header.IsTailLog()) {
142 switch (header.severity) { 142 switch (header.severity) {
143 case MessageHeader::Severity::Trace: 143 case MessageHeader::Severity::Trace:
144 LOG_TRACE(Debug_Emulated, "%s", log_stream.str().c_str()); 144 NGLOG_TRACE(Debug_Emulated, "{}", log_stream.str());
145 break; 145 break;
146 case MessageHeader::Severity::Info: 146 case MessageHeader::Severity::Info:
147 LOG_INFO(Debug_Emulated, "%s", log_stream.str().c_str()); 147 NGLOG_INFO(Debug_Emulated, "{}", log_stream.str());
148 break; 148 break;
149 case MessageHeader::Severity::Warning: 149 case MessageHeader::Severity::Warning:
150 LOG_WARNING(Debug_Emulated, "%s", log_stream.str().c_str()); 150 NGLOG_WARNING(Debug_Emulated, "{}", log_stream.str());
151 break; 151 break;
152 case MessageHeader::Severity::Error: 152 case MessageHeader::Severity::Error:
153 LOG_ERROR(Debug_Emulated, "%s", log_stream.str().c_str()); 153 NGLOG_ERROR(Debug_Emulated, "{}", log_stream.str());
154 break; 154 break;
155 case MessageHeader::Severity::Critical: 155 case MessageHeader::Severity::Critical:
156 LOG_CRITICAL(Debug_Emulated, "%s", log_stream.str().c_str()); 156 NGLOG_CRITICAL(Debug_Emulated, "{}", log_stream.str());
157 break; 157 break;
158 } 158 }
159 } 159 }
@@ -178,7 +178,7 @@ void LM::Initialize(Kernel::HLERequestContext& ctx) {
178 rb.Push(RESULT_SUCCESS); 178 rb.Push(RESULT_SUCCESS);
179 rb.PushIpcInterface<Logger>(); 179 rb.PushIpcInterface<Logger>();
180 180
181 LOG_DEBUG(Service_LM, "called"); 181 NGLOG_DEBUG(Service_LM, "called");
182} 182}
183 183
184LM::LM() : ServiceFramework("lm") { 184LM::LM() : ServiceFramework("lm") {
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index df1e7f8fe..eee92cfcd 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -62,24 +62,24 @@ public:
62 62
63private: 63private:
64 void GetRequestState(Kernel::HLERequestContext& ctx) { 64 void GetRequestState(Kernel::HLERequestContext& ctx) {
65 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 65 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
66 IPC::ResponseBuilder rb{ctx, 3}; 66 IPC::ResponseBuilder rb{ctx, 3};
67 rb.Push(RESULT_SUCCESS); 67 rb.Push(RESULT_SUCCESS);
68 rb.Push<u32>(0); 68 rb.Push<u32>(0);
69 } 69 }
70 void GetResult(Kernel::HLERequestContext& ctx) { 70 void GetResult(Kernel::HLERequestContext& ctx) {
71 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 71 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
72 IPC::ResponseBuilder rb{ctx, 2}; 72 IPC::ResponseBuilder rb{ctx, 2};
73 rb.Push(RESULT_SUCCESS); 73 rb.Push(RESULT_SUCCESS);
74 } 74 }
75 void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { 75 void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) {
76 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 76 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
77 IPC::ResponseBuilder rb{ctx, 2, 2}; 77 IPC::ResponseBuilder rb{ctx, 2, 2};
78 rb.Push(RESULT_SUCCESS); 78 rb.Push(RESULT_SUCCESS);
79 rb.PushCopyObjects(event1, event2); 79 rb.PushCopyObjects(event1, event2);
80 } 80 }
81 void Cancel(Kernel::HLERequestContext& ctx) { 81 void Cancel(Kernel::HLERequestContext& ctx) {
82 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 82 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
83 IPC::ResponseBuilder rb{ctx, 2}; 83 IPC::ResponseBuilder rb{ctx, 2};
84 rb.Push(RESULT_SUCCESS); 84 rb.Push(RESULT_SUCCESS);
85 } 85 }
@@ -105,7 +105,7 @@ public:
105 105
106private: 106private:
107 void GetClientId(Kernel::HLERequestContext& ctx) { 107 void GetClientId(Kernel::HLERequestContext& ctx) {
108 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 108 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
109 IPC::ResponseBuilder rb{ctx, 4}; 109 IPC::ResponseBuilder rb{ctx, 4};
110 rb.Push(RESULT_SUCCESS); 110 rb.Push(RESULT_SUCCESS);
111 rb.Push<u64>(0); 111 rb.Push<u64>(0);
@@ -116,7 +116,7 @@ private:
116 rb.Push(RESULT_SUCCESS); 116 rb.Push(RESULT_SUCCESS);
117 rb.PushIpcInterface<IScanRequest>(); 117 rb.PushIpcInterface<IScanRequest>();
118 118
119 LOG_DEBUG(Service_NIFM, "called"); 119 NGLOG_DEBUG(Service_NIFM, "called");
120 } 120 }
121 void CreateRequest(Kernel::HLERequestContext& ctx) { 121 void CreateRequest(Kernel::HLERequestContext& ctx) {
122 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 122 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -124,10 +124,10 @@ private:
124 rb.Push(RESULT_SUCCESS); 124 rb.Push(RESULT_SUCCESS);
125 rb.PushIpcInterface<IRequest>(); 125 rb.PushIpcInterface<IRequest>();
126 126
127 LOG_DEBUG(Service_NIFM, "called"); 127 NGLOG_DEBUG(Service_NIFM, "called");
128 } 128 }
129 void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) { 129 void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
130 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 130 NGLOG_WARNING(Service_NIFM, "(STUBBED) called");
131 IPC::ResponseBuilder rb{ctx, 2}; 131 IPC::ResponseBuilder rb{ctx, 2};
132 rb.Push(RESULT_SUCCESS); 132 rb.Push(RESULT_SUCCESS);
133 } 133 }
@@ -137,7 +137,7 @@ private:
137 rb.Push(RESULT_SUCCESS); 137 rb.Push(RESULT_SUCCESS);
138 rb.PushIpcInterface<INetworkProfile>(); 138 rb.PushIpcInterface<INetworkProfile>();
139 139
140 LOG_DEBUG(Service_NIFM, "called"); 140 NGLOG_DEBUG(Service_NIFM, "called");
141 } 141 }
142}; 142};
143 143
@@ -187,14 +187,14 @@ void Module::Interface::CreateGeneralServiceOld(Kernel::HLERequestContext& ctx)
187 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 187 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
188 rb.Push(RESULT_SUCCESS); 188 rb.Push(RESULT_SUCCESS);
189 rb.PushIpcInterface<IGeneralService>(); 189 rb.PushIpcInterface<IGeneralService>();
190 LOG_DEBUG(Service_NIFM, "called"); 190 NGLOG_DEBUG(Service_NIFM, "called");
191} 191}
192 192
193void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) { 193void Module::Interface::CreateGeneralService(Kernel::HLERequestContext& ctx) {
194 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 194 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
195 rb.Push(RESULT_SUCCESS); 195 rb.Push(RESULT_SUCCESS);
196 rb.PushIpcInterface<IGeneralService>(); 196 rb.PushIpcInterface<IGeneralService>();
197 LOG_DEBUG(Service_NIFM, "called"); 197 NGLOG_DEBUG(Service_NIFM, "called");
198} 198}
199 199
200Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 200Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index c416ad720..c2a647e89 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -52,7 +52,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
52 ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE); 52 ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
53 file.ReadBytes(shared_font->data(), shared_font->size()); 53 file.ReadBytes(shared_font->data(), shared_font->size());
54 } else { 54 } else {
55 LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str()); 55 NGLOG_WARNING(Service_NS, "Unable to load shared font: {}", filepath);
56 } 56 }
57} 57}
58 58
@@ -60,7 +60,7 @@ void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
60 IPC::RequestParser rp{ctx}; 60 IPC::RequestParser rp{ctx};
61 const u32 shared_font_type{rp.Pop<u32>()}; 61 const u32 shared_font_type{rp.Pop<u32>()};
62 62
63 LOG_DEBUG(Service_NS, "called, shared_font_type=%d", shared_font_type); 63 NGLOG_DEBUG(Service_NS, "called, shared_font_type={}", shared_font_type);
64 IPC::ResponseBuilder rb{ctx, 2}; 64 IPC::ResponseBuilder rb{ctx, 2};
65 rb.Push(RESULT_SUCCESS); 65 rb.Push(RESULT_SUCCESS);
66} 66}
@@ -69,7 +69,7 @@ void PL_U::GetLoadState(Kernel::HLERequestContext& ctx) {
69 IPC::RequestParser rp{ctx}; 69 IPC::RequestParser rp{ctx};
70 const u32 font_id{rp.Pop<u32>()}; 70 const u32 font_id{rp.Pop<u32>()};
71 71
72 LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); 72 NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
73 IPC::ResponseBuilder rb{ctx, 3}; 73 IPC::ResponseBuilder rb{ctx, 3};
74 rb.Push(RESULT_SUCCESS); 74 rb.Push(RESULT_SUCCESS);
75 rb.Push<u32>(static_cast<u32>(LoadState::Done)); 75 rb.Push<u32>(static_cast<u32>(LoadState::Done));
@@ -79,7 +79,7 @@ void PL_U::GetSize(Kernel::HLERequestContext& ctx) {
79 IPC::RequestParser rp{ctx}; 79 IPC::RequestParser rp{ctx};
80 const u32 font_id{rp.Pop<u32>()}; 80 const u32 font_id{rp.Pop<u32>()};
81 81
82 LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); 82 NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
83 IPC::ResponseBuilder rb{ctx, 3}; 83 IPC::ResponseBuilder rb{ctx, 3};
84 rb.Push(RESULT_SUCCESS); 84 rb.Push(RESULT_SUCCESS);
85 rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size); 85 rb.Push<u32>(SHARED_FONT_REGIONS[font_id].size);
@@ -89,7 +89,7 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
89 IPC::RequestParser rp{ctx}; 89 IPC::RequestParser rp{ctx};
90 const u32 font_id{rp.Pop<u32>()}; 90 const u32 font_id{rp.Pop<u32>()};
91 91
92 LOG_DEBUG(Service_NS, "called, font_id=%d", font_id); 92 NGLOG_DEBUG(Service_NS, "called, font_id={}", font_id);
93 IPC::ResponseBuilder rb{ctx, 3}; 93 IPC::ResponseBuilder rb{ctx, 3};
94 rb.Push(RESULT_SUCCESS); 94 rb.Push(RESULT_SUCCESS);
95 rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset); 95 rb.Push<u32>(SHARED_FONT_REGIONS[font_id].offset);
@@ -110,7 +110,7 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
110 Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE, 110 Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
111 "PL_U:shared_font_mem"); 111 "PL_U:shared_font_mem");
112 112
113 LOG_DEBUG(Service_NS, "called"); 113 NGLOG_DEBUG(Service_NS, "called");
114 IPC::ResponseBuilder rb{ctx, 2, 1}; 114 IPC::ResponseBuilder rb{ctx, 2, 1};
115 rb.Push(RESULT_SUCCESS); 115 rb.Push(RESULT_SUCCESS);
116 rb.PushCopyObjects(shared_font_mem); 116 rb.PushCopyObjects(shared_font_mem);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 61f22b1a5..103e66d0c 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -13,16 +13,16 @@
13namespace Service::Nvidia::Devices { 13namespace Service::Nvidia::Devices {
14 14
15u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 15u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
16 UNIMPLEMENTED(); 16 UNIMPLEMENTED_MSG("Unimplemented ioctl");
17 return 0; 17 return 0;
18} 18}
19 19
20void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, 20void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
21 u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) { 21 u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) {
22 VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); 22 VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
23 LOG_WARNING(Service, 23 NGLOG_WARNING(Service,
24 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr, 24 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
25 offset, width, height, stride, format); 25 addr, offset, width, height, stride, format);
26 26
27 using PixelFormat = Tegra::FramebufferConfig::PixelFormat; 27 using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
28 const Tegra::FramebufferConfig framebuffer{ 28 const Tegra::FramebufferConfig framebuffer{
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 71e844959..36d7f837b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -12,8 +12,8 @@
12namespace Service::Nvidia::Devices { 12namespace Service::Nvidia::Devices {
13 13
14u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 14u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
15 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 15 NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
16 command.raw, input.size(), output.size()); 16 command.raw, input.size(), output.size());
17 17
18 switch (static_cast<IoctlCommand>(command.raw)) { 18 switch (static_cast<IoctlCommand>(command.raw)) {
19 case IoctlCommand::IocInitalizeExCommand: 19 case IoctlCommand::IocInitalizeExCommand:
@@ -27,13 +27,18 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
27 case IoctlCommand::IocGetVaRegionsCommand: 27 case IoctlCommand::IocGetVaRegionsCommand:
28 return GetVARegions(input, output); 28 return GetVARegions(input, output);
29 } 29 }
30
31 if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand)
32 return Remap(input, output);
33
34 UNIMPLEMENTED_MSG("Unimplemented ioctl command");
30 return 0; 35 return 0;
31} 36}
32 37
33u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) { 38u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output) {
34 IoctlInitalizeEx params{}; 39 IoctlInitalizeEx params{};
35 std::memcpy(&params, input.data(), input.size()); 40 std::memcpy(&params, input.data(), input.size());
36 LOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size=0x%x", params.big_page_size); 41 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, big_page_size={:#X}", params.big_page_size);
37 std::memcpy(output.data(), &params, output.size()); 42 std::memcpy(output.data(), &params, output.size());
38 return 0; 43 return 0;
39} 44}
@@ -41,8 +46,8 @@ u32 nvhost_as_gpu::InitalizeEx(const std::vector<u8>& input, std::vector<u8>& ou
41u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) { 46u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output) {
42 IoctlAllocSpace params{}; 47 IoctlAllocSpace params{};
43 std::memcpy(&params, input.data(), input.size()); 48 std::memcpy(&params, input.data(), input.size());
44 LOG_DEBUG(Service_NVDRV, "called, pages=%x, page_size=%x, flags=%x", params.pages, 49 NGLOG_DEBUG(Service_NVDRV, "called, pages={:X}, page_size={:X}, flags={:X}", params.pages,
45 params.page_size, params.flags); 50 params.page_size, params.flags);
46 51
47 auto& gpu = Core::System::GetInstance().GPU(); 52 auto& gpu = Core::System::GetInstance().GPU();
48 const u64 size{static_cast<u64>(params.pages) * static_cast<u64>(params.page_size)}; 53 const u64 size{static_cast<u64>(params.pages) * static_cast<u64>(params.page_size)};
@@ -56,15 +61,45 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>&
56 return 0; 61 return 0;
57} 62}
58 63
64u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) {
65 size_t num_entries = input.size() / sizeof(IoctlRemapEntry);
66
67 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, num_entries=0x{:X}", num_entries);
68
69 std::vector<IoctlRemapEntry> entries(num_entries);
70 std::memcpy(entries.data(), input.data(), input.size());
71
72 auto& gpu = Core::System::GetInstance().GPU();
73
74 for (const auto& entry : entries) {
75 NGLOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}",
76 entry.offset, entry.nvmap_handle, entry.pages);
77 Tegra::GPUVAddr offset = static_cast<Tegra::GPUVAddr>(entry.offset) << 0x10;
78
79 auto object = nvmap_dev->GetObject(entry.nvmap_handle);
80 ASSERT(object);
81
82 ASSERT(object->status == nvmap::Object::Status::Allocated);
83
84 u64 size = static_cast<u64>(entry.pages) << 0x10;
85 ASSERT(size <= object->size);
86
87 Tegra::GPUVAddr returned = gpu.memory_manager->MapBufferEx(object->addr, offset, size);
88 ASSERT(returned == offset);
89 }
90 std::memcpy(output.data(), entries.data(), output.size());
91 return 0;
92}
93
59u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) { 94u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output) {
60 IoctlMapBufferEx params{}; 95 IoctlMapBufferEx params{};
61 std::memcpy(&params, input.data(), input.size()); 96 std::memcpy(&params, input.data(), input.size());
62 97
63 LOG_DEBUG(Service_NVDRV, 98 NGLOG_DEBUG(Service_NVDRV,
64 "called, flags=%x, nvmap_handle=%x, buffer_offset=%" PRIu64 ", mapping_size=%" PRIu64 99 "called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
65 ", offset=%" PRIu64, 100 ", offset={}",
66 params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size, 101 params.flags, params.nvmap_handle, params.buffer_offset, params.mapping_size,
67 params.offset); 102 params.offset);
68 103
69 if (!params.nvmap_handle) { 104 if (!params.nvmap_handle) {
70 return 0; 105 return 0;
@@ -73,6 +108,16 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
73 auto object = nvmap_dev->GetObject(params.nvmap_handle); 108 auto object = nvmap_dev->GetObject(params.nvmap_handle);
74 ASSERT(object); 109 ASSERT(object);
75 110
111 // We can only map objects that have already been assigned a CPU address.
112 ASSERT(object->status == nvmap::Object::Status::Allocated);
113
114 ASSERT(params.buffer_offset == 0);
115
116 // The real nvservices doesn't make a distinction between handles and ids, and
117 // object can only have one handle and it will be the same as its id. Assert that this is the
118 // case to prevent unexpected behavior.
119 ASSERT(object->id == params.nvmap_handle);
120
76 auto& gpu = Core::System::GetInstance().GPU(); 121 auto& gpu = Core::System::GetInstance().GPU();
77 122
78 if (params.flags & 1) { 123 if (params.flags & 1) {
@@ -88,7 +133,7 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
88u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) { 133u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& output) {
89 IoctlBindChannel params{}; 134 IoctlBindChannel params{};
90 std::memcpy(&params, input.data(), input.size()); 135 std::memcpy(&params, input.data(), input.size());
91 LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.fd); 136 NGLOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
92 channel = params.fd; 137 channel = params.fd;
93 std::memcpy(output.data(), &params, output.size()); 138 std::memcpy(output.data(), &params, output.size());
94 return 0; 139 return 0;
@@ -97,8 +142,8 @@ u32 nvhost_as_gpu::BindChannel(const std::vector<u8>& input, std::vector<u8>& ou
97u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) { 142u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& output) {
98 IoctlGetVaRegions params{}; 143 IoctlGetVaRegions params{};
99 std::memcpy(&params, input.data(), input.size()); 144 std::memcpy(&params, input.data(), input.size());
100 LOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr=%" PRIu64 ", buf_size=%x", 145 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, buf_addr={:X}, buf_size={:X}", params.buf_addr,
101 params.buf_addr, params.buf_size); 146 params.buf_size);
102 147
103 params.buf_size = 0x30; 148 params.buf_size = 0x30;
104 params.regions[0].offset = 0x04000000; 149 params.regions[0].offset = 0x04000000;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index d86c3ebd9..f2dd0c3b3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -26,6 +26,7 @@ private:
26 enum class IoctlCommand : u32_le { 26 enum class IoctlCommand : u32_le {
27 IocInitalizeExCommand = 0x40284109, 27 IocInitalizeExCommand = 0x40284109,
28 IocAllocateSpaceCommand = 0xC0184102, 28 IocAllocateSpaceCommand = 0xC0184102,
29 IocRemapCommand = 0x00000014,
29 IocMapBufferExCommand = 0xC0284106, 30 IocMapBufferExCommand = 0xC0284106,
30 IocBindChannelCommand = 0x40044101, 31 IocBindChannelCommand = 0x40044101,
31 IocGetVaRegionsCommand = 0xC0404108, 32 IocGetVaRegionsCommand = 0xC0404108,
@@ -54,6 +55,16 @@ private:
54 }; 55 };
55 static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); 56 static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size");
56 57
58 struct IoctlRemapEntry {
59 u16_le flags;
60 u16_le kind;
61 u32_le nvmap_handle;
62 INSERT_PADDING_WORDS(1);
63 u32_le offset;
64 u32_le pages;
65 };
66 static_assert(sizeof(IoctlRemapEntry) == 20, "IoctlRemapEntry is incorrect size");
67
57 struct IoctlMapBufferEx { 68 struct IoctlMapBufferEx {
58 u32_le flags; // bit0: fixed_offset, bit2: cacheable 69 u32_le flags; // bit0: fixed_offset, bit2: cacheable
59 u32_le kind; // -1 is default 70 u32_le kind; // -1 is default
@@ -91,6 +102,7 @@ private:
91 102
92 u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output); 103 u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output);
93 u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output); 104 u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
105 u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
94 u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); 106 u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
95 u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); 107 u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
96 u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); 108 u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 660a0f665..46f0b6862 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -9,8 +9,8 @@
9namespace Service::Nvidia::Devices { 9namespace Service::Nvidia::Devices {
10 10
11u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 11u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
12 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 12 NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
13 command.raw, input.size(), output.size()); 13 command.raw, input.size(), output.size());
14 14
15 switch (static_cast<IoctlCommand>(command.raw)) { 15 switch (static_cast<IoctlCommand>(command.raw)) {
16 case IoctlCommand::IocGetConfigCommand: 16 case IoctlCommand::IocGetConfigCommand:
@@ -18,15 +18,15 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
18 case IoctlCommand::IocCtrlEventWaitCommand: 18 case IoctlCommand::IocCtrlEventWaitCommand:
19 return IocCtrlEventWait(input, output); 19 return IocCtrlEventWait(input, output);
20 } 20 }
21 UNIMPLEMENTED(); 21 UNIMPLEMENTED_MSG("Unimplemented ioctl");
22 return 0; 22 return 0;
23} 23}
24 24
25u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) { 25u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output) {
26 IocGetConfigParams params{}; 26 IocGetConfigParams params{};
27 std::memcpy(&params, input.data(), sizeof(params)); 27 std::memcpy(&params, input.data(), sizeof(params));
28 LOG_DEBUG(Service_NVDRV, "called, setting=%s!%s", params.domain_str.data(), 28 NGLOG_DEBUG(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
29 params.param_str.data()); 29 params.param_str.data());
30 30
31 if (!strcmp(params.domain_str.data(), "nv")) { 31 if (!strcmp(params.domain_str.data(), "nv")) {
32 if (!strcmp(params.param_str.data(), "NV_MEMORY_PROFILER")) { 32 if (!strcmp(params.param_str.data(), "NV_MEMORY_PROFILER")) {
@@ -48,8 +48,8 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
48u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) { 48u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
49 IocCtrlEventWaitParams params{}; 49 IocCtrlEventWaitParams params{};
50 std::memcpy(&params, input.data(), sizeof(params)); 50 std::memcpy(&params, input.data(), sizeof(params));
51 LOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id=%u threshold=%u timeout=%d", 51 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id={} threshold={} timeout={}",
52 params.syncpt_id, params.threshold, params.timeout); 52 params.syncpt_id, params.threshold, params.timeout);
53 53
54 // TODO(Subv): Implement actual syncpt waiting. 54 // TODO(Subv): Implement actual syncpt waiting.
55 params.value = 0; 55 params.value = 0;
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 5008d7cbf..3c78ecaea 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -10,8 +10,8 @@
10namespace Service::Nvidia::Devices { 10namespace Service::Nvidia::Devices {
11 11
12u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 12u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
13 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 13 NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
14 command.raw, input.size(), output.size()); 14 command.raw, input.size(), output.size());
15 15
16 switch (static_cast<IoctlCommand>(command.raw)) { 16 switch (static_cast<IoctlCommand>(command.raw)) {
17 case IoctlCommand::IocGetCharacteristicsCommand: 17 case IoctlCommand::IocGetCharacteristicsCommand:
@@ -25,12 +25,12 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
25 case IoctlCommand::IocZcullGetInfo: 25 case IoctlCommand::IocZcullGetInfo:
26 return ZCullGetInfo(input, output); 26 return ZCullGetInfo(input, output);
27 } 27 }
28 UNIMPLEMENTED(); 28 UNIMPLEMENTED_MSG("Unimplemented ioctl");
29 return 0; 29 return 0;
30} 30}
31 31
32u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) { 32u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output) {
33 LOG_DEBUG(Service_NVDRV, "called"); 33 NGLOG_DEBUG(Service_NVDRV, "called");
34 IoctlCharacteristics params{}; 34 IoctlCharacteristics params{};
35 std::memcpy(&params, input.data(), input.size()); 35 std::memcpy(&params, input.data(), input.size());
36 params.gc.arch = 0x120; 36 params.gc.arch = 0x120;
@@ -77,15 +77,15 @@ u32 nvhost_ctrl_gpu::GetCharacteristics(const std::vector<u8>& input, std::vecto
77u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) { 77u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output) {
78 IoctlGpuGetTpcMasksArgs params{}; 78 IoctlGpuGetTpcMasksArgs params{};
79 std::memcpy(&params, input.data(), input.size()); 79 std::memcpy(&params, input.data(), input.size());
80 LOG_WARNING(Service_NVDRV, "(STUBBED) called, mask=0x%x, mask_buf_addr=0x%" PRIx64, 80 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, mask={:#X}, mask_buf_addr={:#X}",
81 params.mask_buf_size, params.mask_buf_addr); 81 params.mask_buf_size, params.mask_buf_addr);
82 params.unk = 0xcafe; // TODO(ogniK): Needs to be non 0, what does this actually do? 82 params.unk = 0xcafe; // TODO(ogniK): Needs to be non 0, what does this actually do?
83 std::memcpy(output.data(), &params, sizeof(params)); 83 std::memcpy(output.data(), &params, sizeof(params));
84 return 0; 84 return 0;
85} 85}
86 86
87u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) { 87u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
88 LOG_DEBUG(Service_NVDRV, "called"); 88 NGLOG_DEBUG(Service_NVDRV, "called");
89 IoctlActiveSlotMask params{}; 89 IoctlActiveSlotMask params{};
90 std::memcpy(&params, input.data(), input.size()); 90 std::memcpy(&params, input.data(), input.size());
91 params.slot = 0x07; 91 params.slot = 0x07;
@@ -95,7 +95,7 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector
95} 95}
96 96
97u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) { 97u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) {
98 LOG_DEBUG(Service_NVDRV, "called"); 98 NGLOG_DEBUG(Service_NVDRV, "called");
99 IoctlZcullGetCtxSize params{}; 99 IoctlZcullGetCtxSize params{};
100 std::memcpy(&params, input.data(), input.size()); 100 std::memcpy(&params, input.data(), input.size());
101 params.size = 0x1; 101 params.size = 0x1;
@@ -104,7 +104,7 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u
104} 104}
105 105
106u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) { 106u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) {
107 LOG_DEBUG(Service_NVDRV, "called"); 107 NGLOG_DEBUG(Service_NVDRV, "called");
108 IoctlNvgpuGpuZcullGetInfoArgs params{}; 108 IoctlNvgpuGpuZcullGetInfoArgs params{};
109 std::memcpy(&params, input.data(), input.size()); 109 std::memcpy(&params, input.data(), input.size());
110 params.width_align_pixels = 0x20; 110 params.width_align_pixels = 0x20;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index a16e90457..70625211e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -12,8 +12,8 @@
12namespace Service::Nvidia::Devices { 12namespace Service::Nvidia::Devices {
13 13
14u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 14u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
15 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 15 NGLOG_DEBUG(Service_NVDRV, "called, command={:#010X}, input_size={:#X}, output_size={:#X}",
16 command.raw, input.size(), output.size()); 16 command.raw, input.size(), output.size());
17 17
18 switch (static_cast<IoctlCommand>(command.raw)) { 18 switch (static_cast<IoctlCommand>(command.raw)) {
19 case IoctlCommand::IocSetNVMAPfdCommand: 19 case IoctlCommand::IocSetNVMAPfdCommand:
@@ -40,21 +40,21 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
40 } 40 }
41 } 41 }
42 42
43 UNIMPLEMENTED(); 43 UNIMPLEMENTED_MSG("Unimplemented ioctl");
44 return 0; 44 return 0;
45}; 45};
46 46
47u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) { 47u32 nvhost_gpu::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
48 IoctlSetNvmapFD params{}; 48 IoctlSetNvmapFD params{};
49 std::memcpy(&params, input.data(), input.size()); 49 std::memcpy(&params, input.data(), input.size());
50 LOG_DEBUG(Service_NVDRV, "called, fd=%x", params.nvmap_fd); 50 NGLOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
51 nvmap_fd = params.nvmap_fd; 51 nvmap_fd = params.nvmap_fd;
52 std::memcpy(output.data(), &params, output.size()); 52 std::memcpy(output.data(), &params, output.size());
53 return 0; 53 return 0;
54} 54}
55 55
56u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) { 56u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
57 LOG_DEBUG(Service_NVDRV, "called"); 57 NGLOG_DEBUG(Service_NVDRV, "called");
58 IoctlClientData params{}; 58 IoctlClientData params{};
59 std::memcpy(&params, input.data(), input.size()); 59 std::memcpy(&params, input.data(), input.size());
60 user_data = params.data; 60 user_data = params.data;
@@ -63,7 +63,7 @@ u32 nvhost_gpu::SetClientData(const std::vector<u8>& input, std::vector<u8>& out
63} 63}
64 64
65u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) { 65u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& output) {
66 LOG_DEBUG(Service_NVDRV, "called"); 66 NGLOG_DEBUG(Service_NVDRV, "called");
67 IoctlClientData params{}; 67 IoctlClientData params{};
68 std::memcpy(&params, input.data(), input.size()); 68 std::memcpy(&params, input.data(), input.size());
69 params.data = user_data; 69 params.data = user_data;
@@ -73,8 +73,8 @@ u32 nvhost_gpu::GetClientData(const std::vector<u8>& input, std::vector<u8>& out
73 73
74u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) { 74u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output) {
75 std::memcpy(&zcull_params, input.data(), input.size()); 75 std::memcpy(&zcull_params, input.data(), input.size());
76 LOG_DEBUG(Service_NVDRV, "called, gpu_va=%" PRIx64 ", mode=%x", zcull_params.gpu_va, 76 NGLOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
77 zcull_params.mode); 77 zcull_params.mode);
78 std::memcpy(output.data(), &zcull_params, output.size()); 78 std::memcpy(output.data(), &zcull_params, output.size());
79 return 0; 79 return 0;
80} 80}
@@ -82,15 +82,15 @@ u32 nvhost_gpu::ZCullBind(const std::vector<u8>& input, std::vector<u8>& output)
82u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) { 82u32 nvhost_gpu::SetErrorNotifier(const std::vector<u8>& input, std::vector<u8>& output) {
83 IoctlSetErrorNotifier params{}; 83 IoctlSetErrorNotifier params{};
84 std::memcpy(&params, input.data(), input.size()); 84 std::memcpy(&params, input.data(), input.size());
85 LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset=%" PRIx64 ", size=%" PRIx64 ", mem=%x", 85 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}",
86 params.offset, params.size, params.mem); 86 params.offset, params.size, params.mem);
87 std::memcpy(output.data(), &params, output.size()); 87 std::memcpy(output.data(), &params, output.size());
88 return 0; 88 return 0;
89} 89}
90 90
91u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) { 91u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>& output) {
92 std::memcpy(&channel_priority, input.data(), input.size()); 92 std::memcpy(&channel_priority, input.data(), input.size());
93 LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority=%x", channel_priority); 93 NGLOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
94 std::memcpy(output.data(), &channel_priority, output.size()); 94 std::memcpy(output.data(), &channel_priority, output.size());
95 return 0; 95 return 0;
96} 96}
@@ -98,10 +98,11 @@ u32 nvhost_gpu::SetChannelPriority(const std::vector<u8>& input, std::vector<u8>
98u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) { 98u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output) {
99 IoctlAllocGpfifoEx2 params{}; 99 IoctlAllocGpfifoEx2 params{};
100 std::memcpy(&params, input.data(), input.size()); 100 std::memcpy(&params, input.data(), input.size());
101 LOG_WARNING(Service_NVDRV, 101 NGLOG_WARNING(Service_NVDRV,
102 "(STUBBED) called, num_entries=%x, flags=%x, unk0=%x, unk1=%x, unk2=%x, unk3=%x", 102 "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, "
103 params.num_entries, params.flags, params.unk0, params.unk1, params.unk2, 103 "unk1={:X}, unk2={:X}, unk3={:X}",
104 params.unk3); 104 params.num_entries, params.flags, params.unk0, params.unk1, params.unk2,
105 params.unk3);
105 params.fence_out.id = 0; 106 params.fence_out.id = 0;
106 params.fence_out.value = 0; 107 params.fence_out.value = 0;
107 std::memcpy(output.data(), &params, output.size()); 108 std::memcpy(output.data(), &params, output.size());
@@ -111,8 +112,8 @@ u32 nvhost_gpu::AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& ou
111u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) { 112u32 nvhost_gpu::AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output) {
112 IoctlAllocObjCtx params{}; 113 IoctlAllocObjCtx params{};
113 std::memcpy(&params, input.data(), input.size()); 114 std::memcpy(&params, input.data(), input.size());
114 LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num=%x, flags=%x", params.class_num, 115 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
115 params.flags); 116 params.flags);
116 params.obj_id = 0x0; 117 params.obj_id = 0x0;
117 std::memcpy(output.data(), &params, output.size()); 118 std::memcpy(output.data(), &params, output.size());
118 return 0; 119 return 0;
@@ -123,8 +124,8 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
123 UNIMPLEMENTED(); 124 UNIMPLEMENTED();
124 IoctlSubmitGpfifo params{}; 125 IoctlSubmitGpfifo params{};
125 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 126 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
126 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo=%" PRIx64 ", num_entries=%x, flags=%x", 127 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
127 params.gpfifo, params.num_entries, params.flags); 128 params.gpfifo, params.num_entries, params.flags);
128 129
129 auto entries = std::vector<IoctlGpfifoEntry>(); 130 auto entries = std::vector<IoctlGpfifoEntry>();
130 entries.resize(params.num_entries); 131 entries.resize(params.num_entries);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 4bb1f57f6..11df8849d 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -32,7 +32,7 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
32 return IocParam(input, output); 32 return IocParam(input, output);
33 } 33 }
34 34
35 UNIMPLEMENTED(); 35 UNIMPLEMENTED_MSG("Unimplemented ioctl");
36 return 0; 36 return 0;
37} 37}
38 38
@@ -49,7 +49,7 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
49 u32 handle = next_handle++; 49 u32 handle = next_handle++;
50 handles[handle] = std::move(object); 50 handles[handle] = std::move(object);
51 51
52 LOG_DEBUG(Service_NVDRV, "size=0x%08X", params.size); 52 NGLOG_DEBUG(Service_NVDRV, "size={:#010X}", params.size);
53 53
54 params.handle = handle; 54 params.handle = handle;
55 55
@@ -70,7 +70,7 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
70 object->addr = params.addr; 70 object->addr = params.addr;
71 object->status = Object::Status::Allocated; 71 object->status = Object::Status::Allocated;
72 72
73 LOG_DEBUG(Service_NVDRV, "called, addr=0x%" PRIx64, params.addr); 73 NGLOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr);
74 74
75 std::memcpy(output.data(), &params, sizeof(params)); 75 std::memcpy(output.data(), &params, sizeof(params));
76 return 0; 76 return 0;
@@ -80,7 +80,7 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) {
80 IocGetIdParams params; 80 IocGetIdParams params;
81 std::memcpy(&params, input.data(), sizeof(params)); 81 std::memcpy(&params, input.data(), sizeof(params));
82 82
83 LOG_WARNING(Service_NVDRV, "called"); 83 NGLOG_WARNING(Service_NVDRV, "called");
84 84
85 auto object = GetObject(params.handle); 85 auto object = GetObject(params.handle);
86 ASSERT(object); 86 ASSERT(object);
@@ -95,7 +95,7 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
95 IocFromIdParams params; 95 IocFromIdParams params;
96 std::memcpy(&params, input.data(), sizeof(params)); 96 std::memcpy(&params, input.data(), sizeof(params));
97 97
98 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 98 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
99 99
100 auto itr = std::find_if(handles.begin(), handles.end(), 100 auto itr = std::find_if(handles.begin(), handles.end(),
101 [&](const auto& entry) { return entry.second->id == params.id; }); 101 [&](const auto& entry) { return entry.second->id == params.id; });
@@ -114,7 +114,7 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
114 IocParamParams params; 114 IocParamParams params;
115 std::memcpy(&params, input.data(), sizeof(params)); 115 std::memcpy(&params, input.data(), sizeof(params));
116 116
117 LOG_WARNING(Service_NVDRV, "(STUBBED) called type=%u", params.type); 117 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.type);
118 118
119 auto object = GetObject(params.handle); 119 auto object = GetObject(params.handle);
120 ASSERT(object); 120 ASSERT(object);
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index d0d64a840..38b3a9a84 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -12,7 +12,7 @@
12namespace Service::Nvidia { 12namespace Service::Nvidia {
13 13
14void NVDRV::Open(Kernel::HLERequestContext& ctx) { 14void NVDRV::Open(Kernel::HLERequestContext& ctx) {
15 LOG_DEBUG(Service_NVDRV, "called"); 15 NGLOG_DEBUG(Service_NVDRV, "called");
16 16
17 const auto& buffer = ctx.ReadBuffer(); 17 const auto& buffer = ctx.ReadBuffer();
18 std::string device_name(buffer.begin(), buffer.end()); 18 std::string device_name(buffer.begin(), buffer.end());
@@ -25,7 +25,7 @@ void NVDRV::Open(Kernel::HLERequestContext& ctx) {
25} 25}
26 26
27void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { 27void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
28 LOG_DEBUG(Service_NVDRV, "called"); 28 NGLOG_DEBUG(Service_NVDRV, "called");
29 29
30 IPC::RequestParser rp{ctx}; 30 IPC::RequestParser rp{ctx};
31 u32 fd = rp.Pop<u32>(); 31 u32 fd = rp.Pop<u32>();
@@ -41,7 +41,7 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
41} 41}
42 42
43void NVDRV::Close(Kernel::HLERequestContext& ctx) { 43void NVDRV::Close(Kernel::HLERequestContext& ctx) {
44 LOG_DEBUG(Service_NVDRV, "called"); 44 NGLOG_DEBUG(Service_NVDRV, "called");
45 45
46 IPC::RequestParser rp{ctx}; 46 IPC::RequestParser rp{ctx};
47 u32 fd = rp.Pop<u32>(); 47 u32 fd = rp.Pop<u32>();
@@ -53,7 +53,7 @@ void NVDRV::Close(Kernel::HLERequestContext& ctx) {
53} 53}
54 54
55void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { 55void NVDRV::Initialize(Kernel::HLERequestContext& ctx) {
56 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 56 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
57 IPC::ResponseBuilder rb{ctx, 3}; 57 IPC::ResponseBuilder rb{ctx, 3};
58 rb.Push(RESULT_SUCCESS); 58 rb.Push(RESULT_SUCCESS);
59 rb.Push<u32>(0); 59 rb.Push<u32>(0);
@@ -63,7 +63,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {
63 IPC::RequestParser rp{ctx}; 63 IPC::RequestParser rp{ctx};
64 u32 fd = rp.Pop<u32>(); 64 u32 fd = rp.Pop<u32>();
65 u32 event_id = rp.Pop<u32>(); 65 u32 event_id = rp.Pop<u32>();
66 LOG_WARNING(Service_NVDRV, "(STUBBED) called, fd=%x, event_id=%x", fd, event_id); 66 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, fd={:X}, event_id={:X}", fd, event_id);
67 67
68 IPC::ResponseBuilder rb{ctx, 3, 1}; 68 IPC::ResponseBuilder rb{ctx, 3, 1};
69 rb.Push(RESULT_SUCCESS); 69 rb.Push(RESULT_SUCCESS);
@@ -75,14 +75,14 @@ void NVDRV::SetClientPID(Kernel::HLERequestContext& ctx) {
75 IPC::RequestParser rp{ctx}; 75 IPC::RequestParser rp{ctx};
76 pid = rp.Pop<u64>(); 76 pid = rp.Pop<u64>();
77 77
78 LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid=0x%" PRIx64, pid); 78 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#X}", pid);
79 IPC::ResponseBuilder rb{ctx, 3}; 79 IPC::ResponseBuilder rb{ctx, 3};
80 rb.Push(RESULT_SUCCESS); 80 rb.Push(RESULT_SUCCESS);
81 rb.Push<u32>(0); 81 rb.Push<u32>(0);
82} 82}
83 83
84void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) { 84void NVDRV::FinishInitialize(Kernel::HLERequestContext& ctx) {
85 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 85 NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
86 IPC::ResponseBuilder rb{ctx, 2}; 86 IPC::ResponseBuilder rb{ctx, 2};
87 rb.Push(RESULT_SUCCESS); 87 rb.Push(RESULT_SUCCESS);
88} 88}
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 03a4fed59..49e88b394 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -9,7 +9,8 @@
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/hle/service/nvflinger/buffer_queue.h" 10#include "core/hle/service/nvflinger/buffer_queue.h"
11 11
12namespace Service::NVFlinger { 12namespace Service {
13namespace NVFlinger {
13 14
14BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { 15BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
15 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); 16 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
@@ -22,7 +23,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
22 buffer.igbp_buffer = igbp_buffer; 23 buffer.igbp_buffer = igbp_buffer;
23 buffer.status = Buffer::Status::Free; 24 buffer.status = Buffer::Status::Free;
24 25
25 LOG_WARNING(Service, "Adding graphics buffer %u", slot); 26 NGLOG_WARNING(Service, "Adding graphics buffer {}", slot);
26 27
27 queue.emplace_back(buffer); 28 queue.emplace_back(buffer);
28 29
@@ -93,7 +94,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
93} 94}
94 95
95u32 BufferQueue::Query(QueryType type) { 96u32 BufferQueue::Query(QueryType type) {
96 LOG_WARNING(Service, "(STUBBED) called type=%u", static_cast<u32>(type)); 97 NGLOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
97 switch (type) { 98 switch (type) {
98 case QueryType::NativeWindowFormat: 99 case QueryType::NativeWindowFormat:
99 // TODO(Subv): Use an enum for this 100 // TODO(Subv): Use an enum for this
@@ -110,4 +111,5 @@ void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_eve
110 buffer_wait_event = std::move(wait_event); 111 buffer_wait_event = std::move(wait_event);
111} 112}
112 113
113} // namespace Service::NVFlinger 114} // namespace NVFlinger
115} // namespace Service
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 95adc4706..1de5767cb 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -13,7 +13,8 @@ namespace CoreTiming {
13struct EventType; 13struct EventType;
14} 14}
15 15
16namespace Service::NVFlinger { 16namespace Service {
17namespace NVFlinger {
17 18
18struct IGBPBuffer { 19struct IGBPBuffer {
19 u32_le magic; 20 u32_le magic;
@@ -97,4 +98,5 @@ private:
97 Kernel::SharedPtr<Kernel::Event> buffer_wait_event; 98 Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
98}; 99};
99 100
100} // namespace Service::NVFlinger 101} // namespace NVFlinger
102} // namespace Service
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index a99ebc8e6..3481e48d0 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -48,7 +48,7 @@ NVFlinger::~NVFlinger() {
48} 48}
49 49
50u64 NVFlinger::OpenDisplay(const std::string& name) { 50u64 NVFlinger::OpenDisplay(const std::string& name) {
51 LOG_WARNING(Service, "Opening display %s", name.c_str()); 51 NGLOG_WARNING(Service, "Opening display {}", name);
52 52
53 // TODO(Subv): Currently we only support the Default display. 53 // TODO(Subv): Currently we only support the Default display.
54 ASSERT(name == "Default"); 54 ASSERT(name == "Default");
diff --git a/src/core/hle/service/pctl/pctl_a.cpp b/src/core/hle/service/pctl/module.cpp
index 9fb4628ad..dd20d5ae7 100644
--- a/src/core/hle/service/pctl/pctl_a.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -4,7 +4,8 @@
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/pctl/pctl_a.h" 7#include "core/hle/service/pctl/module.h"
8#include "core/hle/service/pctl/pctl.h"
8 9
9namespace Service::PCTL { 10namespace Service::PCTL {
10 11
@@ -12,7 +13,7 @@ class IParentalControlService final : public ServiceFramework<IParentalControlSe
12public: 13public:
13 IParentalControlService() : ServiceFramework("IParentalControlService") { 14 IParentalControlService() : ServiceFramework("IParentalControlService") {
14 static const FunctionInfo functions[] = { 15 static const FunctionInfo functions[] = {
15 {1, nullptr, "Initialize"}, 16 {1, &IParentalControlService::Initialize, "Initialize"},
16 {1001, nullptr, "CheckFreeCommunicationPermission"}, 17 {1001, nullptr, "CheckFreeCommunicationPermission"},
17 {1002, nullptr, "ConfirmLaunchApplicationPermission"}, 18 {1002, nullptr, "ConfirmLaunchApplicationPermission"},
18 {1003, nullptr, "ConfirmResumeApplicationPermission"}, 19 {1003, nullptr, "ConfirmResumeApplicationPermission"},
@@ -108,20 +109,38 @@ public:
108 }; 109 };
109 RegisterHandlers(functions); 110 RegisterHandlers(functions);
110 } 111 }
112
113private:
114 void Initialize(Kernel::HLERequestContext& ctx) {
115 NGLOG_WARNING(Service_PCTL, "(STUBBED) called");
116 IPC::ResponseBuilder rb{ctx, 2, 0, 0};
117 rb.Push(RESULT_SUCCESS);
118 }
111}; 119};
112void PCTL_A::CreateService(Kernel::HLERequestContext& ctx) { 120
121void Module::Interface::CreateService(Kernel::HLERequestContext& ctx) {
113 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 122 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
114 rb.Push(RESULT_SUCCESS); 123 rb.Push(RESULT_SUCCESS);
115 rb.PushIpcInterface<IParentalControlService>(); 124 rb.PushIpcInterface<IParentalControlService>();
116 LOG_DEBUG(Service_PCTL, "called"); 125 NGLOG_DEBUG(Service_PCTL, "called");
117} 126}
118 127
119PCTL_A::PCTL_A() : ServiceFramework("pctl:a") { 128void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx) {
120 static const FunctionInfo functions[] = { 129 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
121 {0, &PCTL_A::CreateService, "CreateService"}, 130 rb.Push(RESULT_SUCCESS);
122 {1, nullptr, "CreateServiceWithoutInitialize"}, 131 rb.PushIpcInterface<IParentalControlService>();
123 }; 132 NGLOG_DEBUG(Service_PCTL, "called");
124 RegisterHandlers(functions); 133}
134
135Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
136 : ServiceFramework(name), module(std::move(module)) {}
137
138void InstallInterfaces(SM::ServiceManager& service_manager) {
139 auto module = std::make_shared<Module>();
140 std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager);
141 std::make_shared<PCTL>(module, "pctl:a")->InstallAsService(service_manager);
142 std::make_shared<PCTL>(module, "pctl:r")->InstallAsService(service_manager);
143 std::make_shared<PCTL>(module, "pctl:s")->InstallAsService(service_manager);
125} 144}
126 145
127} // namespace Service::PCTL 146} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h
new file mode 100644
index 000000000..68da628a8
--- /dev/null
+++ b/src/core/hle/service/pctl/module.h
@@ -0,0 +1,28 @@
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::PCTL {
10
11class Module final {
12public:
13 class Interface : public ServiceFramework<Interface> {
14 public:
15 Interface(std::shared_ptr<Module> module, const char* name);
16
17 void CreateService(Kernel::HLERequestContext& ctx);
18 void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx);
19
20 protected:
21 std::shared_ptr<Module> module;
22 };
23};
24
25/// Registers all PCTL services with the specified service manager.
26void InstallInterfaces(SM::ServiceManager& service_manager);
27
28} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index 6ee81866d..de2741d66 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -3,12 +3,15 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/pctl/pctl.h" 5#include "core/hle/service/pctl/pctl.h"
6#include "core/hle/service/pctl/pctl_a.h"
7 6
8namespace Service::PCTL { 7namespace Service::PCTL {
9 8
10void InstallInterfaces(SM::ServiceManager& service_manager) { 9PCTL::PCTL(std::shared_ptr<Module> module, const char* name)
11 std::make_shared<PCTL_A>()->InstallAsService(service_manager); 10 : Module::Interface(std::move(module), name) {
11 static const FunctionInfo functions[] = {
12 {0, &PCTL::CreateService, "CreateService"},
13 {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"},
14 };
15 RegisterHandlers(functions);
12} 16}
13
14} // namespace Service::PCTL 17} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index f0a84b115..8ddf69128 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -4,11 +4,13 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/pctl/module.h"
8 8
9namespace Service::PCTL { 9namespace Service::PCTL {
10 10
11/// Registers all PCTL services with the specified service manager. 11class PCTL final : public Module::Interface {
12void InstallInterfaces(SM::ServiceManager& service_manager); 12public:
13 explicit PCTL(std::shared_ptr<Module> module, const char* name);
14};
13 15
14} // namespace Service::PCTL 16} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl_a.h b/src/core/hle/service/pctl/pctl_a.h
deleted file mode 100644
index 09ed82e1b..000000000
--- a/src/core/hle/service/pctl/pctl_a.h
+++ /dev/null
@@ -1,20 +0,0 @@
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::PCTL {
10
11class PCTL_A final : public ServiceFramework<PCTL_A> {
12public:
13 PCTL_A();
14 ~PCTL_A() = default;
15
16private:
17 void CreateService(Kernel::HLERequestContext& ctx);
18};
19
20} // namespace Service::PCTL
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 68d2b9f17..34d691b90 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -121,7 +121,7 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
121 } 121 }
122 buf.push_back('}'); 122 buf.push_back('}');
123 123
124 LOG_ERROR(Service, "unknown / unimplemented %s", fmt::to_string(buf).c_str()); 124 NGLOG_ERROR(Service, "unknown / unimplemented {}", fmt::to_string(buf));
125 UNIMPLEMENTED(); 125 UNIMPLEMENTED();
126} 126}
127 127
@@ -132,8 +132,8 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
132 return ReportUnimplementedFunction(ctx, info); 132 return ReportUnimplementedFunction(ctx, info);
133 } 133 }
134 134
135 LOG_TRACE( 135 NGLOG_TRACE(
136 Service, "%s", 136 Service, "{}",
137 MakeFunctionString(info->name, GetServiceName().c_str(), ctx.CommandBuffer()).c_str()); 137 MakeFunctionString(info->name, GetServiceName().c_str(), ctx.CommandBuffer()).c_str());
138 handler_invoker(this, info->handler_callback, ctx); 138 handler_invoker(this, info->handler_callback, ctx);
139} 139}
@@ -201,12 +201,12 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
201 VI::InstallInterfaces(*sm, nv_flinger); 201 VI::InstallInterfaces(*sm, nv_flinger);
202 Set::InstallInterfaces(*sm); 202 Set::InstallInterfaces(*sm);
203 203
204 LOG_DEBUG(Service, "initialized OK"); 204 NGLOG_DEBUG(Service, "initialized OK");
205} 205}
206 206
207/// Shutdown ServiceManager 207/// Shutdown ServiceManager
208void Shutdown() { 208void Shutdown() {
209 g_kernel_named_ports.clear(); 209 g_kernel_named_ports.clear();
210 LOG_DEBUG(Service, "shutdown OK"); 210 NGLOG_DEBUG(Service, "shutdown OK");
211} 211}
212} // namespace Service 212} // namespace Service
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index fc3e424d0..ece29aa70 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -22,7 +22,7 @@ void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
22 22
23 rb.Push(RESULT_SUCCESS); 23 rb.Push(RESULT_SUCCESS);
24 24
25 LOG_WARNING(Service_SET, "(STUBBED) called"); 25 NGLOG_WARNING(Service_SET, "(STUBBED) called");
26} 26}
27 27
28SET::SET() : ServiceFramework("set") { 28SET::SET() : ServiceFramework("set") {
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index fa85277fe..762a664c5 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -16,7 +16,7 @@ void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
16 rb.Push(RESULT_SUCCESS); 16 rb.Push(RESULT_SUCCESS);
17 rb.Push<u32>(0); 17 rb.Push<u32>(0);
18 18
19 LOG_WARNING(Service_SET, "(STUBBED) called"); 19 NGLOG_WARNING(Service_SET, "(STUBBED) called");
20} 20}
21 21
22SET_SYS::SET_SYS() : ServiceFramework("set:sys") { 22SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp
index 13e31620d..fe5097cdc 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/controller.cpp
@@ -17,7 +17,7 @@ void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
17 rb.Push(RESULT_SUCCESS); 17 rb.Push(RESULT_SUCCESS);
18 rb.Push<u32>(1); // Converted sessions start with 1 request handler 18 rb.Push<u32>(1); // Converted sessions start with 1 request handler
19 19
20 LOG_DEBUG(Service, "called, server_session=%d", ctx.Session()->GetObjectId()); 20 NGLOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetObjectId());
21} 21}
22 22
23void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) { 23void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
@@ -29,11 +29,11 @@ void Controller::DuplicateSession(Kernel::HLERequestContext& ctx) {
29 Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client}; 29 Kernel::SharedPtr<Kernel::ClientSession> session{ctx.Session()->parent->client};
30 rb.PushMoveObjects(session); 30 rb.PushMoveObjects(session);
31 31
32 LOG_DEBUG(Service, "called, session=%u", session->GetObjectId()); 32 NGLOG_DEBUG(Service, "called, session={}", session->GetObjectId());
33} 33}
34 34
35void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) { 35void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
36 LOG_WARNING(Service, "(STUBBED) called, using DuplicateSession"); 36 NGLOG_WARNING(Service, "(STUBBED) called, using DuplicateSession");
37 37
38 DuplicateSession(ctx); 38 DuplicateSession(ctx);
39} 39}
@@ -43,7 +43,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
43 rb.Push(RESULT_SUCCESS); 43 rb.Push(RESULT_SUCCESS);
44 rb.Push<u32>(0x500); 44 rb.Push<u32>(0x500);
45 45
46 LOG_WARNING(Service, "(STUBBED) called"); 46 NGLOG_WARNING(Service, "(STUBBED) called");
47} 47}
48 48
49Controller::Controller() : ServiceFramework("IpcController") { 49Controller::Controller() : ServiceFramework("IpcController") {
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 4578fc05f..073277ade 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -86,7 +86,7 @@ SM::~SM() = default;
86void SM::Initialize(Kernel::HLERequestContext& ctx) { 86void SM::Initialize(Kernel::HLERequestContext& ctx) {
87 IPC::ResponseBuilder rb{ctx, 2}; 87 IPC::ResponseBuilder rb{ctx, 2};
88 rb.Push(RESULT_SUCCESS); 88 rb.Push(RESULT_SUCCESS);
89 LOG_DEBUG(Service_SM, "called"); 89 NGLOG_DEBUG(Service_SM, "called");
90} 90}
91 91
92void SM::GetService(Kernel::HLERequestContext& ctx) { 92void SM::GetService(Kernel::HLERequestContext& ctx) {
@@ -102,8 +102,8 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
102 if (client_port.Failed()) { 102 if (client_port.Failed()) {
103 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); 103 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
104 rb.Push(client_port.Code()); 104 rb.Push(client_port.Code());
105 LOG_ERROR(Service_SM, "called service=%s -> error 0x%08X", name.c_str(), 105 NGLOG_ERROR(Service_SM, "called service={} -> error {:#010X}", name,
106 client_port.Code().raw); 106 client_port.Code().raw);
107 if (name.length() == 0) 107 if (name.length() == 0)
108 return; // LibNX Fix 108 return; // LibNX Fix
109 UNIMPLEMENTED(); 109 UNIMPLEMENTED();
@@ -113,8 +113,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
113 auto session = client_port.Unwrap()->Connect(); 113 auto session = client_port.Unwrap()->Connect();
114 ASSERT(session.Succeeded()); 114 ASSERT(session.Succeeded());
115 if (session.Succeeded()) { 115 if (session.Succeeded()) {
116 LOG_DEBUG(Service_SM, "called service=%s -> session=%u", name.c_str(), 116 NGLOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId());
117 (*session)->GetObjectId());
118 IPC::ResponseBuilder rb = 117 IPC::ResponseBuilder rb =
119 rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles); 118 rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles);
120 rb.Push(session.Code()); 119 rb.Push(session.Code());
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index f99809bed..ab909fdaa 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -8,7 +8,7 @@
8namespace Service::Sockets { 8namespace Service::Sockets {
9 9
10void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { 10void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
11 LOG_WARNING(Service, "(STUBBED) called"); 11 NGLOG_WARNING(Service, "(STUBBED) called");
12 12
13 IPC::ResponseBuilder rb{ctx, 3}; 13 IPC::ResponseBuilder rb{ctx, 3};
14 14
@@ -17,7 +17,7 @@ void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
17} 17}
18 18
19void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) { 19void BSD::StartMonitoring(Kernel::HLERequestContext& ctx) {
20 LOG_WARNING(Service, "(STUBBED) called"); 20 NGLOG_WARNING(Service, "(STUBBED) called");
21 21
22 IPC::ResponseBuilder rb{ctx, 3}; 22 IPC::ResponseBuilder rb{ctx, 3};
23 23
@@ -32,7 +32,8 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) {
32 u32 type = rp.Pop<u32>(); 32 u32 type = rp.Pop<u32>();
33 u32 protocol = rp.Pop<u32>(); 33 u32 protocol = rp.Pop<u32>();
34 34
35 LOG_WARNING(Service, "(STUBBED) called domain=%u type=%u protocol=%u", domain, type, protocol); 35 NGLOG_WARNING(Service, "(STUBBED) called domain={} type={} protocol={}", domain, type,
36 protocol);
36 37
37 u32 fd = next_fd++; 38 u32 fd = next_fd++;
38 39
@@ -44,7 +45,7 @@ void BSD::Socket(Kernel::HLERequestContext& ctx) {
44} 45}
45 46
46void BSD::Connect(Kernel::HLERequestContext& ctx) { 47void BSD::Connect(Kernel::HLERequestContext& ctx) {
47 LOG_WARNING(Service, "(STUBBED) called"); 48 NGLOG_WARNING(Service, "(STUBBED) called");
48 49
49 IPC::ResponseBuilder rb{ctx, 4}; 50 IPC::ResponseBuilder rb{ctx, 4};
50 51
@@ -54,7 +55,7 @@ void BSD::Connect(Kernel::HLERequestContext& ctx) {
54} 55}
55 56
56void BSD::SendTo(Kernel::HLERequestContext& ctx) { 57void BSD::SendTo(Kernel::HLERequestContext& ctx) {
57 LOG_WARNING(Service, "(STUBBED) called"); 58 NGLOG_WARNING(Service, "(STUBBED) called");
58 59
59 IPC::ResponseBuilder rb{ctx, 4}; 60 IPC::ResponseBuilder rb{ctx, 4};
60 61
@@ -64,7 +65,7 @@ void BSD::SendTo(Kernel::HLERequestContext& ctx) {
64} 65}
65 66
66void BSD::Close(Kernel::HLERequestContext& ctx) { 67void BSD::Close(Kernel::HLERequestContext& ctx) {
67 LOG_WARNING(Service, "(STUBBED) called"); 68 NGLOG_WARNING(Service, "(STUBBED) called");
68 69
69 IPC::ResponseBuilder rb{ctx, 4}; 70 IPC::ResponseBuilder rb{ctx, 4};
70 71
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index d235c4cfd..f377e59f2 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -10,7 +10,7 @@ namespace Service::Sockets {
10void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) { 10void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) {
11 IPC::RequestParser rp{ctx}; 11 IPC::RequestParser rp{ctx};
12 12
13 LOG_WARNING(Service, "(STUBBED) called"); 13 NGLOG_WARNING(Service, "(STUBBED) called");
14 14
15 IPC::ResponseBuilder rb{ctx, 2}; 15 IPC::ResponseBuilder rb{ctx, 2};
16 16
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 3f5a342a7..76ba97156 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -28,7 +28,7 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
28 28
29 IPC::ResponseBuilder rb{ctx, 2}; 29 IPC::ResponseBuilder rb{ctx, 2};
30 rb.Push(RESULT_SUCCESS); 30 rb.Push(RESULT_SUCCESS);
31 LOG_DEBUG(Service_SPL, "called"); 31 NGLOG_DEBUG(Service_SPL, "called");
32} 32}
33 33
34void InstallInterfaces(SM::ServiceManager& service_manager) { 34void InstallInterfaces(SM::ServiceManager& service_manager) {
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 40aea6090..8a85df91a 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -65,7 +65,7 @@ public:
65 65
66private: 66private:
67 void SetOption(Kernel::HLERequestContext& ctx) { 67 void SetOption(Kernel::HLERequestContext& ctx) {
68 LOG_WARNING(Service_SSL, "(STUBBED) called"); 68 NGLOG_WARNING(Service_SSL, "(STUBBED) called");
69 IPC::RequestParser rp{ctx}; 69 IPC::RequestParser rp{ctx};
70 70
71 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); 71 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
@@ -73,7 +73,7 @@ private:
73 } 73 }
74 74
75 void CreateConnection(Kernel::HLERequestContext& ctx) { 75 void CreateConnection(Kernel::HLERequestContext& ctx) {
76 LOG_WARNING(Service_SSL, "(STUBBED) called"); 76 NGLOG_WARNING(Service_SSL, "(STUBBED) called");
77 77
78 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 78 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
79 rb.Push(RESULT_SUCCESS); 79 rb.Push(RESULT_SUCCESS);
@@ -82,7 +82,7 @@ private:
82}; 82};
83 83
84void SSL::CreateContext(Kernel::HLERequestContext& ctx) { 84void SSL::CreateContext(Kernel::HLERequestContext& ctx) {
85 LOG_WARNING(Service_SSL, "(STUBBED) called"); 85 NGLOG_WARNING(Service_SSL, "(STUBBED) called");
86 86
87 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 87 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
88 rb.Push(RESULT_SUCCESS); 88 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 2604ecc1c..278465358 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -32,14 +32,14 @@ private:
32 const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>( 32 const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
33 std::chrono::system_clock::now().time_since_epoch()) 33 std::chrono::system_clock::now().time_since_epoch())
34 .count()}; 34 .count()};
35 LOG_DEBUG(Service_Time, "called"); 35 NGLOG_DEBUG(Service_Time, "called");
36 IPC::ResponseBuilder rb{ctx, 4}; 36 IPC::ResponseBuilder rb{ctx, 4};
37 rb.Push(RESULT_SUCCESS); 37 rb.Push(RESULT_SUCCESS);
38 rb.Push<u64>(time_since_epoch); 38 rb.Push<u64>(time_since_epoch);
39 } 39 }
40 40
41 void GetSystemClockContext(Kernel::HLERequestContext& ctx) { 41 void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
42 LOG_WARNING(Service_Time, "(STUBBED) called"); 42 NGLOG_WARNING(Service_Time, "(STUBBED) called");
43 SystemClockContext system_clock_ontext{}; 43 SystemClockContext system_clock_ontext{};
44 IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2}; 44 IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
45 rb.Push(RESULT_SUCCESS); 45 rb.Push(RESULT_SUCCESS);
@@ -58,7 +58,7 @@ public:
58 58
59private: 59private:
60 void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) { 60 void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
61 LOG_DEBUG(Service_Time, "called"); 61 NGLOG_DEBUG(Service_Time, "called");
62 SteadyClockTimePoint steady_clock_time_point{cyclesToMs(CoreTiming::GetTicks()) / 1000}; 62 SteadyClockTimePoint steady_clock_time_point{cyclesToMs(CoreTiming::GetTicks()) / 1000};
63 IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2}; 63 IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
64 rb.Push(RESULT_SUCCESS); 64 rb.Push(RESULT_SUCCESS);
@@ -86,7 +86,7 @@ public:
86 86
87private: 87private:
88 void GetDeviceLocationName(Kernel::HLERequestContext& ctx) { 88 void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
89 LOG_WARNING(Service_Time, "(STUBBED) called"); 89 NGLOG_WARNING(Service_Time, "(STUBBED) called");
90 LocationName location_name{}; 90 LocationName location_name{};
91 IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2}; 91 IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
92 rb.Push(RESULT_SUCCESS); 92 rb.Push(RESULT_SUCCESS);
@@ -94,14 +94,14 @@ private:
94 } 94 }
95 95
96 void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) { 96 void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
97 LOG_WARNING(Service_Time, "(STUBBED) called"); 97 NGLOG_WARNING(Service_Time, "(STUBBED) called");
98 IPC::ResponseBuilder rb{ctx, 3}; 98 IPC::ResponseBuilder rb{ctx, 3};
99 rb.Push(RESULT_SUCCESS); 99 rb.Push(RESULT_SUCCESS);
100 rb.Push<u32>(0); 100 rb.Push<u32>(0);
101 } 101 }
102 102
103 void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) { 103 void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
104 LOG_WARNING(Service_Time, "(STUBBED) called"); 104 NGLOG_WARNING(Service_Time, "(STUBBED) called");
105 IPC::ResponseBuilder rb{ctx, 2}; 105 IPC::ResponseBuilder rb{ctx, 2};
106 rb.Push(RESULT_SUCCESS); 106 rb.Push(RESULT_SUCCESS);
107 } 107 }
@@ -110,7 +110,7 @@ private:
110 IPC::RequestParser rp{ctx}; 110 IPC::RequestParser rp{ctx};
111 u64 posix_time = rp.Pop<u64>(); 111 u64 posix_time = rp.Pop<u64>();
112 112
113 LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x%016lX", posix_time); 113 NGLOG_WARNING(Service_Time, "(STUBBED) called, posix_time={:#018X}", posix_time);
114 114
115 CalendarTime calendar_time{2018, 1, 1, 0, 0, 0}; 115 CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
116 CalendarAdditionalInfo additional_info{}; 116 CalendarAdditionalInfo additional_info{};
@@ -125,35 +125,35 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct
125 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 125 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
126 rb.Push(RESULT_SUCCESS); 126 rb.Push(RESULT_SUCCESS);
127 rb.PushIpcInterface<ISystemClock>(); 127 rb.PushIpcInterface<ISystemClock>();
128 LOG_DEBUG(Service_Time, "called"); 128 NGLOG_DEBUG(Service_Time, "called");
129} 129}
130 130
131void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) { 131void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
132 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 132 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
133 rb.Push(RESULT_SUCCESS); 133 rb.Push(RESULT_SUCCESS);
134 rb.PushIpcInterface<ISystemClock>(); 134 rb.PushIpcInterface<ISystemClock>();
135 LOG_DEBUG(Service_Time, "called"); 135 NGLOG_DEBUG(Service_Time, "called");
136} 136}
137 137
138void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { 138void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
139 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 139 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
140 rb.Push(RESULT_SUCCESS); 140 rb.Push(RESULT_SUCCESS);
141 rb.PushIpcInterface<ISteadyClock>(); 141 rb.PushIpcInterface<ISteadyClock>();
142 LOG_DEBUG(Service_Time, "called"); 142 NGLOG_DEBUG(Service_Time, "called");
143} 143}
144 144
145void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { 145void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
146 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 146 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
147 rb.Push(RESULT_SUCCESS); 147 rb.Push(RESULT_SUCCESS);
148 rb.PushIpcInterface<ITimeZoneService>(); 148 rb.PushIpcInterface<ITimeZoneService>();
149 LOG_DEBUG(Service_Time, "called"); 149 NGLOG_DEBUG(Service_Time, "called");
150} 150}
151 151
152void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { 152void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
153 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 153 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
154 rb.Push(RESULT_SUCCESS); 154 rb.Push(RESULT_SUCCESS);
155 rb.PushIpcInterface<ISystemClock>(); 155 rb.PushIpcInterface<ISystemClock>();
156 LOG_DEBUG(Service_Time, "called"); 156 NGLOG_DEBUG(Service_Time, "called");
157} 157}
158 158
159Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) 159Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 36ae2215f..45f3568d2 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -470,7 +470,7 @@ private:
470 u32 flags = rp.Pop<u32>(); 470 u32 flags = rp.Pop<u32>();
471 auto buffer_queue = nv_flinger->GetBufferQueue(id); 471 auto buffer_queue = nv_flinger->GetBufferQueue(id);
472 472
473 LOG_DEBUG(Service_VI, "called, transaction=%x", static_cast<u32>(transaction)); 473 NGLOG_DEBUG(Service_VI, "called, transaction={:X}", static_cast<u32>(transaction));
474 474
475 if (transaction == TransactionId::Connect) { 475 if (transaction == TransactionId::Connect) {
476 IGBPConnectRequestParcel request{ctx.ReadBuffer()}; 476 IGBPConnectRequestParcel request{ctx.ReadBuffer()};
@@ -532,7 +532,7 @@ private:
532 IGBPQueryResponseParcel response{value}; 532 IGBPQueryResponseParcel response{value};
533 ctx.WriteBuffer(response.Serialize()); 533 ctx.WriteBuffer(response.Serialize());
534 } else if (transaction == TransactionId::CancelBuffer) { 534 } else if (transaction == TransactionId::CancelBuffer) {
535 LOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); 535 NGLOG_WARNING(Service_VI, "(STUBBED) called, transaction=CancelBuffer");
536 } else { 536 } else {
537 ASSERT_MSG(false, "Unimplemented"); 537 ASSERT_MSG(false, "Unimplemented");
538 } 538 }
@@ -547,7 +547,8 @@ private:
547 s32 addval = rp.PopRaw<s32>(); 547 s32 addval = rp.PopRaw<s32>();
548 u32 type = rp.Pop<u32>(); 548 u32 type = rp.Pop<u32>();
549 549
550 LOG_WARNING(Service_VI, "(STUBBED) called id=%u, addval=%08X, type=%08X", id, addval, type); 550 NGLOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
551 type);
551 IPC::ResponseBuilder rb{ctx, 2}; 552 IPC::ResponseBuilder rb{ctx, 2};
552 rb.Push(RESULT_SUCCESS); 553 rb.Push(RESULT_SUCCESS);
553 } 554 }
@@ -561,7 +562,7 @@ private:
561 562
562 // TODO(Subv): Find out what this actually is. 563 // TODO(Subv): Find out what this actually is.
563 564
564 LOG_WARNING(Service_VI, "(STUBBED) called id=%u, unknown=%08X", id, unknown); 565 NGLOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
565 IPC::ResponseBuilder rb{ctx, 2, 1}; 566 IPC::ResponseBuilder rb{ctx, 2, 1};
566 rb.Push(RESULT_SUCCESS); 567 rb.Push(RESULT_SUCCESS);
567 rb.PushCopyObjects(buffer_queue->GetNativeHandle()); 568 rb.PushCopyObjects(buffer_queue->GetNativeHandle());
@@ -624,7 +625,7 @@ public:
624 625
625private: 626private:
626 void SetLayerZ(Kernel::HLERequestContext& ctx) { 627 void SetLayerZ(Kernel::HLERequestContext& ctx) {
627 LOG_WARNING(Service_VI, "(STUBBED) called"); 628 NGLOG_WARNING(Service_VI, "(STUBBED) called");
628 IPC::RequestParser rp{ctx}; 629 IPC::RequestParser rp{ctx};
629 u64 layer_id = rp.Pop<u64>(); 630 u64 layer_id = rp.Pop<u64>();
630 u64 z_value = rp.Pop<u64>(); 631 u64 z_value = rp.Pop<u64>();
@@ -639,8 +640,8 @@ private:
639 bool visibility = rp.Pop<bool>(); 640 bool visibility = rp.Pop<bool>();
640 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); 641 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
641 rb.Push(RESULT_SUCCESS); 642 rb.Push(RESULT_SUCCESS);
642 LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id, 643 NGLOG_WARNING(Service_VI, "(STUBBED) called, layer_id={:#010X}, visibility={}", layer_id,
643 visibility); 644 visibility);
644 } 645 }
645}; 646};
646 647
@@ -722,7 +723,7 @@ public:
722 723
723private: 724private:
724 void CloseDisplay(Kernel::HLERequestContext& ctx) { 725 void CloseDisplay(Kernel::HLERequestContext& ctx) {
725 LOG_WARNING(Service_VI, "(STUBBED) called"); 726 NGLOG_WARNING(Service_VI, "(STUBBED) called");
726 IPC::RequestParser rp{ctx}; 727 IPC::RequestParser rp{ctx};
727 u64 display = rp.Pop<u64>(); 728 u64 display = rp.Pop<u64>();
728 729
@@ -731,7 +732,7 @@ private:
731 } 732 }
732 733
733 void CreateManagedLayer(Kernel::HLERequestContext& ctx) { 734 void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
734 LOG_WARNING(Service_VI, "(STUBBED) called"); 735 NGLOG_WARNING(Service_VI, "(STUBBED) called");
735 IPC::RequestParser rp{ctx}; 736 IPC::RequestParser rp{ctx};
736 u32 unknown = rp.Pop<u32>(); 737 u32 unknown = rp.Pop<u32>();
737 rp.Skip(1, false); 738 rp.Skip(1, false);
@@ -746,7 +747,7 @@ private:
746 } 747 }
747 748
748 void AddToLayerStack(Kernel::HLERequestContext& ctx) { 749 void AddToLayerStack(Kernel::HLERequestContext& ctx) {
749 LOG_WARNING(Service_VI, "(STUBBED) called"); 750 NGLOG_WARNING(Service_VI, "(STUBBED) called");
750 IPC::RequestParser rp{ctx}; 751 IPC::RequestParser rp{ctx};
751 u32 stack = rp.Pop<u32>(); 752 u32 stack = rp.Pop<u32>();
752 u64 layer_id = rp.Pop<u64>(); 753 u64 layer_id = rp.Pop<u64>();
@@ -761,8 +762,8 @@ private:
761 bool visibility = rp.Pop<bool>(); 762 bool visibility = rp.Pop<bool>();
762 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); 763 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
763 rb.Push(RESULT_SUCCESS); 764 rb.Push(RESULT_SUCCESS);
764 LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id, 765 NGLOG_WARNING(Service_VI, "(STUBBED) called, layer_id={:#X}, visibility={}", layer_id,
765 visibility); 766 visibility);
766 } 767 }
767 768
768 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; 769 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
@@ -775,7 +776,7 @@ public:
775 776
776private: 777private:
777 void GetRelayService(Kernel::HLERequestContext& ctx) { 778 void GetRelayService(Kernel::HLERequestContext& ctx) {
778 LOG_WARNING(Service_VI, "(STUBBED) called"); 779 NGLOG_WARNING(Service_VI, "(STUBBED) called");
779 780
780 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 781 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
781 rb.Push(RESULT_SUCCESS); 782 rb.Push(RESULT_SUCCESS);
@@ -783,7 +784,7 @@ private:
783 } 784 }
784 785
785 void GetSystemDisplayService(Kernel::HLERequestContext& ctx) { 786 void GetSystemDisplayService(Kernel::HLERequestContext& ctx) {
786 LOG_WARNING(Service_VI, "(STUBBED) called"); 787 NGLOG_WARNING(Service_VI, "(STUBBED) called");
787 788
788 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 789 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
789 rb.Push(RESULT_SUCCESS); 790 rb.Push(RESULT_SUCCESS);
@@ -791,7 +792,7 @@ private:
791 } 792 }
792 793
793 void GetManagerDisplayService(Kernel::HLERequestContext& ctx) { 794 void GetManagerDisplayService(Kernel::HLERequestContext& ctx) {
794 LOG_WARNING(Service_VI, "(STUBBED) called"); 795 NGLOG_WARNING(Service_VI, "(STUBBED) called");
795 796
796 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 797 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
797 rb.Push(RESULT_SUCCESS); 798 rb.Push(RESULT_SUCCESS);
@@ -799,7 +800,7 @@ private:
799 } 800 }
800 801
801 void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) { 802 void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) {
802 LOG_WARNING(Service_VI, "(STUBBED) called"); 803 NGLOG_WARNING(Service_VI, "(STUBBED) called");
803 804
804 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 805 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
805 rb.Push(RESULT_SUCCESS); 806 rb.Push(RESULT_SUCCESS);
@@ -807,7 +808,7 @@ private:
807 } 808 }
808 809
809 void OpenDisplay(Kernel::HLERequestContext& ctx) { 810 void OpenDisplay(Kernel::HLERequestContext& ctx) {
810 LOG_WARNING(Service_VI, "(STUBBED) called"); 811 NGLOG_WARNING(Service_VI, "(STUBBED) called");
811 IPC::RequestParser rp{ctx}; 812 IPC::RequestParser rp{ctx};
812 auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); 813 auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
813 auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); 814 auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@@ -822,7 +823,7 @@ private:
822 } 823 }
823 824
824 void CloseDisplay(Kernel::HLERequestContext& ctx) { 825 void CloseDisplay(Kernel::HLERequestContext& ctx) {
825 LOG_WARNING(Service_VI, "(STUBBED) called"); 826 NGLOG_WARNING(Service_VI, "(STUBBED) called");
826 IPC::RequestParser rp{ctx}; 827 IPC::RequestParser rp{ctx};
827 u64 display_id = rp.Pop<u64>(); 828 u64 display_id = rp.Pop<u64>();
828 829
@@ -831,7 +832,7 @@ private:
831 } 832 }
832 833
833 void GetDisplayResolution(Kernel::HLERequestContext& ctx) { 834 void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
834 LOG_WARNING(Service_VI, "(STUBBED) called"); 835 NGLOG_WARNING(Service_VI, "(STUBBED) called");
835 IPC::RequestParser rp{ctx}; 836 IPC::RequestParser rp{ctx};
836 u64 display_id = rp.Pop<u64>(); 837 u64 display_id = rp.Pop<u64>();
837 838
@@ -848,7 +849,7 @@ private:
848 } 849 }
849 850
850 void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { 851 void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
851 LOG_WARNING(Service_VI, "(STUBBED) called"); 852 NGLOG_WARNING(Service_VI, "(STUBBED) called");
852 IPC::RequestParser rp{ctx}; 853 IPC::RequestParser rp{ctx};
853 u32 scaling_mode = rp.Pop<u32>(); 854 u32 scaling_mode = rp.Pop<u32>();
854 u64 unknown = rp.Pop<u64>(); 855 u64 unknown = rp.Pop<u64>();
@@ -864,11 +865,11 @@ private:
864 IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); 865 IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
865 rb.Push(RESULT_SUCCESS); 866 rb.Push(RESULT_SUCCESS);
866 rb.Push<u64>(1); 867 rb.Push<u64>(1);
867 LOG_WARNING(Service_VI, "(STUBBED) called"); 868 NGLOG_WARNING(Service_VI, "(STUBBED) called");
868 } 869 }
869 870
870 void OpenLayer(Kernel::HLERequestContext& ctx) { 871 void OpenLayer(Kernel::HLERequestContext& ctx) {
871 LOG_DEBUG(Service_VI, "called"); 872 NGLOG_DEBUG(Service_VI, "called");
872 IPC::RequestParser rp{ctx}; 873 IPC::RequestParser rp{ctx};
873 auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); 874 auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
874 auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); 875 auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@@ -888,7 +889,7 @@ private:
888 } 889 }
889 890
890 void CreateStrayLayer(Kernel::HLERequestContext& ctx) { 891 void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
891 LOG_DEBUG(Service_VI, "called"); 892 NGLOG_DEBUG(Service_VI, "called");
892 893
893 IPC::RequestParser rp{ctx}; 894 IPC::RequestParser rp{ctx};
894 u32 flags = rp.Pop<u32>(); 895 u32 flags = rp.Pop<u32>();
@@ -908,7 +909,7 @@ private:
908 } 909 }
909 910
910 void DestroyStrayLayer(Kernel::HLERequestContext& ctx) { 911 void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
911 LOG_WARNING(Service_VI, "(STUBBED) called"); 912 NGLOG_WARNING(Service_VI, "(STUBBED) called");
912 913
913 IPC::RequestParser rp{ctx}; 914 IPC::RequestParser rp{ctx};
914 u64 layer_id = rp.Pop<u64>(); 915 u64 layer_id = rp.Pop<u64>();
@@ -918,7 +919,7 @@ private:
918 } 919 }
919 920
920 void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) { 921 void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
921 LOG_WARNING(Service_VI, "(STUBBED) called"); 922 NGLOG_WARNING(Service_VI, "(STUBBED) called");
922 IPC::RequestParser rp{ctx}; 923 IPC::RequestParser rp{ctx};
923 u64 display_id = rp.Pop<u64>(); 924 u64 display_id = rp.Pop<u64>();
924 925
@@ -967,7 +968,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name,
967 : ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {} 968 : ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {}
968 969
969void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) { 970void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) {
970 LOG_WARNING(Service_VI, "(STUBBED) called"); 971 NGLOG_WARNING(Service_VI, "(STUBBED) called");
971 972
972 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 973 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
973 rb.Push(RESULT_SUCCESS); 974 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index 0db604c76..f8a40390a 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -33,7 +33,8 @@ inline void Read(T& var, const u32 addr) {
33 LCD::Read(var, addr); 33 LCD::Read(var, addr);
34 break; 34 break;
35 default: 35 default:
36 LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); 36 NGLOG_ERROR(HW_Memory, "Unknown Read{} @ {:#010X}", sizeof(var) * 8, addr);
37 break;
37 } 38 }
38} 39}
39 40
@@ -61,7 +62,8 @@ inline void Write(u32 addr, const T data) {
61 LCD::Write(addr, data); 62 LCD::Write(addr, data);
62 break; 63 break;
63 default: 64 default:
64 LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); 65 NGLOG_ERROR(HW_Memory, "Unknown Write{} {:#010X} @ {:#010X}", sizeof(data) * 8, data, addr);
66 break;
65 } 67 }
66} 68}
67 69
@@ -83,12 +85,12 @@ void Update() {}
83/// Initialize hardware 85/// Initialize hardware
84void Init() { 86void Init() {
85 LCD::Init(); 87 LCD::Init();
86 LOG_DEBUG(HW, "initialized OK"); 88 NGLOG_DEBUG(HW, "Initialized OK");
87} 89}
88 90
89/// Shutdown hardware 91/// Shutdown hardware
90void Shutdown() { 92void Shutdown() {
91 LCD::Shutdown(); 93 LCD::Shutdown();
92 LOG_DEBUG(HW, "shutdown OK"); 94 NGLOG_DEBUG(HW, "Shutdown OK");
93} 95}
94} // namespace HW 96} // namespace HW
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp
index 690079b65..7d0046bf3 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -20,7 +20,7 @@ inline void Read(T& var, const u32 raw_addr) {
20 20
21 // Reads other than u32 are untested, so I'd rather have them abort than silently fail 21 // Reads other than u32 are untested, so I'd rather have them abort than silently fail
22 if (index >= 0x400 || !std::is_same<T, u32>::value) { 22 if (index >= 0x400 || !std::is_same<T, u32>::value) {
23 LOG_ERROR(HW_LCD, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); 23 NGLOG_ERROR(HW_LCD, "Unknown Read{} @ {:#010X}", sizeof(var) * 8, addr);
24 return; 24 return;
25 } 25 }
26 26
@@ -34,7 +34,7 @@ inline void Write(u32 addr, const T data) {
34 34
35 // Writes other than u32 are untested, so I'd rather have them abort than silently fail 35 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
36 if (index >= 0x400 || !std::is_same<T, u32>::value) { 36 if (index >= 0x400 || !std::is_same<T, u32>::value) {
37 LOG_ERROR(HW_LCD, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); 37 NGLOG_ERROR(HW_LCD, "Unknown Write{} {:#010X} @ {:#010X}", sizeof(data) * 8, data, addr);
38 return; 38 return;
39 } 39 }
40 40
@@ -56,12 +56,12 @@ template void Write<u8>(u32 addr, const u8 data);
56/// Initialize hardware 56/// Initialize hardware
57void Init() { 57void Init() {
58 memset(&g_regs, 0, sizeof(g_regs)); 58 memset(&g_regs, 0, sizeof(g_regs));
59 LOG_DEBUG(HW_LCD, "initialized OK"); 59 NGLOG_DEBUG(HW_LCD, "Initialized OK");
60} 60}
61 61
62/// Shutdown hardware 62/// Shutdown hardware
63void Shutdown() { 63void Shutdown() {
64 LOG_DEBUG(HW_LCD, "shutdown OK"); 64 NGLOG_DEBUG(HW_LCD, "Shutdown OK");
65} 65}
66 66
67} // namespace LCD 67} // namespace LCD
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 8696c28bd..40a81025f 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -132,7 +132,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
132 const VAddr load_addr = next_load_addr; 132 const VAddr load_addr = next_load_addr;
133 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr); 133 next_load_addr = AppLoader_NSO::LoadModule(path, load_addr);
134 if (next_load_addr) { 134 if (next_load_addr) {
135 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, module, load_addr); 135 NGLOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr);
136 } else { 136 } else {
137 next_load_addr = load_addr; 137 next_load_addr = load_addr;
138 } 138 }
@@ -163,7 +163,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(
163 std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 163 std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) {
164 164
165 if (filepath_romfs.empty()) { 165 if (filepath_romfs.empty()) {
166 LOG_DEBUG(Loader, "No RomFS available"); 166 NGLOG_DEBUG(Loader, "No RomFS available");
167 return ResultStatus::ErrorNotUsed; 167 return ResultStatus::ErrorNotUsed;
168 } 168 }
169 169
@@ -176,8 +176,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(
176 offset = 0; 176 offset = 0;
177 size = romfs_file->GetSize(); 177 size = romfs_file->GetSize();
178 178
179 LOG_DEBUG(Loader, "RomFS offset: 0x%016" PRIX64, offset); 179 NGLOG_DEBUG(Loader, "RomFS offset: {:#018X}", offset);
180 LOG_DEBUG(Loader, "RomFS size: 0x%016" PRIX64, size); 180 NGLOG_DEBUG(Loader, "RomFS size: {:#018X}", size);
181 181
182 // Reset read pointer 182 // Reset read pointer
183 file.Seek(0, SEEK_SET); 183 file.Seek(0, SEEK_SET);
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index e9f462196..e42d3a870 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -273,18 +273,18 @@ const char* ElfReader::GetSectionName(int section) const {
273} 273}
274 274
275SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) { 275SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
276 LOG_DEBUG(Loader, "String section: %i", header->e_shstrndx); 276 NGLOG_DEBUG(Loader, "String section: {}", header->e_shstrndx);
277 277
278 // Should we relocate? 278 // Should we relocate?
279 relocate = (header->e_type != ET_EXEC); 279 relocate = (header->e_type != ET_EXEC);
280 280
281 if (relocate) { 281 if (relocate) {
282 LOG_DEBUG(Loader, "Relocatable module"); 282 NGLOG_DEBUG(Loader, "Relocatable module");
283 entryPoint += vaddr; 283 entryPoint += vaddr;
284 } else { 284 } else {
285 LOG_DEBUG(Loader, "Prerelocated executable"); 285 NGLOG_DEBUG(Loader, "Prerelocated executable");
286 } 286 }
287 LOG_DEBUG(Loader, "%i segments:", header->e_phnum); 287 NGLOG_DEBUG(Loader, "{} segments:", header->e_phnum);
288 288
289 // First pass : Get the bits into RAM 289 // First pass : Get the bits into RAM
290 u32 base_addr = relocate ? vaddr : 0; 290 u32 base_addr = relocate ? vaddr : 0;
@@ -304,8 +304,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
304 304
305 for (unsigned int i = 0; i < header->e_phnum; ++i) { 305 for (unsigned int i = 0; i < header->e_phnum; ++i) {
306 Elf32_Phdr* p = &segments[i]; 306 Elf32_Phdr* p = &segments[i];
307 LOG_DEBUG(Loader, "Type: %i Vaddr: %08X Filesz: %8X Memsz: %8X ", p->p_type, p->p_vaddr, 307 NGLOG_DEBUG(Loader, "Type: {} Vaddr: {:08X} Filesz: {:08X} Memsz: {:08X} ", p->p_type,
308 p->p_filesz, p->p_memsz); 308 p->p_vaddr, p->p_filesz, p->p_memsz);
309 309
310 if (p->p_type == PT_LOAD) { 310 if (p->p_type == PT_LOAD) {
311 CodeSet::Segment* codeset_segment; 311 CodeSet::Segment* codeset_segment;
@@ -317,16 +317,16 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
317 } else if (permission_flags == (PF_R | PF_W)) { 317 } else if (permission_flags == (PF_R | PF_W)) {
318 codeset_segment = &codeset->data; 318 codeset_segment = &codeset->data;
319 } else { 319 } else {
320 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, 320 NGLOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id {} with flags {:X}", i,
321 p->p_flags); 321 p->p_flags);
322 continue; 322 continue;
323 } 323 }
324 324
325 if (codeset_segment->size != 0) { 325 if (codeset_segment->size != 0) {
326 LOG_ERROR(Loader, 326 NGLOG_ERROR(Loader,
327 "ELF has more than one segment of the same type. Skipping extra " 327 "ELF has more than one segment of the same type. Skipping extra "
328 "segment (id %i)", 328 "segment (id {})",
329 i); 329 i);
330 continue; 330 continue;
331 } 331 }
332 332
@@ -345,7 +345,7 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
345 codeset->entrypoint = base_addr + header->e_entry; 345 codeset->entrypoint = base_addr + header->e_entry;
346 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 346 codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
347 347
348 LOG_DEBUG(Loader, "Done loading."); 348 NGLOG_DEBUG(Loader, "Done loading.");
349 349
350 return codeset; 350 return codeset;
351} 351}
diff --git a/src/core/loader/linker.cpp b/src/core/loader/linker.cpp
index 69198e3e3..c7be5f265 100644
--- a/src/core/loader/linker.cpp
+++ b/src/core/loader/linker.cpp
@@ -84,7 +84,7 @@ void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<
84 } 84 }
85 break; 85 break;
86 default: 86 default:
87 LOG_CRITICAL(Loader, "Unknown relocation type: %d", static_cast<int>(rela.type)); 87 NGLOG_CRITICAL(Loader, "Unknown relocation type: {}", static_cast<int>(rela.type));
88 break; 88 break;
89 } 89 }
90 } 90 }
@@ -141,7 +141,7 @@ void Linker::ResolveImports() {
141 if (search != exports.end()) { 141 if (search != exports.end()) {
142 Memory::Write64(import.second.ea, search->second + import.second.addend); 142 Memory::Write64(import.second.ea, search->second + import.second.addend);
143 } else { 143 } else {
144 LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str()); 144 NGLOG_ERROR(Loader, "Unresolved import: {}", import.first);
145 } 145 }
146 } 146 }
147} 147}
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 2ec08506d..6a4fd38cb 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -41,7 +41,7 @@ FileType IdentifyFile(FileUtil::IOFile& file, const std::string& filepath) {
41FileType IdentifyFile(const std::string& file_name) { 41FileType IdentifyFile(const std::string& file_name) {
42 FileUtil::IOFile file(file_name, "rb"); 42 FileUtil::IOFile file(file_name, "rb");
43 if (!file.IsOpen()) { 43 if (!file.IsOpen()) {
44 LOG_ERROR(Loader, "Failed to load file %s", file_name.c_str()); 44 NGLOG_ERROR(Loader, "Failed to load file {}", file_name);
45 return FileType::Unknown; 45 return FileType::Unknown;
46 } 46 }
47 47
@@ -116,7 +116,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileTyp
116std::unique_ptr<AppLoader> GetLoader(const std::string& filename) { 116std::unique_ptr<AppLoader> GetLoader(const std::string& filename) {
117 FileUtil::IOFile file(filename, "rb"); 117 FileUtil::IOFile file(filename, "rb");
118 if (!file.IsOpen()) { 118 if (!file.IsOpen()) {
119 LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); 119 NGLOG_ERROR(Loader, "Failed to load file {}", filename);
120 return nullptr; 120 return nullptr;
121 } 121 }
122 122
@@ -127,12 +127,12 @@ std::unique_ptr<AppLoader> GetLoader(const std::string& filename) {
127 FileType filename_type = GuessFromExtension(filename_extension); 127 FileType filename_type = GuessFromExtension(filename_extension);
128 128
129 if (type != filename_type) { 129 if (type != filename_type) {
130 LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); 130 NGLOG_WARNING(Loader, "File {} has a different type than its extension.", filename);
131 if (FileType::Unknown == type) 131 if (FileType::Unknown == type)
132 type = filename_type; 132 type = filename_type;
133 } 133 }
134 134
135 LOG_DEBUG(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); 135 NGLOG_DEBUG(Loader, "Loading file {} as {}...", filename, GetFileTypeString(type));
136 136
137 return GetFileLoader(std::move(file), type, filename_filename, filename); 137 return GetFileLoader(std::move(file), type, filename_filename, filename);
138} 138}
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index b5133e4d6..3853cfa1a 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -137,7 +137,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
137 process->address_mappings = default_address_mappings; 137 process->address_mappings = default_address_mappings;
138 process->resource_limit = 138 process->resource_limit =
139 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 139 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
140 process->Run(base_addr, 48, Memory::DEFAULT_STACK_SIZE); 140 process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
141 141
142 is_loaded = true; 142 is_loaded = true;
143 return ResultStatus::Success; 143 return ResultStatus::Success;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 3bc10ed0d..1842bae20 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -73,7 +73,7 @@ static std::vector<u8> ReadSegment(FileUtil::IOFile& file, const NsoSegmentHeade
73 73
74 file.Seek(header.offset, SEEK_SET); 74 file.Seek(header.offset, SEEK_SET);
75 if (compressed_size != file.ReadBytes(compressed_data.data(), compressed_size)) { 75 if (compressed_size != file.ReadBytes(compressed_data.data(), compressed_size)) {
76 LOG_CRITICAL(Loader, "Failed to read %d NSO LZ4 compressed bytes", compressed_size); 76 NGLOG_CRITICAL(Loader, "Failed to read {} NSO LZ4 compressed bytes", compressed_size);
77 return {}; 77 return {};
78 } 78 }
79 79
@@ -158,14 +158,13 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
158 158
159 // Load module 159 // Load module
160 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR); 160 LoadModule(filepath, Memory::PROCESS_IMAGE_VADDR);
161 LOG_DEBUG(Loader, "loaded module %s @ 0x%" PRIx64, filepath.c_str(), 161 NGLOG_DEBUG(Loader, "loaded module {} @ {:#X}", filepath, Memory::PROCESS_IMAGE_VADDR);
162 Memory::PROCESS_IMAGE_VADDR);
163 162
164 process->svc_access_mask.set(); 163 process->svc_access_mask.set();
165 process->address_mappings = default_address_mappings; 164 process->address_mappings = default_address_mappings;
166 process->resource_limit = 165 process->resource_limit =
167 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 166 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
168 process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Memory::DEFAULT_STACK_SIZE); 167 process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
169 168
170 is_loaded = true; 169 is_loaded = true;
171 return ResultStatus::Success; 170 return ResultStatus::Success;
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 291bf066f..2afa0916d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -39,8 +39,8 @@ PageTable* GetCurrentPageTable() {
39} 39}
40 40
41static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { 41static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) {
42 LOG_DEBUG(HW_Memory, "Mapping %p onto %016" PRIX64 "-%016" PRIX64, memory, base * PAGE_SIZE, 42 NGLOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
43 (base + size) * PAGE_SIZE); 43 (base + size) * PAGE_SIZE);
44 44
45 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE, 45 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
46 FlushMode::FlushAndInvalidate); 46 FlushMode::FlushAndInvalidate);
@@ -169,10 +169,10 @@ T Read(const VAddr vaddr) {
169 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 169 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
170 switch (type) { 170 switch (type) {
171 case PageType::Unmapped: 171 case PageType::Unmapped:
172 LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr); 172 NGLOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#010X}", sizeof(T) * 8, vaddr);
173 return 0; 173 return 0;
174 case PageType::Memory: 174 case PageType::Memory:
175 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 175 ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
176 break; 176 break;
177 case PageType::RasterizerCachedMemory: { 177 case PageType::RasterizerCachedMemory: {
178 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); 178 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
@@ -201,11 +201,11 @@ void Write(const VAddr vaddr, const T data) {
201 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 201 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
202 switch (type) { 202 switch (type) {
203 case PageType::Unmapped: 203 case PageType::Unmapped:
204 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, 204 NGLOG_ERROR(HW_Memory, "Unmapped Write{} {:#010X} @ {:#018X}", sizeof(data) * 8, (u32)data,
205 vaddr); 205 vaddr);
206 return; 206 return;
207 case PageType::Memory: 207 case PageType::Memory:
208 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 208 ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
209 break; 209 break;
210 case PageType::RasterizerCachedMemory: { 210 case PageType::RasterizerCachedMemory: {
211 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); 211 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate);
@@ -251,7 +251,7 @@ u8* GetPointer(const VAddr vaddr) {
251 return GetPointerFromVMA(vaddr); 251 return GetPointerFromVMA(vaddr);
252 } 252 }
253 253
254 LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); 254 NGLOG_ERROR(HW_Memory, "Unknown GetPointer @ {:#018X}", vaddr);
255 return nullptr; 255 return nullptr;
256} 256}
257 257
@@ -288,13 +288,12 @@ u8* GetPhysicalPointer(PAddr address) {
288 }); 288 });
289 289
290 if (area == std::end(memory_areas)) { 290 if (area == std::end(memory_areas)) {
291 LOG_ERROR(HW_Memory, "unknown GetPhysicalPointer @ 0x%016" PRIX64, address); 291 NGLOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#018X}", address);
292 return nullptr; 292 return nullptr;
293 } 293 }
294 294
295 if (area->paddr_base == IO_AREA_PADDR) { 295 if (area->paddr_base == IO_AREA_PADDR) {
296 LOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr=0x%016" PRIX64, 296 NGLOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr={:018X}", address);
297 address);
298 return nullptr; 297 return nullptr;
299 } 298 }
300 299
@@ -325,15 +324,29 @@ u8* GetPhysicalPointer(PAddr address) {
325 return target_pointer; 324 return target_pointer;
326} 325}
327 326
328void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { 327void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) {
329 if (start == 0) { 328 if (gpu_addr == 0) {
330 return; 329 return;
331 } 330 }
332 331
333 u64 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; 332 // Iterate over a contiguous CPU address space, which corresponds to the specified GPU address
334 VAddr vaddr = start; 333 // space, marking the region as un/cached. The region is marked un/cached at a granularity of
334 // CPU pages, hence why we iterate on a CPU page basis (note: GPU page size is different). This
335 // assumes the specified GPU address region is contiguous as well.
336
337 u64 num_pages = ((gpu_addr + size - 1) >> PAGE_BITS) - (gpu_addr >> PAGE_BITS) + 1;
338 for (unsigned i = 0; i < num_pages; ++i, gpu_addr += PAGE_SIZE) {
339 boost::optional<VAddr> maybe_vaddr =
340 Core::System::GetInstance().GPU().memory_manager->GpuToCpuAddress(gpu_addr);
341 // The GPU <-> CPU virtual memory mapping is not 1:1
342 if (!maybe_vaddr) {
343 NGLOG_ERROR(HW_Memory,
344 "Trying to flush a cached region to an invalid physical address {:016X}",
345 gpu_addr);
346 continue;
347 }
348 VAddr vaddr = *maybe_vaddr;
335 349
336 for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
337 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; 350 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
338 351
339 if (cached) { 352 if (cached) {
@@ -347,6 +360,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
347 page_type = PageType::RasterizerCachedMemory; 360 page_type = PageType::RasterizerCachedMemory;
348 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; 361 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
349 break; 362 break;
363 case PageType::RasterizerCachedMemory:
364 // There can be more than one GPU region mapped per CPU region, so it's common that
365 // this area is already marked as cached.
366 break;
350 default: 367 default:
351 UNREACHABLE(); 368 UNREACHABLE();
352 } 369 }
@@ -357,6 +374,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
357 // It is not necessary for a process to have this region mapped into its address 374 // It is not necessary for a process to have this region mapped into its address
358 // space, for example, a system module need not have a VRAM mapping. 375 // space, for example, a system module need not have a VRAM mapping.
359 break; 376 break;
377 case PageType::Memory:
378 // There can be more than one GPU region mapped per CPU region, so it's common that
379 // this area is already unmarked as cached.
380 break;
360 case PageType::RasterizerCachedMemory: { 381 case PageType::RasterizerCachedMemory: {
361 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); 382 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
362 if (pointer == nullptr) { 383 if (pointer == nullptr) {
@@ -394,19 +415,29 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) {
394 415
395 VAddr overlap_start = std::max(start, region_start); 416 VAddr overlap_start = std::max(start, region_start);
396 VAddr overlap_end = std::min(end, region_end); 417 VAddr overlap_end = std::min(end, region_end);
418
419 std::vector<Tegra::GPUVAddr> gpu_addresses =
420 Core::System::GetInstance().GPU().memory_manager->CpuToGpuAddress(overlap_start);
421
422 if (gpu_addresses.empty()) {
423 return;
424 }
425
397 u64 overlap_size = overlap_end - overlap_start; 426 u64 overlap_size = overlap_end - overlap_start;
398 427
399 auto* rasterizer = VideoCore::g_renderer->Rasterizer(); 428 for (const auto& gpu_address : gpu_addresses) {
400 switch (mode) { 429 auto* rasterizer = VideoCore::g_renderer->Rasterizer();
401 case FlushMode::Flush: 430 switch (mode) {
402 rasterizer->FlushRegion(overlap_start, overlap_size); 431 case FlushMode::Flush:
403 break; 432 rasterizer->FlushRegion(gpu_address, overlap_size);
404 case FlushMode::Invalidate: 433 break;
405 rasterizer->InvalidateRegion(overlap_start, overlap_size); 434 case FlushMode::Invalidate:
406 break; 435 rasterizer->InvalidateRegion(gpu_address, overlap_size);
407 case FlushMode::FlushAndInvalidate: 436 break;
408 rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); 437 case FlushMode::FlushAndInvalidate:
409 break; 438 rasterizer->FlushAndInvalidateRegion(gpu_address, overlap_size);
439 break;
440 }
410 } 441 }
411 }; 442 };
412 443
@@ -445,8 +476,9 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
445 476
446 switch (page_table.attributes[page_index]) { 477 switch (page_table.attributes[page_index]) {
447 case PageType::Unmapped: { 478 case PageType::Unmapped: {
448 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 479 NGLOG_ERROR(HW_Memory,
449 current_vaddr, src_addr, size); 480 "Unmapped ReadBlock @ {:#018X} (start address = {:#018X}, size = {})",
481 current_vaddr, src_addr, size);
450 std::memset(dest_buffer, 0, copy_amount); 482 std::memset(dest_buffer, 0, copy_amount);
451 break; 483 break;
452 } 484 }
@@ -508,9 +540,9 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
508 540
509 switch (page_table.attributes[page_index]) { 541 switch (page_table.attributes[page_index]) {
510 case PageType::Unmapped: { 542 case PageType::Unmapped: {
511 LOG_ERROR(HW_Memory, 543 NGLOG_ERROR(HW_Memory,
512 "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 544 "Unmapped WriteBlock @ {:#018X} (start address = {:#018X}, size = {})",
513 current_vaddr, dest_addr, size); 545 current_vaddr, dest_addr, size);
514 break; 546 break;
515 } 547 }
516 case PageType::Memory: { 548 case PageType::Memory: {
@@ -556,8 +588,9 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const size
556 588
557 switch (page_table.attributes[page_index]) { 589 switch (page_table.attributes[page_index]) {
558 case PageType::Unmapped: { 590 case PageType::Unmapped: {
559 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 591 NGLOG_ERROR(HW_Memory,
560 current_vaddr, dest_addr, size); 592 "Unmapped ZeroBlock @ {:#018X} (start address = {#:018X}, size = {})",
593 current_vaddr, dest_addr, size);
561 break; 594 break;
562 } 595 }
563 case PageType::Memory: { 596 case PageType::Memory: {
@@ -596,8 +629,9 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
596 629
597 switch (page_table.attributes[page_index]) { 630 switch (page_table.attributes[page_index]) {
598 case PageType::Unmapped: { 631 case PageType::Unmapped: {
599 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 632 NGLOG_ERROR(HW_Memory,
600 current_vaddr, src_addr, size); 633 "Unmapped CopyBlock @ {:#018X} (start address = {:#018X}, size = {})",
634 current_vaddr, src_addr, size);
601 ZeroBlock(process, dest_addr, copy_amount); 635 ZeroBlock(process, dest_addr, copy_amount);
602 break; 636 break;
603 } 637 }
@@ -625,6 +659,10 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
625 } 659 }
626} 660}
627 661
662void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) {
663 CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size);
664}
665
628boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { 666boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
629 if (addr == 0) { 667 if (addr == 0) {
630 return 0; 668 return 0;
@@ -646,7 +684,7 @@ boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
646PAddr VirtualToPhysicalAddress(const VAddr addr) { 684PAddr VirtualToPhysicalAddress(const VAddr addr) {
647 auto paddr = TryVirtualToPhysicalAddress(addr); 685 auto paddr = TryVirtualToPhysicalAddress(addr);
648 if (!paddr) { 686 if (!paddr) {
649 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%016" PRIX64, addr); 687 NGLOG_ERROR(HW_Memory, "Unknown virtual address @ {:#018X}", addr);
650 // To help with debugging, set bit on address so that it's obviously invalid. 688 // To help with debugging, set bit on address so that it's obviously invalid.
651 return addr | 0x80000000; 689 return addr | 0x80000000;
652 } 690 }
diff --git a/src/core/memory.h b/src/core/memory.h
index e9b8ca873..3f56a2c6a 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -14,6 +14,7 @@
14#include <boost/optional.hpp> 14#include <boost/optional.hpp>
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "core/memory_hook.h" 16#include "core/memory_hook.h"
17#include "video_core/memory_manager.h"
17 18
18namespace Kernel { 19namespace Kernel {
19class Process; 20class Process;
@@ -258,7 +259,7 @@ enum class FlushMode {
258/** 259/**
259 * Mark each page touching the region as cached. 260 * Mark each page touching the region as cached.
260 */ 261 */
261void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached); 262void RasterizerMarkRegionCached(Tegra::GPUVAddr start, u64 size, bool cached);
262 263
263/** 264/**
264 * Flushes and invalidates any externally cached rasterizer resources touching the given virtual 265 * Flushes and invalidates any externally cached rasterizer resources touching the given virtual
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index d4cdb4ab2..2eaece298 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -24,41 +24,18 @@ namespace Tegra {
24 24
25enum class BufferMethods { 25enum class BufferMethods {
26 BindObject = 0, 26 BindObject = 0,
27 SetGraphMacroCode = 0x45, 27 CountBufferMethods = 0x40,
28 SetGraphMacroCodeArg = 0x46,
29 SetGraphMacroEntry = 0x47,
30 CountBufferMethods = 0x100,
31}; 28};
32 29
33void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) { 30void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) {
34 LOG_WARNING(HW_GPU, "Processing method %08X on subchannel %u value %08X remaining params %u", 31 NGLOG_WARNING(HW_GPU,
35 method, subchannel, value, remaining_params); 32 "Processing method {:08X} on subchannel {} value "
36 33 "{:08X} remaining params {}",
37 if (method == static_cast<u32>(BufferMethods::SetGraphMacroEntry)) { 34 method, subchannel, value, remaining_params);
38 // Prepare to upload a new macro, reset the upload counter.
39 LOG_DEBUG(HW_GPU, "Uploading GPU macro %08X", value);
40 current_macro_entry = value;
41 current_macro_code.clear();
42 return;
43 }
44
45 if (method == static_cast<u32>(BufferMethods::SetGraphMacroCodeArg)) {
46 // Append a new code word to the current macro.
47 current_macro_code.push_back(value);
48
49 // There are no more params remaining, submit the code to the 3D engine.
50 if (remaining_params == 0) {
51 maxwell_3d->SubmitMacroCode(current_macro_entry, std::move(current_macro_code));
52 current_macro_entry = InvalidGraphMacroEntry;
53 current_macro_code.clear();
54 }
55
56 return;
57 }
58 35
59 if (method == static_cast<u32>(BufferMethods::BindObject)) { 36 if (method == static_cast<u32>(BufferMethods::BindObject)) {
60 // Bind the current subchannel to the desired engine id. 37 // Bind the current subchannel to the desired engine id.
61 LOG_DEBUG(HW_GPU, "Binding subchannel %u to engine %u", subchannel, value); 38 NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
62 ASSERT(bound_engines.find(subchannel) == bound_engines.end()); 39 ASSERT(bound_engines.find(subchannel) == bound_engines.end());
63 bound_engines[subchannel] = static_cast<EngineID>(value); 40 bound_engines[subchannel] = static_cast<EngineID>(value);
64 return; 41 return;
@@ -66,7 +43,7 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
66 43
67 if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) { 44 if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
68 // TODO(Subv): Research and implement these methods. 45 // TODO(Subv): Research and implement these methods.
69 LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); 46 NGLOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
70 return; 47 return;
71 } 48 }
72 49
@@ -90,11 +67,9 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
90} 67}
91 68
92void GPU::ProcessCommandList(GPUVAddr address, u32 size) { 69void GPU::ProcessCommandList(GPUVAddr address, u32 size) {
93 // TODO(Subv): PhysicalToVirtualAddress is a misnomer, it converts a GPU VAddr into an 70 const boost::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address);
94 // application VAddr. 71 VAddr current_addr = *head_address;
95 const VAddr head_address = memory_manager->PhysicalToVirtualAddress(address); 72 while (current_addr < *head_address + size * sizeof(CommandHeader)) {
96 VAddr current_addr = head_address;
97 while (current_addr < head_address + size * sizeof(CommandHeader)) {
98 const CommandHeader header = {Memory::Read32(current_addr)}; 73 const CommandHeader header = {Memory::Read32(current_addr)};
99 current_addr += sizeof(u32); 74 current_addr += sizeof(u32);
100 75
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 7aab163dc..9019f2504 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -2,12 +2,71 @@
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 "core/memory.h"
5#include "video_core/engines/fermi_2d.h" 6#include "video_core/engines/fermi_2d.h"
7#include "video_core/textures/decoders.h"
6 8
7namespace Tegra { 9namespace Tegra {
8namespace Engines { 10namespace Engines {
9 11
10void Fermi2D::WriteReg(u32 method, u32 value) {} 12Fermi2D::Fermi2D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
13
14void Fermi2D::WriteReg(u32 method, u32 value) {
15 ASSERT_MSG(method < Regs::NUM_REGS,
16 "Invalid Fermi2D register, increase the size of the Regs structure");
17
18 regs.reg_array[method] = value;
19
20 switch (method) {
21 case FERMI2D_REG_INDEX(trigger): {
22 HandleSurfaceCopy();
23 break;
24 }
25 }
26}
27
28void Fermi2D::HandleSurfaceCopy() {
29 NGLOG_WARNING(HW_GPU, "Requested a surface copy with operation {}",
30 static_cast<u32>(regs.operation));
31
32 const GPUVAddr source = regs.src.Address();
33 const GPUVAddr dest = regs.dst.Address();
34
35 // TODO(Subv): Only same-format and same-size copies are allowed for now.
36 ASSERT(regs.src.format == regs.dst.format);
37 ASSERT(regs.src.width * regs.src.height == regs.dst.width * regs.dst.height);
38
39 // TODO(Subv): Only raw copies are implemented.
40 ASSERT(regs.operation == Regs::Operation::SrcCopy);
41
42 const VAddr source_cpu = *memory_manager.GpuToCpuAddress(source);
43 const VAddr dest_cpu = *memory_manager.GpuToCpuAddress(dest);
44
45 u32 src_bytes_per_pixel = RenderTargetBytesPerPixel(regs.src.format);
46 u32 dst_bytes_per_pixel = RenderTargetBytesPerPixel(regs.dst.format);
47
48 if (regs.src.linear == regs.dst.linear) {
49 // If the input layout and the output layout are the same, just perform a raw copy.
50 Memory::CopyBlock(dest_cpu, source_cpu,
51 src_bytes_per_pixel * regs.dst.width * regs.dst.height);
52 return;
53 }
54
55 u8* src_buffer = Memory::GetPointer(source_cpu);
56 u8* dst_buffer = Memory::GetPointer(dest_cpu);
57
58 if (!regs.src.linear && regs.dst.linear) {
59 // If the input is tiled and the output is linear, deswizzle the input and copy it over.
60 Texture::CopySwizzledData(regs.src.width, regs.src.height, src_bytes_per_pixel,
61 dst_bytes_per_pixel, src_buffer, dst_buffer, true,
62 regs.src.block_height);
63 } else {
64 // If the input is linear and the output is tiled, swizzle the input and copy it over.
65 Texture::CopySwizzledData(regs.src.width, regs.src.height, src_bytes_per_pixel,
66 dst_bytes_per_pixel, dst_buffer, src_buffer, false,
67 regs.dst.block_height);
68 }
69}
11 70
12} // namespace Engines 71} // namespace Engines
13} // namespace Tegra 72} // namespace Tegra
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 8967ddede..0c5b413cc 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -4,19 +4,106 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
8#include "common/assert.h"
9#include "common/bit_field.h"
10#include "common/common_funcs.h"
7#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h"
8 14
9namespace Tegra { 15namespace Tegra {
10namespace Engines { 16namespace Engines {
11 17
18#define FERMI2D_REG_INDEX(field_name) \
19 (offsetof(Tegra::Engines::Fermi2D::Regs, field_name) / sizeof(u32))
20
12class Fermi2D final { 21class Fermi2D final {
13public: 22public:
14 Fermi2D() = default; 23 explicit Fermi2D(MemoryManager& memory_manager);
15 ~Fermi2D() = default; 24 ~Fermi2D() = default;
16 25
17 /// Write the value to the register identified by method. 26 /// Write the value to the register identified by method.
18 void WriteReg(u32 method, u32 value); 27 void WriteReg(u32 method, u32 value);
28
29 struct Regs {
30 static constexpr size_t NUM_REGS = 0x258;
31
32 struct Surface {
33 RenderTargetFormat format;
34 BitField<0, 1, u32> linear;
35 union {
36 BitField<0, 4, u32> block_depth;
37 BitField<4, 4, u32> block_height;
38 BitField<8, 4, u32> block_width;
39 };
40 u32 depth;
41 u32 layer;
42 u32 pitch;
43 u32 width;
44 u32 height;
45 u32 address_high;
46 u32 address_low;
47
48 GPUVAddr Address() const {
49 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
50 address_low);
51 }
52 };
53 static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size");
54
55 enum class Operation : u32 {
56 SrcCopyAnd = 0,
57 ROPAnd = 1,
58 Blend = 2,
59 SrcCopy = 3,
60 ROP = 4,
61 SrcCopyPremult = 5,
62 BlendPremult = 6,
63 };
64
65 union {
66 struct {
67 INSERT_PADDING_WORDS(0x80);
68
69 Surface dst;
70
71 INSERT_PADDING_WORDS(2);
72
73 Surface src;
74
75 INSERT_PADDING_WORDS(0x15);
76
77 Operation operation;
78
79 INSERT_PADDING_WORDS(0x9);
80
81 // TODO(Subv): This is only a guess.
82 u32 trigger;
83
84 INSERT_PADDING_WORDS(0x1A3);
85 };
86 std::array<u32, NUM_REGS> reg_array;
87 };
88 } regs{};
89
90 MemoryManager& memory_manager;
91
92private:
93 /// Performs the copy from the source surface to the destination surface as configured in the
94 /// registers.
95 void HandleSurfaceCopy();
19}; 96};
20 97
98#define ASSERT_REG_POSITION(field_name, position) \
99 static_assert(offsetof(Fermi2D::Regs, field_name) == position * 4, \
100 "Field " #field_name " has invalid position")
101
102ASSERT_REG_POSITION(dst, 0x80);
103ASSERT_REG_POSITION(src, 0x8C);
104ASSERT_REG_POSITION(operation, 0xAB);
105ASSERT_REG_POSITION(trigger, 0xB5);
106#undef ASSERT_REG_POSITION
107
21} // namespace Engines 108} // namespace Engines
22} // namespace Tegra 109} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 2a3ff234a..4306b894f 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -22,10 +22,6 @@ constexpr u32 MacroRegistersStart = 0xE00;
22Maxwell3D::Maxwell3D(MemoryManager& memory_manager) 22Maxwell3D::Maxwell3D(MemoryManager& memory_manager)
23 : memory_manager(memory_manager), macro_interpreter(*this) {} 23 : memory_manager(memory_manager), macro_interpreter(*this) {}
24 24
25void Maxwell3D::SubmitMacroCode(u32 entry, std::vector<u32> code) {
26 uploaded_macros[entry * 2 + MacroRegistersStart] = std::move(code);
27}
28
29void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { 25void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
30 auto macro_code = uploaded_macros.find(method); 26 auto macro_code = uploaded_macros.find(method);
31 // The requested macro must have been uploaded already. 27 // The requested macro must have been uploaded already.
@@ -37,9 +33,6 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
37} 33}
38 34
39void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) { 35void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
40 ASSERT_MSG(method < Regs::NUM_REGS,
41 "Invalid Maxwell3D register, increase the size of the Regs structure");
42
43 auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); 36 auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
44 37
45 // It is an error to write to a register other than the current macro's ARG register before it 38 // It is an error to write to a register other than the current macro's ARG register before it
@@ -68,6 +61,9 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
68 return; 61 return;
69 } 62 }
70 63
64 ASSERT_MSG(method < Regs::NUM_REGS,
65 "Invalid Maxwell3D register, increase the size of the Regs structure");
66
71 if (debug_context) { 67 if (debug_context) {
72 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); 68 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
73 } 69 }
@@ -75,6 +71,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
75 regs.reg_array[method] = value; 71 regs.reg_array[method] = value;
76 72
77 switch (method) { 73 switch (method) {
74 case MAXWELL3D_REG_INDEX(macros.data): {
75 ProcessMacroUpload(value);
76 break;
77 }
78 case MAXWELL3D_REG_INDEX(code_address.code_address_high): 78 case MAXWELL3D_REG_INDEX(code_address.code_address_high):
79 case MAXWELL3D_REG_INDEX(code_address.code_address_low): { 79 case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
80 // Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS 80 // Note: For some reason games (like Puyo Puyo Tetris) seem to write 0 to the CODE_ADDRESS
@@ -141,17 +141,48 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
141 } 141 }
142} 142}
143 143
144void Maxwell3D::ProcessMacroUpload(u32 data) {
145 // Store the uploaded macro code to interpret them when they're called.
146 auto& macro = uploaded_macros[regs.macros.entry * 2 + MacroRegistersStart];
147 macro.push_back(data);
148}
149
144void Maxwell3D::ProcessQueryGet() { 150void Maxwell3D::ProcessQueryGet() {
145 GPUVAddr sequence_address = regs.query.QueryAddress(); 151 GPUVAddr sequence_address = regs.query.QueryAddress();
146 // Since the sequence address is given as a GPU VAddr, we have to convert it to an application 152 // Since the sequence address is given as a GPU VAddr, we have to convert it to an application
147 // VAddr before writing. 153 // VAddr before writing.
148 VAddr address = memory_manager.PhysicalToVirtualAddress(sequence_address); 154 boost::optional<VAddr> address = memory_manager.GpuToCpuAddress(sequence_address);
155
156 // TODO(Subv): Support the other query units.
157 ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,
158 "Units other than CROP are unimplemented");
159 ASSERT_MSG(regs.query.query_get.short_query,
160 "Writing the entire query result structure is unimplemented");
161
162 u32 value = Memory::Read32(*address);
163 u32 result = 0;
164
165 // TODO(Subv): Support the other query variables
166 switch (regs.query.query_get.select) {
167 case Regs::QuerySelect::Zero:
168 result = 0;
169 break;
170 default:
171 UNIMPLEMENTED_MSG("Unimplemented query select type %u",
172 static_cast<u32>(regs.query.query_get.select.Value()));
173 }
174
175 // TODO(Subv): Research and implement how query sync conditions work.
149 176
150 switch (regs.query.query_get.mode) { 177 switch (regs.query.query_get.mode) {
151 case Regs::QueryMode::Write: { 178 case Regs::QueryMode::Write:
179 case Regs::QueryMode::Write2: {
152 // Write the current query sequence to the sequence address. 180 // Write the current query sequence to the sequence address.
153 u32 sequence = regs.query.query_sequence; 181 u32 sequence = regs.query.query_sequence;
154 Memory::Write32(address, sequence); 182 Memory::Write32(*address, sequence);
183
184 // TODO(Subv): Write the proper query response structure to the address when not using short
185 // mode.
155 break; 186 break;
156 } 187 }
157 default: 188 default:
@@ -161,8 +192,8 @@ void Maxwell3D::ProcessQueryGet() {
161} 192}
162 193
163void Maxwell3D::DrawArrays() { 194void Maxwell3D::DrawArrays() {
164 LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(), 195 NGLOG_DEBUG(HW_GPU, "called, topology={}, count={}",
165 regs.vertex_buffer.count); 196 static_cast<u32>(regs.draw.topology.Value()), regs.vertex_buffer.count);
166 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?"); 197 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
167 198
168 auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); 199 auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
@@ -200,10 +231,10 @@ void Maxwell3D::ProcessCBData(u32 value) {
200 // Don't allow writing past the end of the buffer. 231 // Don't allow writing past the end of the buffer.
201 ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size); 232 ASSERT(regs.const_buffer.cb_pos + sizeof(u32) <= regs.const_buffer.cb_size);
202 233
203 VAddr address = 234 boost::optional<VAddr> address =
204 memory_manager.PhysicalToVirtualAddress(buffer_address + regs.const_buffer.cb_pos); 235 memory_manager.GpuToCpuAddress(buffer_address + regs.const_buffer.cb_pos);
205 236
206 Memory::Write32(address, value); 237 Memory::Write32(*address, value);
207 238
208 // Increment the current buffer position. 239 // Increment the current buffer position.
209 regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4; 240 regs.const_buffer.cb_pos = regs.const_buffer.cb_pos + 4;
@@ -213,10 +244,10 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
213 GPUVAddr tic_base_address = regs.tic.TICAddress(); 244 GPUVAddr tic_base_address = regs.tic.TICAddress();
214 245
215 GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry); 246 GPUVAddr tic_address_gpu = tic_base_address + tic_index * sizeof(Texture::TICEntry);
216 VAddr tic_address_cpu = memory_manager.PhysicalToVirtualAddress(tic_address_gpu); 247 boost::optional<VAddr> tic_address_cpu = memory_manager.GpuToCpuAddress(tic_address_gpu);
217 248
218 Texture::TICEntry tic_entry; 249 Texture::TICEntry tic_entry;
219 Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); 250 Memory::ReadBlock(*tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
220 251
221 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear || 252 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear ||
222 tic_entry.header_version == Texture::TICHeaderVersion::Pitch, 253 tic_entry.header_version == Texture::TICHeaderVersion::Pitch,
@@ -243,10 +274,10 @@ Texture::TSCEntry Maxwell3D::GetTSCEntry(u32 tsc_index) const {
243 GPUVAddr tsc_base_address = regs.tsc.TSCAddress(); 274 GPUVAddr tsc_base_address = regs.tsc.TSCAddress();
244 275
245 GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry); 276 GPUVAddr tsc_address_gpu = tsc_base_address + tsc_index * sizeof(Texture::TSCEntry);
246 VAddr tsc_address_cpu = memory_manager.PhysicalToVirtualAddress(tsc_address_gpu); 277 boost::optional<VAddr> tsc_address_cpu = memory_manager.GpuToCpuAddress(tsc_address_gpu);
247 278
248 Texture::TSCEntry tsc_entry; 279 Texture::TSCEntry tsc_entry;
249 Memory::ReadBlock(tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry)); 280 Memory::ReadBlock(*tsc_address_cpu, &tsc_entry, sizeof(Texture::TSCEntry));
250 return tsc_entry; 281 return tsc_entry;
251} 282}
252 283
@@ -268,7 +299,7 @@ std::vector<Texture::FullTextureInfo> Maxwell3D::GetStageTextures(Regs::ShaderSt
268 current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) { 299 current_texture < tex_info_buffer_end; current_texture += sizeof(Texture::TextureHandle)) {
269 300
270 Texture::TextureHandle tex_handle{ 301 Texture::TextureHandle tex_handle{
271 Memory::Read32(memory_manager.PhysicalToVirtualAddress(current_texture))}; 302 Memory::Read32(*memory_manager.GpuToCpuAddress(current_texture))};
272 303
273 Texture::FullTextureInfo tex_info{}; 304 Texture::FullTextureInfo tex_info{};
274 // TODO(Subv): Use the shader to determine which textures are actually accessed. 305 // TODO(Subv): Use the shader to determine which textures are actually accessed.
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index d4fcedace..5cf62fb01 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -31,7 +31,7 @@ public:
31 /// Register structure of the Maxwell3D engine. 31 /// Register structure of the Maxwell3D engine.
32 /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. 32 /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
33 struct Regs { 33 struct Regs {
34 static constexpr size_t NUM_REGS = 0xE36; 34 static constexpr size_t NUM_REGS = 0xE00;
35 35
36 static constexpr size_t NumRenderTargets = 8; 36 static constexpr size_t NumRenderTargets = 8;
37 static constexpr size_t NumViewports = 16; 37 static constexpr size_t NumViewports = 16;
@@ -46,6 +46,29 @@ public:
46 enum class QueryMode : u32 { 46 enum class QueryMode : u32 {
47 Write = 0, 47 Write = 0,
48 Sync = 1, 48 Sync = 1,
49 // TODO(Subv): It is currently unknown what the difference between method 2 and method 0
50 // is.
51 Write2 = 2,
52 };
53
54 enum class QueryUnit : u32 {
55 VFetch = 1,
56 VP = 2,
57 Rast = 4,
58 StrmOut = 5,
59 GP = 6,
60 ZCull = 7,
61 Prop = 10,
62 Crop = 15,
63 };
64
65 enum class QuerySelect : u32 {
66 Zero = 0,
67 };
68
69 enum class QuerySyncCondition : u32 {
70 NotEqual = 0,
71 GreaterThan = 1,
49 }; 72 };
50 73
51 enum class ShaderProgram : u32 { 74 enum class ShaderProgram : u32 {
@@ -299,7 +322,15 @@ public:
299 322
300 union { 323 union {
301 struct { 324 struct {
302 INSERT_PADDING_WORDS(0x200); 325 INSERT_PADDING_WORDS(0x45);
326
327 struct {
328 INSERT_PADDING_WORDS(1);
329 u32 data;
330 u32 entry;
331 } macros;
332
333 INSERT_PADDING_WORDS(0x1B8);
303 334
304 struct { 335 struct {
305 u32 address_high; 336 u32 address_high;
@@ -476,7 +507,10 @@ public:
476 u32 raw; 507 u32 raw;
477 BitField<0, 2, QueryMode> mode; 508 BitField<0, 2, QueryMode> mode;
478 BitField<4, 1, u32> fence; 509 BitField<4, 1, u32> fence;
479 BitField<12, 4, u32> unit; 510 BitField<12, 4, QueryUnit> unit;
511 BitField<16, 1, QuerySyncCondition> sync_cond;
512 BitField<23, 5, QuerySelect> select;
513 BitField<28, 1, u32> short_query;
480 } query_get; 514 } query_get;
481 515
482 GPUVAddr QueryAddress() const { 516 GPUVAddr QueryAddress() const {
@@ -500,6 +534,11 @@ public:
500 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) | 534 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) |
501 start_low); 535 start_low);
502 } 536 }
537
538 bool IsEnabled() const {
539 return enable != 0 && StartAddress() != 0;
540 }
541
503 } vertex_array[NumVertexArrays]; 542 } vertex_array[NumVertexArrays];
504 543
505 Blend blend; 544 Blend blend;
@@ -574,7 +613,7 @@ public:
574 u32 size[MaxShaderStage]; 613 u32 size[MaxShaderStage];
575 } tex_info_buffers; 614 } tex_info_buffers;
576 615
577 INSERT_PADDING_WORDS(0x102); 616 INSERT_PADDING_WORDS(0xCC);
578 }; 617 };
579 std::array<u32, NUM_REGS> reg_array; 618 std::array<u32, NUM_REGS> reg_array;
580 }; 619 };
@@ -606,9 +645,6 @@ public:
606 /// Write the value to the register identified by method. 645 /// Write the value to the register identified by method.
607 void WriteReg(u32 method, u32 value, u32 remaining_params); 646 void WriteReg(u32 method, u32 value, u32 remaining_params);
608 647
609 /// Uploads the code for a GPU macro program associated with the specified entry.
610 void SubmitMacroCode(u32 entry, std::vector<u32> code);
611
612 /// Returns a list of enabled textures for the specified shader stage. 648 /// Returns a list of enabled textures for the specified shader stage.
613 std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; 649 std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
614 650
@@ -639,6 +675,9 @@ private:
639 */ 675 */
640 void CallMacroMethod(u32 method, std::vector<u32> parameters); 676 void CallMacroMethod(u32 method, std::vector<u32> parameters);
641 677
678 /// Handles writes to the macro uploading registers.
679 void ProcessMacroUpload(u32 data);
680
642 /// Handles a write to the QUERY_GET register. 681 /// Handles a write to the QUERY_GET register.
643 void ProcessQueryGet(); 682 void ProcessQueryGet();
644 683
@@ -656,6 +695,7 @@ private:
656 static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \ 695 static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
657 "Field " #field_name " has invalid position") 696 "Field " #field_name " has invalid position")
658 697
698ASSERT_REG_POSITION(macros, 0x45);
659ASSERT_REG_POSITION(rt, 0x200); 699ASSERT_REG_POSITION(rt, 0x200);
660ASSERT_REG_POSITION(viewport_transform[0], 0x280); 700ASSERT_REG_POSITION(viewport_transform[0], 0x280);
661ASSERT_REG_POSITION(viewport, 0x300); 701ASSERT_REG_POSITION(viewport, 0x300);
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 5a006aee5..f4d11fa5d 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -214,6 +214,20 @@ union Instruction {
214 BitField<56, 1, u64> neg_b; 214 BitField<56, 1, u64> neg_b;
215 } fsetp; 215 } fsetp;
216 216
217 union {
218 BitField<39, 3, u64> pred39;
219 BitField<42, 1, u64> neg_pred;
220 BitField<43, 1, u64> neg_a;
221 BitField<44, 1, u64> abs_b;
222 BitField<45, 2, PredOperation> op;
223 BitField<48, 4, PredCondition> cond;
224 BitField<53, 1, u64> neg_b;
225 BitField<54, 1, u64> abs_a;
226 BitField<52, 1, u64> bf;
227 BitField<55, 1, u64> ftz;
228 BitField<56, 1, u64> neg_imm;
229 } fset;
230
217 BitField<61, 1, u64> is_b_imm; 231 BitField<61, 1, u64> is_b_imm;
218 BitField<60, 1, u64> is_b_gpr; 232 BitField<60, 1, u64> is_b_gpr;
219 BitField<59, 1, u64> is_c_gpr; 233 BitField<59, 1, u64> is_c_gpr;
@@ -261,6 +275,9 @@ public:
261 I2F_C, 275 I2F_C,
262 I2F_R, 276 I2F_R,
263 I2F_IMM, 277 I2F_IMM,
278 I2I_C,
279 I2I_R,
280 I2I_IMM,
264 LOP32I, 281 LOP32I,
265 MOV_C, 282 MOV_C,
266 MOV_R, 283 MOV_R,
@@ -272,6 +289,9 @@ public:
272 FSETP_C, // Set Predicate 289 FSETP_C, // Set Predicate
273 FSETP_R, 290 FSETP_R,
274 FSETP_IMM, 291 FSETP_IMM,
292 FSET_C,
293 FSET_R,
294 FSET_IMM,
275 ISETP_C, 295 ISETP_C,
276 ISETP_IMM, 296 ISETP_IMM,
277 ISETP_R, 297 ISETP_R,
@@ -283,8 +303,9 @@ public:
283 Ffma, 303 Ffma,
284 Flow, 304 Flow,
285 Memory, 305 Memory,
286 FloatPredicate, 306 FloatSet,
287 IntegerPredicate, 307 FloatSetPredicate,
308 IntegerSetPredicate,
288 Unknown, 309 Unknown,
289 }; 310 };
290 311
@@ -409,6 +430,9 @@ private:
409 INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"), 430 INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"),
410 INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"), 431 INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"),
411 INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"), 432 INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"),
433 INST("0100110011100---", Id::I2I_C, Type::Arithmetic, "I2I_C"),
434 INST("0101110011100---", Id::I2I_R, Type::Arithmetic, "I2I_R"),
435 INST("01110001-1000---", Id::I2I_IMM, Type::Arithmetic, "I2I_IMM"),
412 INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), 436 INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
413 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), 437 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
414 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), 438 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
@@ -417,12 +441,15 @@ private:
417 INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"), 441 INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
418 INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"), 442 INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
419 INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"), 443 INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
420 INST("010010111011----", Id::FSETP_C, Type::FloatPredicate, "FSETP_C"), 444 INST("01011000--------", Id::FSET_R, Type::FloatSet, "FSET_R"),
421 INST("010110111011----", Id::FSETP_R, Type::FloatPredicate, "FSETP_R"), 445 INST("0100100---------", Id::FSET_C, Type::FloatSet, "FSET_C"),
422 INST("0011011-1011----", Id::FSETP_IMM, Type::FloatPredicate, "FSETP_IMM"), 446 INST("0011000---------", Id::FSET_IMM, Type::FloatSet, "FSET_IMM"),
423 INST("010010110110----", Id::ISETP_C, Type::IntegerPredicate, "ISETP_C"), 447 INST("010010111011----", Id::FSETP_C, Type::FloatSetPredicate, "FSETP_C"),
424 INST("010110110110----", Id::ISETP_R, Type::IntegerPredicate, "ISETP_R"), 448 INST("010110111011----", Id::FSETP_R, Type::FloatSetPredicate, "FSETP_R"),
425 INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerPredicate, "ISETP_IMM"), 449 INST("0011011-1011----", Id::FSETP_IMM, Type::FloatSetPredicate, "FSETP_IMM"),
450 INST("010010110110----", Id::ISETP_C, Type::IntegerSetPredicate, "ISETP_C"),
451 INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"),
452 INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"),
426 }; 453 };
427#undef INST 454#undef INST
428 std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { 455 std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 9463cd5d6..9eb143918 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -12,7 +12,7 @@ namespace Tegra {
12GPU::GPU() { 12GPU::GPU() {
13 memory_manager = std::make_unique<MemoryManager>(); 13 memory_manager = std::make_unique<MemoryManager>();
14 maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager); 14 maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager);
15 fermi_2d = std::make_unique<Engines::Fermi2D>(); 15 fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);
16 maxwell_compute = std::make_unique<Engines::MaxwellCompute>(); 16 maxwell_compute = std::make_unique<Engines::MaxwellCompute>();
17} 17}
18 18
@@ -22,4 +22,16 @@ const Tegra::Engines::Maxwell3D& GPU::Get3DEngine() const {
22 return *maxwell_3d; 22 return *maxwell_3d;
23} 23}
24 24
25u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
26 ASSERT(format != RenderTargetFormat::NONE);
27
28 switch (format) {
29 case RenderTargetFormat::RGBA8_UNORM:
30 case RenderTargetFormat::RGB10_A2_UNORM:
31 return 4;
32 default:
33 UNIMPLEMENTED_MSG("Unimplemented render target format %u", static_cast<u32>(format));
34 }
35}
36
25} // namespace Tegra 37} // namespace Tegra
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 2888daedc..f168a5171 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -21,6 +21,9 @@ enum class RenderTargetFormat : u32 {
21 RGBA8_SRGB = 0xD6, 21 RGBA8_SRGB = 0xD6,
22}; 22};
23 23
24/// Returns the number of bytes per pixel of each rendertarget format.
25u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
26
24class DebugContext; 27class DebugContext;
25 28
26/** 29/**
@@ -86,8 +89,6 @@ public:
86 } 89 }
87 90
88private: 91private:
89 static constexpr u32 InvalidGraphMacroEntry = 0xFFFFFFFF;
90
91 /// Writes a single register in the engine bound to the specified subchannel 92 /// Writes a single register in the engine bound to the specified subchannel
92 void WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params); 93 void WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params);
93 94
@@ -100,11 +101,6 @@ private:
100 std::unique_ptr<Engines::Fermi2D> fermi_2d; 101 std::unique_ptr<Engines::Fermi2D> fermi_2d;
101 /// Compute engine 102 /// Compute engine
102 std::unique_ptr<Engines::MaxwellCompute> maxwell_compute; 103 std::unique_ptr<Engines::MaxwellCompute> maxwell_compute;
103
104 /// Entry of the macro that is currently being uploaded
105 u32 current_macro_entry = InvalidGraphMacroEntry;
106 /// Code being uploaded for the current macro
107 std::vector<u32> current_macro_code;
108}; 104};
109 105
110} // namespace Tegra 106} // namespace Tegra
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 2789a4ca1..25984439d 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -2,109 +2,118 @@
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 "common/alignment.h"
5#include "common/assert.h" 6#include "common/assert.h"
6#include "video_core/memory_manager.h" 7#include "video_core/memory_manager.h"
7 8
8namespace Tegra { 9namespace Tegra {
9 10
10PAddr MemoryManager::AllocateSpace(u64 size, u64 align) { 11GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
11 boost::optional<PAddr> paddr = FindFreeBlock(size, align); 12 boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, align);
12 ASSERT(paddr); 13 ASSERT(gpu_addr);
13 14
14 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { 15 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
15 PageSlot(*paddr + offset) = static_cast<u64>(PageStatus::Allocated); 16 ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
17 PageSlot(*gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
16 } 18 }
17 19
18 return *paddr; 20 return *gpu_addr;
19} 21}
20 22
21PAddr MemoryManager::AllocateSpace(PAddr paddr, u64 size, u64 align) { 23GPUVAddr MemoryManager::AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align) {
22 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { 24 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
23 if (IsPageMapped(paddr + offset)) { 25 ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
24 return AllocateSpace(size, align); 26 PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Allocated);
25 }
26 }
27
28 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) {
29 PageSlot(paddr + offset) = static_cast<u64>(PageStatus::Allocated);
30 } 27 }
31 28
32 return paddr; 29 return gpu_addr;
33} 30}
34 31
35PAddr MemoryManager::MapBufferEx(VAddr vaddr, u64 size) { 32GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, u64 size) {
36 vaddr &= ~Memory::PAGE_MASK; 33 boost::optional<GPUVAddr> gpu_addr = FindFreeBlock(size, PAGE_SIZE);
37 34 ASSERT(gpu_addr);
38 boost::optional<PAddr> paddr = FindFreeBlock(size);
39 ASSERT(paddr);
40 35
41 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { 36 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
42 PageSlot(*paddr + offset) = vaddr + offset; 37 ASSERT(PageSlot(*gpu_addr + offset) == static_cast<u64>(PageStatus::Unmapped));
38 PageSlot(*gpu_addr + offset) = cpu_addr + offset;
43 } 39 }
44 40
45 return *paddr; 41 MappedRegion region{cpu_addr, *gpu_addr, size};
42 mapped_regions.push_back(region);
43
44 return *gpu_addr;
46} 45}
47 46
48PAddr MemoryManager::MapBufferEx(VAddr vaddr, PAddr paddr, u64 size) { 47GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size) {
49 vaddr &= ~Memory::PAGE_MASK; 48 ASSERT((gpu_addr & PAGE_MASK) == 0);
50 paddr &= ~Memory::PAGE_MASK;
51 49
52 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { 50 for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
53 if (PageSlot(paddr + offset) != static_cast<u64>(PageStatus::Allocated)) { 51 ASSERT(PageSlot(gpu_addr + offset) == static_cast<u64>(PageStatus::Allocated));
54 return MapBufferEx(vaddr, size); 52 PageSlot(gpu_addr + offset) = cpu_addr + offset;
55 }
56 } 53 }
57 54
58 for (u64 offset = 0; offset < size; offset += Memory::PAGE_SIZE) { 55 MappedRegion region{cpu_addr, gpu_addr, size};
59 PageSlot(paddr + offset) = vaddr + offset; 56 mapped_regions.push_back(region);
60 }
61 57
62 return paddr; 58 return gpu_addr;
63} 59}
64 60
65boost::optional<PAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) { 61boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
66 PAddr paddr{}; 62 GPUVAddr gpu_addr = 0;
67 u64 free_space{}; 63 u64 free_space = 0;
68 align = (align + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; 64 align = (align + PAGE_MASK) & ~PAGE_MASK;
69 65
70 while (paddr + free_space < MAX_ADDRESS) { 66 while (gpu_addr + free_space < MAX_ADDRESS) {
71 if (!IsPageMapped(paddr + free_space)) { 67 if (!IsPageMapped(gpu_addr + free_space)) {
72 free_space += Memory::PAGE_SIZE; 68 free_space += PAGE_SIZE;
73 if (free_space >= size) { 69 if (free_space >= size) {
74 return paddr; 70 return gpu_addr;
75 } 71 }
76 } else { 72 } else {
77 paddr += free_space + Memory::PAGE_SIZE; 73 gpu_addr += free_space + PAGE_SIZE;
78 free_space = 0; 74 free_space = 0;
79 const u64 remainder{paddr % align}; 75 gpu_addr = Common::AlignUp(gpu_addr, align);
80 if (!remainder) {
81 paddr = (paddr - remainder) + align;
82 }
83 } 76 }
84 } 77 }
85 78
86 return {}; 79 return {};
87} 80}
88 81
89VAddr MemoryManager::PhysicalToVirtualAddress(PAddr paddr) { 82boost::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) {
90 VAddr base_addr = PageSlot(paddr); 83 VAddr base_addr = PageSlot(gpu_addr);
91 ASSERT(base_addr != static_cast<u64>(PageStatus::Unmapped)); 84 ASSERT(base_addr != static_cast<u64>(PageStatus::Unmapped));
92 return base_addr + (paddr & Memory::PAGE_MASK); 85
86 if (base_addr == static_cast<u64>(PageStatus::Allocated)) {
87 return {};
88 }
89
90 return base_addr + (gpu_addr & PAGE_MASK);
91}
92
93std::vector<GPUVAddr> MemoryManager::CpuToGpuAddress(VAddr cpu_addr) const {
94 std::vector<GPUVAddr> results;
95 for (const auto& region : mapped_regions) {
96 if (cpu_addr >= region.cpu_addr && cpu_addr < (region.cpu_addr + region.size)) {
97 u64 offset = cpu_addr - region.cpu_addr;
98 results.push_back(region.gpu_addr + offset);
99 }
100 }
101 return results;
93} 102}
94 103
95bool MemoryManager::IsPageMapped(PAddr paddr) { 104bool MemoryManager::IsPageMapped(GPUVAddr gpu_addr) {
96 return PageSlot(paddr) != static_cast<u64>(PageStatus::Unmapped); 105 return PageSlot(gpu_addr) != static_cast<u64>(PageStatus::Unmapped);
97} 106}
98 107
99VAddr& MemoryManager::PageSlot(PAddr paddr) { 108VAddr& MemoryManager::PageSlot(GPUVAddr gpu_addr) {
100 auto& block = page_table[(paddr >> (Memory::PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK]; 109 auto& block = page_table[(gpu_addr >> (PAGE_BITS + PAGE_TABLE_BITS)) & PAGE_TABLE_MASK];
101 if (!block) { 110 if (!block) {
102 block = std::make_unique<PageBlock>(); 111 block = std::make_unique<PageBlock>();
103 for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) { 112 for (unsigned index = 0; index < PAGE_BLOCK_SIZE; index++) {
104 (*block)[index] = static_cast<u64>(PageStatus::Unmapped); 113 (*block)[index] = static_cast<u64>(PageStatus::Unmapped);
105 } 114 }
106 } 115 }
107 return (*block)[(paddr >> Memory::PAGE_BITS) & PAGE_BLOCK_MASK]; 116 return (*block)[(gpu_addr >> PAGE_BITS) & PAGE_BLOCK_MASK];
108} 117}
109 118
110} // namespace Tegra 119} // namespace Tegra
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 47da7acd6..08140c83a 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -6,8 +6,11 @@
6 6
7#include <array> 7#include <array>
8#include <memory> 8#include <memory>
9#include <vector>
10
11#include <boost/optional.hpp>
12
9#include "common/common_types.h" 13#include "common/common_types.h"
10#include "core/memory.h"
11 14
12namespace Tegra { 15namespace Tegra {
13 16
@@ -18,16 +21,21 @@ class MemoryManager final {
18public: 21public:
19 MemoryManager() = default; 22 MemoryManager() = default;
20 23
21 PAddr AllocateSpace(u64 size, u64 align); 24 GPUVAddr AllocateSpace(u64 size, u64 align);
22 PAddr AllocateSpace(PAddr paddr, u64 size, u64 align); 25 GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align);
23 PAddr MapBufferEx(VAddr vaddr, u64 size); 26 GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size);
24 PAddr MapBufferEx(VAddr vaddr, PAddr paddr, u64 size); 27 GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
25 VAddr PhysicalToVirtualAddress(PAddr paddr); 28 boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
29 std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;
30
31 static constexpr u64 PAGE_BITS = 16;
32 static constexpr u64 PAGE_SIZE = 1 << PAGE_BITS;
33 static constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
26 34
27private: 35private:
28 boost::optional<PAddr> FindFreeBlock(u64 size, u64 align = 1); 36 boost::optional<GPUVAddr> FindFreeBlock(u64 size, u64 align = 1);
29 bool IsPageMapped(PAddr paddr); 37 bool IsPageMapped(GPUVAddr gpu_addr);
30 VAddr& PageSlot(PAddr paddr); 38 VAddr& PageSlot(GPUVAddr gpu_addr);
31 39
32 enum class PageStatus : u64 { 40 enum class PageStatus : u64 {
33 Unmapped = 0xFFFFFFFFFFFFFFFFULL, 41 Unmapped = 0xFFFFFFFFFFFFFFFFULL,
@@ -35,7 +43,7 @@ private:
35 }; 43 };
36 44
37 static constexpr u64 MAX_ADDRESS{0x10000000000ULL}; 45 static constexpr u64 MAX_ADDRESS{0x10000000000ULL};
38 static constexpr u64 PAGE_TABLE_BITS{14}; 46 static constexpr u64 PAGE_TABLE_BITS{10};
39 static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS}; 47 static constexpr u64 PAGE_TABLE_SIZE{1 << PAGE_TABLE_BITS};
40 static constexpr u64 PAGE_TABLE_MASK{PAGE_TABLE_SIZE - 1}; 48 static constexpr u64 PAGE_TABLE_MASK{PAGE_TABLE_SIZE - 1};
41 static constexpr u64 PAGE_BLOCK_BITS{14}; 49 static constexpr u64 PAGE_BLOCK_BITS{14};
@@ -44,6 +52,14 @@ private:
44 52
45 using PageBlock = std::array<VAddr, PAGE_BLOCK_SIZE>; 53 using PageBlock = std::array<VAddr, PAGE_BLOCK_SIZE>;
46 std::array<std::unique_ptr<PageBlock>, PAGE_TABLE_SIZE> page_table{}; 54 std::array<std::unique_ptr<PageBlock>, PAGE_TABLE_SIZE> page_table{};
55
56 struct MappedRegion {
57 VAddr cpu_addr;
58 GPUVAddr gpu_addr;
59 u64 size;
60 };
61
62 std::vector<MappedRegion> mapped_regions;
47}; 63};
48 64
49} // namespace Tegra 65} // namespace Tegra
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 36629dd11..f0e48a802 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -6,6 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "video_core/gpu.h" 8#include "video_core/gpu.h"
9#include "video_core/memory_manager.h"
9 10
10struct ScreenInfo; 11struct ScreenInfo;
11 12
@@ -25,14 +26,14 @@ public:
25 virtual void FlushAll() = 0; 26 virtual void FlushAll() = 0;
26 27
27 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 28 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
28 virtual void FlushRegion(VAddr addr, u64 size) = 0; 29 virtual void FlushRegion(Tegra::GPUVAddr addr, u64 size) = 0;
29 30
30 /// Notify rasterizer that any caches of the specified region should be invalidated 31 /// Notify rasterizer that any caches of the specified region should be invalidated
31 virtual void InvalidateRegion(VAddr addr, u64 size) = 0; 32 virtual void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0;
32 33
33 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 34 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
34 /// and invalidated 35 /// and invalidated
35 virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; 36 virtual void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) = 0;
36 37
37 /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0 38 /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0
38 virtual bool AccelerateDisplayTransfer(const void* config) { 39 virtual bool AccelerateDisplayTransfer(const void* config) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 2d4a0d6db..9b3542e10 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -116,7 +116,7 @@ RasterizerOpenGL::RasterizerOpenGL() {
116 116
117 glEnable(GL_BLEND); 117 glEnable(GL_BLEND);
118 118
119 LOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!"); 119 NGLOG_CRITICAL(Render_OpenGL, "Sync fixed function OpenGL state here!");
120} 120}
121 121
122RasterizerOpenGL::~RasterizerOpenGL() { 122RasterizerOpenGL::~RasterizerOpenGL() {
@@ -127,7 +127,8 @@ RasterizerOpenGL::~RasterizerOpenGL() {
127 } 127 }
128} 128}
129 129
130void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { 130std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
131 GLintptr buffer_offset) {
131 MICROPROFILE_SCOPE(OpenGL_VAO); 132 MICROPROFILE_SCOPE(OpenGL_VAO);
132 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 133 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
133 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; 134 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
@@ -136,43 +137,58 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
136 state.draw.vertex_buffer = stream_buffer->GetHandle(); 137 state.draw.vertex_buffer = stream_buffer->GetHandle();
137 state.Apply(); 138 state.Apply();
138 139
139 // TODO(bunnei): Add support for 1+ vertex arrays 140 // Upload all guest vertex arrays sequentially to our buffer
140 const auto& vertex_array{regs.vertex_array[0]}; 141 for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
141 const auto& vertex_array_limit{regs.vertex_array_limit[0]}; 142 const auto& vertex_array = regs.vertex_array[index];
142 ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?"); 143 if (!vertex_array.IsEnabled())
143 ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!"); 144 continue;
144 for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) { 145
145 ASSERT_MSG(!regs.vertex_array[index].enable, "vertex array %d is unimplemented!", index); 146 const Tegra::GPUVAddr start = vertex_array.StartAddress();
147 const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
148
149 ASSERT(end > start);
150 u64 size = end - start + 1;
151
152 // Copy vertex array data
153 res_cache.FlushRegion(start, size, nullptr);
154 Memory::ReadBlock(*memory_manager->GpuToCpuAddress(start), array_ptr, size);
155
156 // Bind the vertex array to the buffer at the current offset.
157 glBindVertexBuffer(index, stream_buffer->GetHandle(), buffer_offset, vertex_array.stride);
158
159 ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented");
160
161 array_ptr += size;
162 buffer_offset += size;
146 } 163 }
147 164
148 // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. 165 // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
149 // Enables the first 16 vertex attributes always, as we don't know which ones are actually used 166 // Enables the first 16 vertex attributes always, as we don't know which ones are actually used
150 // until shader time. Note, Tegra technically supports 32, but we're cappinig this to 16 for now 167 // until shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now
151 // to avoid OpenGL errors. 168 // to avoid OpenGL errors.
169 // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
170 // assume every shader uses them all.
152 for (unsigned index = 0; index < 16; ++index) { 171 for (unsigned index = 0; index < 16; ++index) {
153 auto& attrib = regs.vertex_attrib_format[index]; 172 auto& attrib = regs.vertex_attrib_format[index];
154 NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}", 173 NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
155 index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(), 174 index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
156 attrib.offset.Value(), attrib.IsNormalized()); 175 attrib.offset.Value(), attrib.IsNormalized());
157 176
158 glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), 177 auto& buffer = regs.vertex_array[attrib.buffer];
159 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride, 178 ASSERT(buffer.IsEnabled());
160 reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset)); 179
161 glEnableVertexAttribArray(index); 180 glEnableVertexAttribArray(index);
181 glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
182 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
183 glVertexAttribBinding(index, attrib.buffer);
184
162 hw_vao_enabled_attributes[index] = true; 185 hw_vao_enabled_attributes[index] = true;
163 } 186 }
164 187
165 // Copy vertex array data 188 return {array_ptr, buffer_offset};
166 const u64 data_size{vertex_array_limit.LimitAddress() - vertex_array.StartAddress() + 1};
167 const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
168 res_cache.FlushRegion(data_addr, data_size, nullptr);
169 Memory::ReadBlock(data_addr, array_ptr, data_size);
170
171 array_ptr += data_size;
172 buffer_offset += data_size;
173} 189}
174 190
175void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos) { 191void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) {
176 // Helper function for uploading uniform data 192 // Helper function for uploading uniform data
177 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { 193 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
178 if (has_ARB_direct_state_access) { 194 if (has_ARB_direct_state_access) {
@@ -190,8 +206,6 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
190 u32 current_constbuffer_bindpoint = 0; 206 u32 current_constbuffer_bindpoint = 0;
191 207
192 for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { 208 for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) {
193 ptr_pos += sizeof(GLShader::MaxwellUniformData);
194
195 auto& shader_config = gpu.regs.shader_config[index]; 209 auto& shader_config = gpu.regs.shader_config[index];
196 const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; 210 const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
197 211
@@ -205,18 +219,21 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
205 } 219 }
206 220
207 // Upload uniform data as one UBO per stage 221 // Upload uniform data as one UBO per stage
208 const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); 222 const GLintptr ubo_offset = buffer_offset;
209 copy_buffer(uniform_buffers[stage].handle, ubo_offset, 223 copy_buffer(uniform_buffers[stage].handle, ubo_offset,
210 sizeof(GLShader::MaxwellUniformData)); 224 sizeof(GLShader::MaxwellUniformData));
211 GLShader::MaxwellUniformData* ub_ptr = 225 GLShader::MaxwellUniformData* ub_ptr =
212 reinterpret_cast<GLShader::MaxwellUniformData*>(&buffer_ptr[ptr_pos]); 226 reinterpret_cast<GLShader::MaxwellUniformData*>(buffer_ptr);
213 ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]); 227 ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]);
214 228
229 buffer_ptr += sizeof(GLShader::MaxwellUniformData);
230 buffer_offset += sizeof(GLShader::MaxwellUniformData);
231
215 // Fetch program code from memory 232 // Fetch program code from memory
216 GLShader::ProgramCode program_code; 233 GLShader::ProgramCode program_code;
217 const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset}; 234 const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset};
218 const VAddr cpu_address{gpu.memory_manager.PhysicalToVirtualAddress(gpu_address)}; 235 const boost::optional<VAddr> cpu_address{gpu.memory_manager.GpuToCpuAddress(gpu_address)};
219 Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64)); 236 Memory::ReadBlock(*cpu_address, program_code.data(), program_code.size() * sizeof(u64));
220 GLShader::ShaderSetup setup{std::move(program_code)}; 237 GLShader::ShaderSetup setup{std::move(program_code)};
221 238
222 GLShader::ShaderEntries shader_resources; 239 GLShader::ShaderEntries shader_resources;
@@ -235,8 +252,8 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
235 break; 252 break;
236 } 253 }
237 default: 254 default:
238 LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index, 255 NGLOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset={:#010X}",
239 shader_config.enable.Value(), shader_config.offset); 256 index, shader_config.enable.Value(), shader_config.offset);
240 UNREACHABLE(); 257 UNREACHABLE();
241 } 258 }
242 259
@@ -252,6 +269,24 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size
252 shader_program_manager->UseTrivialGeometryShader(); 269 shader_program_manager->UseTrivialGeometryShader();
253} 270}
254 271
272size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
273 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
274
275 size_t size = 0;
276 for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
277 if (!regs.vertex_array[index].IsEnabled())
278 continue;
279
280 const Tegra::GPUVAddr start = regs.vertex_array[index].StartAddress();
281 const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
282
283 ASSERT(end > start);
284 size += end - start + 1;
285 }
286
287 return size;
288}
289
255bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { 290bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
256 accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; 291 accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays;
257 DrawArrays(); 292 DrawArrays();
@@ -329,44 +364,49 @@ void RasterizerOpenGL::DrawArrays() {
329 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()}; 364 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
330 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count}; 365 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
331 366
332 // TODO(bunnei): Add support for 1+ vertex arrays
333 vs_input_size = vertex_num * regs.vertex_array[0].stride;
334
335 state.draw.vertex_buffer = stream_buffer->GetHandle(); 367 state.draw.vertex_buffer = stream_buffer->GetHandle();
336 state.Apply(); 368 state.Apply();
337 369
338 size_t buffer_size = static_cast<size_t>(vs_input_size); 370 size_t buffer_size = CalculateVertexArraysSize();
371
339 if (is_indexed) { 372 if (is_indexed) {
340 buffer_size = Common::AlignUp(buffer_size, 4) + index_buffer_size; 373 buffer_size = Common::AlignUp<size_t>(buffer_size, 4) + index_buffer_size;
341 } 374 }
342 375
343 // Uniform space for the 5 shader stages 376 // Uniform space for the 5 shader stages
344 buffer_size += sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage; 377 buffer_size = Common::AlignUp<size_t>(buffer_size, 4) +
378 sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage;
345 379
346 size_t ptr_pos = 0;
347 u8* buffer_ptr; 380 u8* buffer_ptr;
348 GLintptr buffer_offset; 381 GLintptr buffer_offset;
349 std::tie(buffer_ptr, buffer_offset) = 382 std::tie(buffer_ptr, buffer_offset) =
350 stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4); 383 stream_buffer->Map(static_cast<GLsizeiptr>(buffer_size), 4);
351 384
352 SetupVertexArray(buffer_ptr, buffer_offset); 385 u8* offseted_buffer;
353 ptr_pos += vs_input_size; 386 std::tie(offseted_buffer, buffer_offset) = SetupVertexArrays(buffer_ptr, buffer_offset);
387
388 offseted_buffer =
389 reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
390 buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
354 391
355 // If indexed mode, copy the index buffer 392 // If indexed mode, copy the index buffer
356 GLintptr index_buffer_offset = 0; 393 GLintptr index_buffer_offset = 0;
357 if (is_indexed) { 394 if (is_indexed) {
358 ptr_pos = Common::AlignUp(ptr_pos, 4);
359
360 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; 395 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
361 const VAddr index_data_addr{ 396 const boost::optional<VAddr> index_data_addr{
362 memory_manager->PhysicalToVirtualAddress(regs.index_array.StartAddress())}; 397 memory_manager->GpuToCpuAddress(regs.index_array.StartAddress())};
363 Memory::ReadBlock(index_data_addr, &buffer_ptr[ptr_pos], index_buffer_size); 398 Memory::ReadBlock(*index_data_addr, offseted_buffer, index_buffer_size);
364 399
365 index_buffer_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); 400 index_buffer_offset = buffer_offset;
366 ptr_pos += index_buffer_size; 401 offseted_buffer += index_buffer_size;
402 buffer_offset += index_buffer_size;
367 } 403 }
368 404
369 SetupShaders(buffer_ptr, buffer_offset, ptr_pos); 405 offseted_buffer =
406 reinterpret_cast<u8*>(Common::AlignUp(reinterpret_cast<size_t>(offseted_buffer), 4));
407 buffer_offset = Common::AlignUp<size_t>(buffer_offset, 4);
408
409 SetupShaders(offseted_buffer, buffer_offset);
370 410
371 stream_buffer->Unmap(); 411 stream_buffer->Unmap();
372 412
@@ -478,17 +518,17 @@ void RasterizerOpenGL::FlushAll() {
478 res_cache.FlushAll(); 518 res_cache.FlushAll();
479} 519}
480 520
481void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { 521void RasterizerOpenGL::FlushRegion(Tegra::GPUVAddr addr, u64 size) {
482 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 522 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
483 res_cache.FlushRegion(addr, size); 523 res_cache.FlushRegion(addr, size);
484} 524}
485 525
486void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { 526void RasterizerOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, u64 size) {
487 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 527 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
488 res_cache.InvalidateRegion(addr, size, nullptr); 528 res_cache.InvalidateRegion(addr, size, nullptr);
489} 529}
490 530
491void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { 531void RasterizerOpenGL::FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) {
492 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 532 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
493 res_cache.FlushRegion(addr, size); 533 res_cache.FlushRegion(addr, size);
494 res_cache.InvalidateRegion(addr, size, nullptr); 534 res_cache.InvalidateRegion(addr, size, nullptr);
@@ -519,7 +559,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
519 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 559 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
520 560
521 SurfaceParams src_params; 561 SurfaceParams src_params;
522 src_params.addr = framebuffer_addr; 562 src_params.cpu_addr = framebuffer_addr;
563 src_params.addr = res_cache.TryFindFramebufferGpuAddress(framebuffer_addr).get_value_or(0);
523 src_params.width = std::min(framebuffer.width, pixel_stride); 564 src_params.width = std::min(framebuffer.width, pixel_stride);
524 src_params.height = framebuffer.height; 565 src_params.height = framebuffer.height;
525 src_params.stride = pixel_stride; 566 src_params.stride = pixel_stride;
@@ -618,9 +659,9 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr
618 buffer_draw_state.enabled = true; 659 buffer_draw_state.enabled = true;
619 buffer_draw_state.bindpoint = current_bindpoint + bindpoint; 660 buffer_draw_state.bindpoint = current_bindpoint + bindpoint;
620 661
621 VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address); 662 boost::optional<VAddr> addr = gpu.memory_manager->GpuToCpuAddress(buffer.address);
622 std::vector<u8> data(used_buffer.GetSize() * sizeof(float)); 663 std::vector<u8> data(used_buffer.GetSize() * sizeof(float));
623 Memory::ReadBlock(addr, data.data(), data.size()); 664 Memory::ReadBlock(*addr, data.data(), data.size());
624 665
625 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo); 666 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo);
626 glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW); 667 glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 03e02b52a..9709e595e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -11,6 +11,7 @@
11#include <glad/glad.h> 11#include <glad/glad.h>
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "video_core/engines/maxwell_3d.h" 13#include "video_core/engines/maxwell_3d.h"
14#include "video_core/memory_manager.h"
14#include "video_core/rasterizer_interface.h" 15#include "video_core/rasterizer_interface.h"
15#include "video_core/renderer_opengl/gl_rasterizer_cache.h" 16#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
16#include "video_core/renderer_opengl/gl_resource_manager.h" 17#include "video_core/renderer_opengl/gl_resource_manager.h"
@@ -29,9 +30,9 @@ public:
29 void DrawArrays() override; 30 void DrawArrays() override;
30 void NotifyMaxwellRegisterChanged(u32 method) override; 31 void NotifyMaxwellRegisterChanged(u32 method) override;
31 void FlushAll() override; 32 void FlushAll() override;
32 void FlushRegion(VAddr addr, u64 size) override; 33 void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
33 void InvalidateRegion(VAddr addr, u64 size) override; 34 void InvalidateRegion(Tegra::GPUVAddr addr, u64 size) override;
34 void FlushAndInvalidateRegion(VAddr addr, u64 size) override; 35 void FlushAndInvalidateRegion(Tegra::GPUVAddr addr, u64 size) override;
35 bool AccelerateDisplayTransfer(const void* config) override; 36 bool AccelerateDisplayTransfer(const void* config) override;
36 bool AccelerateTextureCopy(const void* config) override; 37 bool AccelerateTextureCopy(const void* config) override;
37 bool AccelerateFill(const void* config) override; 38 bool AccelerateFill(const void* config) override;
@@ -148,13 +149,13 @@ private:
148 static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024; 149 static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024;
149 std::unique_ptr<OGLStreamBuffer> stream_buffer; 150 std::unique_ptr<OGLStreamBuffer> stream_buffer;
150 151
151 GLsizeiptr vs_input_size; 152 size_t CalculateVertexArraysSize() const;
152 153
153 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); 154 std::pair<u8*, GLintptr> SetupVertexArrays(u8* array_ptr, GLintptr buffer_offset);
154 155
155 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers; 156 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
156 157
157 void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos); 158 void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset);
158 159
159 enum class AccelDraw { Disabled, Arrays, Indexed }; 160 enum class AccelDraw { Disabled, Arrays, Indexed };
160 AccelDraw accelerate_draw; 161 AccelDraw accelerate_draw;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 7410471cc..501d15e98 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -41,18 +41,15 @@ struct FormatTuple {
41 GLenum format; 41 GLenum format;
42 GLenum type; 42 GLenum type;
43 bool compressed; 43 bool compressed;
44 // How many pixels in the original texture are equivalent to one pixel in the compressed
45 // texture.
46 u32 compression_factor;
47}; 44};
48 45
49static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{ 46static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
50 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8 47 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8
51 {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1}, // B5G6R5 48 {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false}, // B5G6R5
52 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, 1}, // A2B10G10R10 49 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false}, // A2B10G10R10
53 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1 50 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1
54 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23 51 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23
55 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45 52 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45
56}}; 53}};
57 54
58static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) { 55static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
@@ -83,26 +80,30 @@ static u16 GetResolutionScaleFactor() {
83} 80}
84 81
85template <bool morton_to_gl, PixelFormat format> 82template <bool morton_to_gl, PixelFormat format>
86void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start, 83void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, Tegra::GPUVAddr base,
87 VAddr end) { 84 Tegra::GPUVAddr start, Tegra::GPUVAddr end) {
88 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 85 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / CHAR_BIT;
89 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 86 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
87 const auto& gpu = Core::System::GetInstance().GPU();
90 88
91 if (morton_to_gl) { 89 if (morton_to_gl) {
92 auto data = Tegra::Texture::UnswizzleTexture( 90 auto data = Tegra::Texture::UnswizzleTexture(
93 base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, 91 *gpu.memory_manager->GpuToCpuAddress(base),
94 block_height); 92 SurfaceParams::TextureFormatFromPixelFormat(format), stride, height, block_height);
95 std::memcpy(gl_buffer, data.data(), data.size()); 93 std::memcpy(gl_buffer, data.data(), data.size());
96 } else { 94 } else {
97 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check 95 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check
98 // the configuration for this and perform more generic un/swizzle 96 // the configuration for this and perform more generic un/swizzle
99 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); 97 NGLOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
100 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, 98 VideoCore::MortonCopyPixels128(
101 Memory::GetPointer(base), gl_buffer, morton_to_gl); 99 stride, height, bytes_per_pixel, gl_bytes_per_pixel,
100 Memory::GetPointer(*gpu.memory_manager->GpuToCpuAddress(base)), gl_buffer,
101 morton_to_gl);
102 } 102 }
103} 103}
104 104
105static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 105static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr,
106 Tegra::GPUVAddr),
106 SurfaceParams::MaxPixelFormat> 107 SurfaceParams::MaxPixelFormat>
107 morton_to_gl_fns = { 108 morton_to_gl_fns = {
108 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>, 109 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
@@ -110,7 +111,8 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
110 MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>, 111 MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>,
111}; 112};
112 113
113static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 114static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr,
115 Tegra::GPUVAddr),
114 SurfaceParams::MaxPixelFormat> 116 SurfaceParams::MaxPixelFormat>
115 gl_to_morton_fns = { 117 gl_to_morton_fns = {
116 MortonCopy<false, PixelFormat::ABGR8>, 118 MortonCopy<false, PixelFormat::ABGR8>,
@@ -219,9 +221,9 @@ SurfaceParams SurfaceParams::FromInterval(SurfaceInterval interval) const {
219 SurfaceParams params = *this; 221 SurfaceParams params = *this;
220 const u32 tiled_size = is_tiled ? 8 : 1; 222 const u32 tiled_size = is_tiled ? 8 : 1;
221 const u64 stride_tiled_bytes = BytesInPixels(stride * tiled_size); 223 const u64 stride_tiled_bytes = BytesInPixels(stride * tiled_size);
222 VAddr aligned_start = 224 Tegra::GPUVAddr aligned_start =
223 addr + Common::AlignDown(boost::icl::first(interval) - addr, stride_tiled_bytes); 225 addr + Common::AlignDown(boost::icl::first(interval) - addr, stride_tiled_bytes);
224 VAddr aligned_end = 226 Tegra::GPUVAddr aligned_end =
225 addr + Common::AlignUp(boost::icl::last_next(interval) - addr, stride_tiled_bytes); 227 addr + Common::AlignUp(boost::icl::last_next(interval) - addr, stride_tiled_bytes);
226 228
227 if (aligned_end - aligned_start > stride_tiled_bytes) { 229 if (aligned_end - aligned_start > stride_tiled_bytes) {
@@ -342,6 +344,13 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const {
342 return FromInterval(texcopy_params.GetInterval()).GetInterval() == texcopy_params.GetInterval(); 344 return FromInterval(texcopy_params.GetInterval()).GetInterval() == texcopy_params.GetInterval();
343} 345}
344 346
347VAddr SurfaceParams::GetCpuAddr() const {
348 // When this function is used, only cpu_addr or (GPU) addr should be set, not both
349 ASSERT(!(cpu_addr && addr));
350 const auto& gpu = Core::System::GetInstance().GPU();
351 return cpu_addr.get_value_or(*gpu.memory_manager->GpuToCpuAddress(addr));
352}
353
345bool CachedSurface::CanFill(const SurfaceParams& dest_surface, 354bool CachedSurface::CanFill(const SurfaceParams& dest_surface,
346 SurfaceInterval fill_interval) const { 355 SurfaceInterval fill_interval) const {
347 if (type == SurfaceType::Fill && IsRegionValid(fill_interval) && 356 if (type == SurfaceType::Fill && IsRegionValid(fill_interval) &&
@@ -349,9 +358,9 @@ bool CachedSurface::CanFill(const SurfaceParams& dest_surface,
349 boost::icl::last_next(fill_interval) <= end && // dest_surface is within our fill range 358 boost::icl::last_next(fill_interval) <= end && // dest_surface is within our fill range
350 dest_surface.FromInterval(fill_interval).GetInterval() == 359 dest_surface.FromInterval(fill_interval).GetInterval() ==
351 fill_interval) { // make sure interval is a rectangle in dest surface 360 fill_interval) { // make sure interval is a rectangle in dest surface
352 if (fill_size * 8 != dest_surface.GetFormatBpp()) { 361 if (fill_size * CHAR_BIT != dest_surface.GetFormatBpp()) {
353 // Check if bits repeat for our fill_size 362 // Check if bits repeat for our fill_size
354 const u32 dest_bytes_per_pixel = std::max(dest_surface.GetFormatBpp() / 8, 1u); 363 const u32 dest_bytes_per_pixel = std::max(dest_surface.GetFormatBpp() / CHAR_BIT, 1u);
355 std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel); 364 std::vector<u8> fill_test(fill_size * dest_bytes_per_pixel);
356 365
357 for (u32 i = 0; i < dest_bytes_per_pixel; ++i) 366 for (u32 i = 0; i < dest_bytes_per_pixel; ++i)
@@ -456,15 +465,15 @@ void RasterizerCacheOpenGL::CopySurface(const Surface& src_surface, const Surfac
456} 465}
457 466
458MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192)); 467MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
459void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) { 468void CachedSurface::LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr load_end) {
460 ASSERT(type != SurfaceType::Fill); 469 ASSERT(type != SurfaceType::Fill);
461 470
462 u8* const texture_src_data = Memory::GetPointer(addr); 471 u8* const texture_src_data = Memory::GetPointer(GetCpuAddr());
463 if (texture_src_data == nullptr) 472 if (texture_src_data == nullptr)
464 return; 473 return;
465 474
466 if (gl_buffer == nullptr) { 475 if (gl_buffer == nullptr) {
467 gl_buffer_size = width * height * GetGLBytesPerPixel(pixel_format); 476 gl_buffer_size = GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format);
468 gl_buffer.reset(new u8[gl_buffer_size]); 477 gl_buffer.reset(new u8[gl_buffer_size]);
469 } 478 }
470 479
@@ -479,14 +488,15 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) {
479 std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset, 488 std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
480 bytes_per_pixel * width * height); 489 bytes_per_pixel * width * height);
481 } else { 490 } else {
482 morton_to_gl_fns[static_cast<size_t>(pixel_format)]( 491 morton_to_gl_fns[static_cast<size_t>(pixel_format)](GetActualWidth(), block_height,
483 stride, block_height, height, &gl_buffer[0], addr, load_start, load_end); 492 GetActualHeight(), &gl_buffer[0], addr,
493 load_start, load_end);
484 } 494 }
485} 495}
486 496
487MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); 497MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
488void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) { 498void CachedSurface::FlushGLBuffer(Tegra::GPUVAddr flush_start, Tegra::GPUVAddr flush_end) {
489 u8* const dst_buffer = Memory::GetPointer(addr); 499 u8* const dst_buffer = Memory::GetPointer(GetCpuAddr());
490 if (dst_buffer == nullptr) 500 if (dst_buffer == nullptr)
491 return; 501 return;
492 502
@@ -536,7 +546,8 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
536 546
537 MICROPROFILE_SCOPE(OpenGL_TextureUL); 547 MICROPROFILE_SCOPE(OpenGL_TextureUL);
538 548
539 ASSERT(gl_buffer_size == width * height * GetGLBytesPerPixel(pixel_format)); 549 ASSERT(gl_buffer_size ==
550 GetActualWidth() * GetActualHeight() * GetGLBytesPerPixel(pixel_format));
540 551
541 // Load data from memory to the surface 552 // Load data from memory to the surface
542 GLint x0 = static_cast<GLint>(rect.left); 553 GLint x0 = static_cast<GLint>(rect.left);
@@ -571,11 +582,9 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
571 glActiveTexture(GL_TEXTURE0); 582 glActiveTexture(GL_TEXTURE0);
572 if (tuple.compressed) { 583 if (tuple.compressed) {
573 glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, 584 glCompressedTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format,
574 static_cast<GLsizei>(rect.GetWidth()), 585 static_cast<GLsizei>(rect.GetWidth() * GetCompresssionFactor()),
575 static_cast<GLsizei>(rect.GetHeight()), 0, 586 static_cast<GLsizei>(rect.GetHeight() * GetCompresssionFactor()), 0,
576 rect.GetWidth() * rect.GetHeight() * 587 size, &gl_buffer[buffer_offset]);
577 GetGLBytesPerPixel(pixel_format) / tuple.compression_factor,
578 &gl_buffer[buffer_offset]);
579 } else { 588 } else {
580 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()), 589 glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
581 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type, 590 static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
@@ -945,6 +954,33 @@ Surface RasterizerCacheOpenGL::GetSurface(const SurfaceParams& params, ScaleMatc
945 return surface; 954 return surface;
946} 955}
947 956
957boost::optional<Tegra::GPUVAddr> RasterizerCacheOpenGL::TryFindFramebufferGpuAddress(
958 VAddr cpu_addr) const {
959 // Tries to find the GPU address of a framebuffer based on the CPU address. This is because
960 // final output framebuffers are specified by CPU address, but internally our GPU cache uses GPU
961 // addresses. We iterate through all cached framebuffers, and compare their starting CPU address
962 // to the one provided. This is obviously not great, and won't work if the framebuffer overlaps
963 // surfaces.
964
965 std::vector<Tegra::GPUVAddr> gpu_addresses;
966 for (const auto& pair : surface_cache) {
967 for (const auto& surface : pair.second) {
968 const VAddr surface_cpu_addr = surface->GetCpuAddr();
969 if (cpu_addr >= surface_cpu_addr && cpu_addr < (surface_cpu_addr + surface->size)) {
970 ASSERT_MSG(cpu_addr == surface_cpu_addr, "overlapping surfaces are unsupported");
971 gpu_addresses.push_back(surface->addr);
972 }
973 }
974 }
975
976 if (gpu_addresses.empty()) {
977 return {};
978 }
979
980 ASSERT_MSG(gpu_addresses.size() == 1, ">1 surface is unsupported");
981 return gpu_addresses[0];
982}
983
948SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params, 984SurfaceRect_Tuple RasterizerCacheOpenGL::GetSurfaceSubRect(const SurfaceParams& params,
949 ScaleMatch match_res_scale, 985 ScaleMatch match_res_scale,
950 bool load_if_create) { 986 bool load_if_create) {
@@ -1028,11 +1064,11 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1028 auto& gpu = Core::System::GetInstance().GPU(); 1064 auto& gpu = Core::System::GetInstance().GPU();
1029 1065
1030 SurfaceParams params; 1066 SurfaceParams params;
1031 params.addr = gpu.memory_manager->PhysicalToVirtualAddress(config.tic.Address()); 1067 params.addr = config.tic.Address();
1032 params.width = config.tic.Width();
1033 params.height = config.tic.Height();
1034 params.is_tiled = config.tic.IsTiled(); 1068 params.is_tiled = config.tic.IsTiled();
1035 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); 1069 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
1070 params.width = config.tic.Width() / params.GetCompresssionFactor();
1071 params.height = config.tic.Height() / params.GetCompresssionFactor();
1036 1072
1037 // TODO(Subv): Different types per component are not supported. 1073 // TODO(Subv): Different types per component are not supported.
1038 ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() && 1074 ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
@@ -1045,7 +1081,7 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1045 params.block_height = config.tic.BlockHeight(); 1081 params.block_height = config.tic.BlockHeight();
1046 } else { 1082 } else {
1047 // Use the texture-provided stride value if the texture isn't tiled. 1083 // Use the texture-provided stride value if the texture isn't tiled.
1048 params.stride = params.PixelsInBytes(config.tic.Pitch()); 1084 params.stride = static_cast<u32>(params.PixelsInBytes(config.tic.Pitch()));
1049 } 1085 }
1050 1086
1051 params.UpdateParams(); 1087 params.UpdateParams();
@@ -1073,11 +1109,10 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1073SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces( 1109SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1074 bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) { 1110 bool using_color_fb, bool using_depth_fb, const MathUtil::Rectangle<s32>& viewport) {
1075 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 1111 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
1076 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
1077 const auto& config = regs.rt[0]; 1112 const auto& config = regs.rt[0];
1078 1113
1079 // TODO(bunnei): This is hard corded to use just the first render buffer 1114 // TODO(bunnei): This is hard corded to use just the first render buffer
1080 LOG_WARNING(Render_OpenGL, "hard-coded for render target 0!"); 1115 NGLOG_WARNING(Render_OpenGL, "hard-coded for render target 0!");
1081 1116
1082 // update resolution_scale_factor and reset cache if changed 1117 // update resolution_scale_factor and reset cache if changed
1083 // TODO (bunnei): This code was ported as-is from Citra, and is technically not thread-safe. We 1118 // TODO (bunnei): This code was ported as-is from Citra, and is technically not thread-safe. We
@@ -1106,7 +1141,7 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1106 color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight; 1141 color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
1107 SurfaceParams depth_params = color_params; 1142 SurfaceParams depth_params = color_params;
1108 1143
1109 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); 1144 color_params.addr = config.Address();
1110 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); 1145 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format);
1111 color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format); 1146 color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format);
1112 color_params.UpdateParams(); 1147 color_params.UpdateParams();
@@ -1122,8 +1157,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1122 // Make sure that framebuffers don't overlap if both color and depth are being used 1157 // Make sure that framebuffers don't overlap if both color and depth are being used
1123 if (using_color_fb && using_depth_fb && 1158 if (using_color_fb && using_depth_fb &&
1124 boost::icl::length(color_vp_interval & depth_vp_interval)) { 1159 boost::icl::length(color_vp_interval & depth_vp_interval)) {
1125 LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " 1160 NGLOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; "
1126 "overlapping framebuffers not supported!"); 1161 "overlapping framebuffers not supported!");
1127 using_depth_fb = false; 1162 using_depth_fb = false;
1128 } 1163 }
1129 1164
@@ -1222,7 +1257,8 @@ void RasterizerCacheOpenGL::DuplicateSurface(const Surface& src_surface,
1222 } 1257 }
1223} 1258}
1224 1259
1225void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr, u64 size) { 1260void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, Tegra::GPUVAddr addr,
1261 u64 size) {
1226 if (size == 0) 1262 if (size == 0)
1227 return; 1263 return;
1228 1264
@@ -1261,7 +1297,7 @@ void RasterizerCacheOpenGL::ValidateSurface(const Surface& surface, VAddr addr,
1261 } 1297 }
1262} 1298}
1263 1299
1264void RasterizerCacheOpenGL::FlushRegion(VAddr addr, u64 size, Surface flush_surface) { 1300void RasterizerCacheOpenGL::FlushRegion(Tegra::GPUVAddr addr, u64 size, Surface flush_surface) {
1265 if (size == 0) 1301 if (size == 0)
1266 return; 1302 return;
1267 1303
@@ -1297,7 +1333,8 @@ void RasterizerCacheOpenGL::FlushAll() {
1297 FlushRegion(0, Kernel::VMManager::MAX_ADDRESS); 1333 FlushRegion(0, Kernel::VMManager::MAX_ADDRESS);
1298} 1334}
1299 1335
1300void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface& region_owner) { 1336void RasterizerCacheOpenGL::InvalidateRegion(Tegra::GPUVAddr addr, u64 size,
1337 const Surface& region_owner) {
1301 if (size == 0) 1338 if (size == 0)
1302 return; 1339 return;
1303 1340
@@ -1390,10 +1427,10 @@ void RasterizerCacheOpenGL::UnregisterSurface(const Surface& surface) {
1390 surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); 1427 surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}});
1391} 1428}
1392 1429
1393void RasterizerCacheOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 1430void RasterizerCacheOpenGL::UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) {
1394 const u64 num_pages = 1431 const u64 num_pages = ((addr + size - 1) >> Tegra::MemoryManager::PAGE_BITS) -
1395 ((addr + size - 1) >> Memory::PAGE_BITS) - (addr >> Memory::PAGE_BITS) + 1; 1432 (addr >> Tegra::MemoryManager::PAGE_BITS) + 1;
1396 const u64 page_start = addr >> Memory::PAGE_BITS; 1433 const u64 page_start = addr >> Tegra::MemoryManager::PAGE_BITS;
1397 const u64 page_end = page_start + num_pages; 1434 const u64 page_end = page_start + num_pages;
1398 1435
1399 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to 1436 // Interval maps will erase segments if count reaches 0, so if delta is negative we have to
@@ -1406,8 +1443,10 @@ void RasterizerCacheOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int del
1406 const auto interval = pair.first & pages_interval; 1443 const auto interval = pair.first & pages_interval;
1407 const int count = pair.second; 1444 const int count = pair.second;
1408 1445
1409 const VAddr interval_start_addr = boost::icl::first(interval) << Memory::PAGE_BITS; 1446 const Tegra::GPUVAddr interval_start_addr = boost::icl::first(interval)
1410 const VAddr interval_end_addr = boost::icl::last_next(interval) << Memory::PAGE_BITS; 1447 << Tegra::MemoryManager::PAGE_BITS;
1448 const Tegra::GPUVAddr interval_end_addr = boost::icl::last_next(interval)
1449 << Tegra::MemoryManager::PAGE_BITS;
1411 const u64 interval_size = interval_end_addr - interval_start_addr; 1450 const u64 interval_size = interval_end_addr - interval_start_addr;
1412 1451
1413 if (delta > 0 && count == delta) 1452 if (delta > 0 && count == delta)
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index e4cb3390f..55f1bdee8 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -17,12 +17,14 @@
17#ifdef __GNUC__ 17#ifdef __GNUC__
18#pragma GCC diagnostic pop 18#pragma GCC diagnostic pop
19#endif 19#endif
20#include <boost/optional.hpp>
20#include <glad/glad.h> 21#include <glad/glad.h>
21#include "common/assert.h" 22#include "common/assert.h"
22#include "common/common_funcs.h" 23#include "common/common_funcs.h"
23#include "common/common_types.h" 24#include "common/common_types.h"
24#include "common/math_util.h" 25#include "common/math_util.h"
25#include "video_core/gpu.h" 26#include "video_core/gpu.h"
27#include "video_core/memory_manager.h"
26#include "video_core/renderer_opengl/gl_resource_manager.h" 28#include "video_core/renderer_opengl/gl_resource_manager.h"
27#include "video_core/textures/texture.h" 29#include "video_core/textures/texture.h"
28 30
@@ -30,9 +32,9 @@ struct CachedSurface;
30using Surface = std::shared_ptr<CachedSurface>; 32using Surface = std::shared_ptr<CachedSurface>;
31using SurfaceSet = std::set<Surface>; 33using SurfaceSet = std::set<Surface>;
32 34
33using SurfaceRegions = boost::icl::interval_set<VAddr>; 35using SurfaceRegions = boost::icl::interval_set<Tegra::GPUVAddr>;
34using SurfaceMap = boost::icl::interval_map<VAddr, Surface>; 36using SurfaceMap = boost::icl::interval_map<Tegra::GPUVAddr, Surface>;
35using SurfaceCache = boost::icl::interval_map<VAddr, SurfaceSet>; 37using SurfaceCache = boost::icl::interval_map<Tegra::GPUVAddr, SurfaceSet>;
36 38
37using SurfaceInterval = SurfaceCache::interval_type; 39using SurfaceInterval = SurfaceCache::interval_type;
38static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() && 40static_assert(std::is_same<SurfaceRegions::interval_type, SurfaceCache::interval_type>() &&
@@ -82,23 +84,49 @@ struct SurfaceParams {
82 Invalid = 4, 84 Invalid = 4,
83 }; 85 };
84 86
85 static constexpr unsigned int GetFormatBpp(PixelFormat format) { 87 /**
88 * Gets the compression factor for the specified PixelFormat. This applies to just the
89 * "compressed width" and "compressed height", not the overall compression factor of a
90 * compressed image. This is used for maintaining proper surface sizes for compressed texture
91 * formats.
92 */
93 static constexpr u32 GetCompresssionFactor(PixelFormat format) {
86 if (format == PixelFormat::Invalid) 94 if (format == PixelFormat::Invalid)
87 return 0; 95 return 0;
88 96
89 constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = { 97 constexpr std::array<u32, MaxPixelFormat> compression_factor_table = {{
98 1, // ABGR8
99 1, // B5G6R5
100 1, // A2B10G10R10
101 4, // DXT1
102 4, // DXT23
103 4, // DXT45
104 }};
105
106 ASSERT(static_cast<size_t>(format) < compression_factor_table.size());
107 return compression_factor_table[static_cast<size_t>(format)];
108 }
109 u32 GetCompresssionFactor() const {
110 return GetCompresssionFactor(pixel_format);
111 }
112
113 static constexpr u32 GetFormatBpp(PixelFormat format) {
114 if (format == PixelFormat::Invalid)
115 return 0;
116
117 constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
90 32, // ABGR8 118 32, // ABGR8
91 16, // B5G6R5 119 16, // B5G6R5
92 32, // A2B10G10R10 120 32, // A2B10G10R10
93 64, // DXT1 121 64, // DXT1
94 128, // DXT23 122 128, // DXT23
95 128, // DXT45 123 128, // DXT45
96 }; 124 }};
97 125
98 ASSERT(static_cast<size_t>(format) < bpp_table.size()); 126 ASSERT(static_cast<size_t>(format) < bpp_table.size());
99 return bpp_table[static_cast<size_t>(format)]; 127 return bpp_table[static_cast<size_t>(format)];
100 } 128 }
101 unsigned int GetFormatBpp() const { 129 u32 GetFormatBpp() const {
102 return GetFormatBpp(pixel_format); 130 return GetFormatBpp(pixel_format);
103 } 131 }
104 132
@@ -106,6 +134,8 @@ struct SurfaceParams {
106 switch (format) { 134 switch (format) {
107 case Tegra::RenderTargetFormat::RGBA8_UNORM: 135 case Tegra::RenderTargetFormat::RGBA8_UNORM:
108 return PixelFormat::ABGR8; 136 return PixelFormat::ABGR8;
137 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
138 return PixelFormat::A2B10G10R10;
109 default: 139 default:
110 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 140 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
111 UNREACHABLE(); 141 UNREACHABLE();
@@ -251,6 +281,24 @@ struct SurfaceParams {
251 // Returns the region of the biggest valid rectange within interval 281 // Returns the region of the biggest valid rectange within interval
252 SurfaceInterval GetCopyableInterval(const Surface& src_surface) const; 282 SurfaceInterval GetCopyableInterval(const Surface& src_surface) const;
253 283
284 /**
285 * Gets the actual width (in pixels) of the surface. This is provided because `width` is used
286 * for tracking the surface region in memory, which may be compressed for certain formats. In
287 * this scenario, `width` is actually the compressed width.
288 */
289 u32 GetActualWidth() const {
290 return width * GetCompresssionFactor();
291 }
292
293 /**
294 * Gets the actual height (in pixels) of the surface. This is provided because `height` is used
295 * for tracking the surface region in memory, which may be compressed for certain formats. In
296 * this scenario, `height` is actually the compressed height.
297 */
298 u32 GetActualHeight() const {
299 return height * GetCompresssionFactor();
300 }
301
254 u32 GetScaledWidth() const { 302 u32 GetScaledWidth() const {
255 return width * res_scale; 303 return width * res_scale;
256 } 304 }
@@ -275,6 +323,8 @@ struct SurfaceParams {
275 return pixels * GetFormatBpp(pixel_format) / CHAR_BIT; 323 return pixels * GetFormatBpp(pixel_format) / CHAR_BIT;
276 } 324 }
277 325
326 VAddr GetCpuAddr() const;
327
278 bool ExactMatch(const SurfaceParams& other_surface) const; 328 bool ExactMatch(const SurfaceParams& other_surface) const;
279 bool CanSubRect(const SurfaceParams& sub_surface) const; 329 bool CanSubRect(const SurfaceParams& sub_surface) const;
280 bool CanExpand(const SurfaceParams& expanded_surface) const; 330 bool CanExpand(const SurfaceParams& expanded_surface) const;
@@ -283,8 +333,9 @@ struct SurfaceParams {
283 MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const; 333 MathUtil::Rectangle<u32> GetSubRect(const SurfaceParams& sub_surface) const;
284 MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const; 334 MathUtil::Rectangle<u32> GetScaledSubRect(const SurfaceParams& sub_surface) const;
285 335
286 VAddr addr = 0; 336 Tegra::GPUVAddr addr = 0;
287 VAddr end = 0; 337 Tegra::GPUVAddr end = 0;
338 boost::optional<VAddr> cpu_addr;
288 u64 size = 0; 339 u64 size = 0;
289 340
290 u32 width = 0; 341 u32 width = 0;
@@ -323,15 +374,15 @@ struct CachedSurface : SurfaceParams {
323 if (format == PixelFormat::Invalid) 374 if (format == PixelFormat::Invalid)
324 return 0; 375 return 0;
325 376
326 return SurfaceParams::GetFormatBpp(format) / 8; 377 return SurfaceParams::GetFormatBpp(format) / CHAR_BIT;
327 } 378 }
328 379
329 std::unique_ptr<u8[]> gl_buffer; 380 std::unique_ptr<u8[]> gl_buffer;
330 size_t gl_buffer_size = 0; 381 size_t gl_buffer_size = 0;
331 382
332 // Read/Write data in Switch memory to/from gl_buffer 383 // Read/Write data in Switch memory to/from gl_buffer
333 void LoadGLBuffer(VAddr load_start, VAddr load_end); 384 void LoadGLBuffer(Tegra::GPUVAddr load_start, Tegra::GPUVAddr load_end);
334 void FlushGLBuffer(VAddr flush_start, VAddr flush_end); 385 void FlushGLBuffer(Tegra::GPUVAddr flush_start, Tegra::GPUVAddr flush_end);
335 386
336 // Upload/Download data in gl_buffer in/to this surface's texture 387 // Upload/Download data in gl_buffer in/to this surface's texture
337 void UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle, 388 void UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint read_fb_handle,
@@ -360,6 +411,9 @@ public:
360 Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale, 411 Surface GetSurface(const SurfaceParams& params, ScaleMatch match_res_scale,
361 bool load_if_create); 412 bool load_if_create);
362 413
414 /// Tries to find a framebuffer GPU address based on the provided CPU address
415 boost::optional<Tegra::GPUVAddr> TryFindFramebufferGpuAddress(VAddr cpu_addr) const;
416
363 /// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from 417 /// Attempt to find a subrect (resolution scaled) of a surface, otherwise loads a texture from
364 /// Switch memory to OpenGL and caches it (if not already cached) 418 /// Switch memory to OpenGL and caches it (if not already cached)
365 SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale, 419 SurfaceRect_Tuple GetSurfaceSubRect(const SurfaceParams& params, ScaleMatch match_res_scale,
@@ -379,10 +433,10 @@ public:
379 SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params); 433 SurfaceRect_Tuple GetTexCopySurface(const SurfaceParams& params);
380 434
381 /// Write any cached resources overlapping the region back to memory (if dirty) 435 /// Write any cached resources overlapping the region back to memory (if dirty)
382 void FlushRegion(VAddr addr, u64 size, Surface flush_surface = nullptr); 436 void FlushRegion(Tegra::GPUVAddr addr, u64 size, Surface flush_surface = nullptr);
383 437
384 /// Mark region as being invalidated by region_owner (nullptr if Switch memory) 438 /// Mark region as being invalidated by region_owner (nullptr if Switch memory)
385 void InvalidateRegion(VAddr addr, u64 size, const Surface& region_owner); 439 void InvalidateRegion(Tegra::GPUVAddr addr, u64 size, const Surface& region_owner);
386 440
387 /// Flush all cached resources tracked by this cache manager 441 /// Flush all cached resources tracked by this cache manager
388 void FlushAll(); 442 void FlushAll();
@@ -391,7 +445,7 @@ private:
391 void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface); 445 void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface);
392 446
393 /// Update surface's texture for given region when necessary 447 /// Update surface's texture for given region when necessary
394 void ValidateSurface(const Surface& surface, VAddr addr, u64 size); 448 void ValidateSurface(const Surface& surface, Tegra::GPUVAddr addr, u64 size);
395 449
396 /// Create a new surface 450 /// Create a new surface
397 Surface CreateSurface(const SurfaceParams& params); 451 Surface CreateSurface(const SurfaceParams& params);
@@ -403,7 +457,7 @@ private:
403 void UnregisterSurface(const Surface& surface); 457 void UnregisterSurface(const Surface& surface);
404 458
405 /// Increase/decrease the number of surface in pages touching the specified region 459 /// Increase/decrease the number of surface in pages touching the specified region
406 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta); 460 void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta);
407 461
408 SurfaceCache surface_cache; 462 SurfaceCache surface_cache;
409 PageMap cached_pages; 463 PageMap cached_pages;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 086424395..3dffb205d 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -519,7 +519,7 @@ private:
519 } 519 }
520 break; 520 break;
521 } 521 }
522 case OpCode::Type::FloatPredicate: { 522 case OpCode::Type::FloatSetPredicate: {
523 std::string op_a = instr.fsetp.neg_a ? "-" : ""; 523 std::string op_a = instr.fsetp.neg_a ? "-" : "";
524 op_a += GetRegister(instr.gpr8); 524 op_a += GetRegister(instr.gpr8);
525 525
@@ -570,6 +570,59 @@ private:
570 } 570 }
571 break; 571 break;
572 } 572 }
573 case OpCode::Type::FloatSet: {
574 std::string dest = GetRegister(instr.gpr0);
575 std::string op_a = instr.fset.neg_a ? "-" : "";
576 op_a += GetRegister(instr.gpr8);
577
578 if (instr.fset.abs_a) {
579 op_a = "abs(" + op_a + ')';
580 }
581
582 std::string op_b = instr.fset.neg_b ? "-" : "";
583
584 if (instr.is_b_imm) {
585 std::string imm = GetImmediate19(instr);
586 if (instr.fset.neg_imm)
587 op_b += "(-" + imm + ')';
588 else
589 op_b += imm;
590 } else {
591 if (instr.is_b_gpr) {
592 op_b += GetRegister(instr.gpr20);
593 } else {
594 op_b += GetUniform(instr.uniform);
595 }
596 }
597
598 if (instr.fset.abs_b) {
599 op_b = "abs(" + op_b + ")";
600 }
601
602 using Tegra::Shader::Pred;
603 ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
604 "Compound predicates are not implemented");
605
606 // The fset instruction sets a register to 1.0 if the condition is true, and to 0
607 // otherwise.
608 using Tegra::Shader::PredCondition;
609 switch (instr.fset.cond) {
610 case PredCondition::LessThan:
611 SetDest(0, dest, "((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1);
612 break;
613 case PredCondition::Equal:
614 SetDest(0, dest, "((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
615 break;
616 case PredCondition::GreaterThan:
617 SetDest(0, dest, "((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
618 break;
619 default:
620 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
621 static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
622 UNREACHABLE();
623 }
624 break;
625 }
573 default: { 626 default: {
574 switch (opcode->GetId()) { 627 switch (opcode->GetId()) {
575 case OpCode::Id::EXIT: { 628 case OpCode::Id::EXIT: {
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index ab0acb20a..77d1692f4 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -152,7 +152,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
152 screen_info.display_texture = screen_info.texture.resource.handle; 152 screen_info.display_texture = screen_info.texture.resource.handle;
153 screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); 153 screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
154 154
155 Rasterizer()->FlushRegion(framebuffer_addr, size_in_bytes); 155 Memory::RasterizerFlushVirtualRegion(framebuffer_addr, size_in_bytes,
156 Memory::FlushMode::Flush);
156 157
157 VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4, 158 VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4,
158 Memory::GetPointer(framebuffer_addr), 159 Memory::GetPointer(framebuffer_addr),
@@ -269,10 +270,9 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
269 GLint internal_format; 270 GLint internal_format;
270 switch (framebuffer.pixel_format) { 271 switch (framebuffer.pixel_format) {
271 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 272 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
272 // Use RGBA8 and swap in the fragment shader
273 internal_format = GL_RGBA; 273 internal_format = GL_RGBA;
274 texture.gl_format = GL_RGBA; 274 texture.gl_format = GL_RGBA;
275 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8; 275 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
276 gl_framebuffer_data.resize(texture.width * texture.height * 4); 276 gl_framebuffer_data.resize(texture.width * texture.height * 4);
277 break; 277 break;
278 default: 278 default:
@@ -295,17 +295,18 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
295 const auto& texcoords = screen_info.display_texcoords; 295 const auto& texcoords = screen_info.display_texcoords;
296 auto left = texcoords.left; 296 auto left = texcoords.left;
297 auto right = texcoords.right; 297 auto right = texcoords.right;
298 if (framebuffer_transform_flags != Tegra::FramebufferConfig::TransformFlags::Unset) 298 if (framebuffer_transform_flags != Tegra::FramebufferConfig::TransformFlags::Unset) {
299 if (framebuffer_transform_flags == Tegra::FramebufferConfig::TransformFlags::FlipV) { 299 if (framebuffer_transform_flags == Tegra::FramebufferConfig::TransformFlags::FlipV) {
300 // Flip the framebuffer vertically 300 // Flip the framebuffer vertically
301 left = texcoords.right; 301 left = texcoords.right;
302 right = texcoords.left; 302 right = texcoords.left;
303 } else { 303 } else {
304 // Other transformations are unsupported 304 // Other transformations are unsupported
305 LOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags=%d", 305 NGLOG_CRITICAL(Render_OpenGL, "Unsupported framebuffer_transform_flags={}",
306 framebuffer_transform_flags); 306 static_cast<u32>(framebuffer_transform_flags));
307 UNIMPLEMENTED(); 307 UNIMPLEMENTED();
308 } 308 }
309 }
309 310
310 std::array<ScreenRectVertex, 4> vertices = {{ 311 std::array<ScreenRectVertex, 4> vertices = {{
311 ScreenRectVertex(x, y, texcoords.top, left), 312 ScreenRectVertex(x, y, texcoords.top, left),
@@ -427,9 +428,9 @@ bool RendererOpenGL::Init() {
427 const char* gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))}; 428 const char* gpu_vendor{reinterpret_cast<char const*>(glGetString(GL_VENDOR))};
428 const char* gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))}; 429 const char* gpu_model{reinterpret_cast<char const*>(glGetString(GL_RENDERER))};
429 430
430 LOG_INFO(Render_OpenGL, "GL_VERSION: %s", gl_version); 431 NGLOG_INFO(Render_OpenGL, "GL_VERSION: {}", gl_version);
431 LOG_INFO(Render_OpenGL, "GL_VENDOR: %s", gpu_vendor); 432 NGLOG_INFO(Render_OpenGL, "GL_VENDOR: {}", gpu_vendor);
432 LOG_INFO(Render_OpenGL, "GL_RENDERER: %s", gpu_model); 433 NGLOG_INFO(Render_OpenGL, "GL_RENDERER: {}", gpu_model);
433 434
434 Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Vendor", gpu_vendor); 435 Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Vendor", gpu_vendor);
435 Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Model", gpu_model); 436 Core::Telemetry().AddField(Telemetry::FieldType::UserSystem, "GPU_Model", gpu_model);
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index e0509f0ce..8b39b2bdf 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -4,6 +4,7 @@
4 4
5#include <cstring> 5#include <cstring>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "core/memory.h"
7#include "video_core/textures/decoders.h" 8#include "video_core/textures/decoders.h"
8#include "video_core/textures/texture.h" 9#include "video_core/textures/texture.h"
9 10
@@ -26,9 +27,8 @@ static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel,
26 return address; 27 return address;
27} 28}
28 29
29static void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel, 30void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
30 u8* swizzled_data, u8* unswizzled_data, bool unswizzle, 31 u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height) {
31 u32 block_height) {
32 u8* data_ptrs[2]; 32 u8* data_ptrs[2];
33 for (unsigned y = 0; y < height; ++y) { 33 for (unsigned y = 0; y < height; ++y) {
34 for (unsigned x = 0; x < width; ++x) { 34 for (unsigned x = 0; x < width; ++x) {
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index a700911cf..2562c4b06 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -17,6 +17,10 @@ namespace Texture {
17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height, 17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
18 u32 block_height = TICEntry::DefaultBlockHeight); 18 u32 block_height = TICEntry::DefaultBlockHeight);
19 19
20/// Copies texture data from a buffer and performs swizzling/unswizzling as necessary.
21void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
22 u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height);
23
20/** 24/**
21 * Decodes an unswizzled texture into a A8R8G8B8 texture. 25 * Decodes an unswizzled texture into a A8R8G8B8 texture.
22 */ 26 */
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 289140f31..89dc8ed1e 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -24,9 +24,9 @@ bool Init(EmuWindow* emu_window) {
24 g_renderer = std::make_unique<RendererOpenGL>(); 24 g_renderer = std::make_unique<RendererOpenGL>();
25 g_renderer->SetWindow(g_emu_window); 25 g_renderer->SetWindow(g_emu_window);
26 if (g_renderer->Init()) { 26 if (g_renderer->Init()) {
27 LOG_DEBUG(Render, "initialized OK"); 27 NGLOG_DEBUG(Render, "initialized OK");
28 } else { 28 } else {
29 LOG_CRITICAL(Render, "initialization failed !"); 29 NGLOG_CRITICAL(Render, "initialization failed !");
30 return false; 30 return false;
31 } 31 }
32 return true; 32 return true;
@@ -36,7 +36,7 @@ bool Init(EmuWindow* emu_window) {
36void Shutdown() { 36void Shutdown() {
37 g_renderer.reset(); 37 g_renderer.reset();
38 38
39 LOG_DEBUG(Render, "shutdown OK"); 39 NGLOG_DEBUG(Render, "shutdown OK");
40} 40}
41 41
42} // namespace VideoCore 42} // namespace VideoCore
diff --git a/src/yuzu/debugger/graphics/graphics_surface.cpp b/src/yuzu/debugger/graphics/graphics_surface.cpp
index 1e4844b57..1fbca8ad0 100644
--- a/src/yuzu/debugger/graphics/graphics_surface.cpp
+++ b/src/yuzu/debugger/graphics/graphics_surface.cpp
@@ -25,6 +25,8 @@ static Tegra::Texture::TextureFormat ConvertToTextureFormat(
25 switch (render_target_format) { 25 switch (render_target_format) {
26 case Tegra::RenderTargetFormat::RGBA8_UNORM: 26 case Tegra::RenderTargetFormat::RGBA8_UNORM:
27 return Tegra::Texture::TextureFormat::A8R8G8B8; 27 return Tegra::Texture::TextureFormat::A8R8G8B8;
28 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
29 return Tegra::Texture::TextureFormat::A2B10G10R10;
28 default: 30 default:
29 UNIMPLEMENTED_MSG("Unimplemented RT format"); 31 UNIMPLEMENTED_MSG("Unimplemented RT format");
30 } 32 }
@@ -376,10 +378,10 @@ void GraphicsSurfaceWidget::OnUpdate() {
376 // TODO: Implement a good way to visualize alpha components! 378 // TODO: Implement a good way to visualize alpha components!
377 379
378 QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); 380 QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32);
379 VAddr address = gpu.memory_manager->PhysicalToVirtualAddress(surface_address); 381 boost::optional<VAddr> address = gpu.memory_manager->GpuToCpuAddress(surface_address);
380 382
381 auto unswizzled_data = 383 auto unswizzled_data =
382 Tegra::Texture::UnswizzleTexture(address, surface_format, surface_width, surface_height); 384 Tegra::Texture::UnswizzleTexture(*address, surface_format, surface_width, surface_height);
383 385
384 auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format, 386 auto texture_data = Tegra::Texture::DecodeTexture(unswizzled_data, surface_format,
385 surface_width, surface_height); 387 surface_width, surface_height);
@@ -435,9 +437,9 @@ void GraphicsSurfaceWidget::SaveSurface() {
435 pixmap->save(&file, "PNG"); 437 pixmap->save(&file, "PNG");
436 } else if (selectedFilter == bin_filter) { 438 } else if (selectedFilter == bin_filter) {
437 auto& gpu = Core::System::GetInstance().GPU(); 439 auto& gpu = Core::System::GetInstance().GPU();
438 VAddr address = gpu.memory_manager->PhysicalToVirtualAddress(surface_address); 440 boost::optional<VAddr> address = gpu.memory_manager->GpuToCpuAddress(surface_address);
439 441
440 const u8* buffer = Memory::GetPointer(address); 442 const u8* buffer = Memory::GetPointer(*address);
441 ASSERT_MSG(buffer != nullptr, "Memory not accessible"); 443 ASSERT_MSG(buffer != nullptr, "Memory not accessible");
442 444
443 QFile file(filename); 445 QFile file(filename);
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index cae2864e5..acc4c2e0b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -6,8 +6,8 @@
6#include "yuzu/util/util.h" 6#include "yuzu/util/util.h"
7 7
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/kernel/condition_variable.h"
10#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/kernel/timer.h" 13#include "core/hle/kernel/timer.h"
@@ -67,6 +67,29 @@ QString WaitTreeText::GetText() const {
67 return text; 67 return text;
68} 68}
69 69
70WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) {
71 mutex_value = Memory::Read32(mutex_address);
72 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask);
73 owner = Kernel::g_handle_table.Get<Kernel::Thread>(owner_handle);
74}
75
76QString WaitTreeMutexInfo::GetText() const {
77 return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char('0'));
78}
79
80std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const {
81 std::vector<std::unique_ptr<WaitTreeItem>> list;
82
83 bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
84
85 list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters)));
86 list.push_back(std::make_unique<WaitTreeText>(
87 tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char('0'))));
88 if (owner != nullptr)
89 list.push_back(std::make_unique<WaitTreeThread>(*owner));
90 return list;
91}
92
70WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {} 93WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {}
71 94
72bool WaitTreeExpandableItem::IsExpandable() const { 95bool WaitTreeExpandableItem::IsExpandable() const {
@@ -84,11 +107,6 @@ std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitO
84 switch (object.GetHandleType()) { 107 switch (object.GetHandleType()) {
85 case Kernel::HandleType::Event: 108 case Kernel::HandleType::Event:
86 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object)); 109 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object));
87 case Kernel::HandleType::Mutex:
88 return std::make_unique<WaitTreeMutex>(static_cast<const Kernel::Mutex&>(object));
89 case Kernel::HandleType::ConditionVariable:
90 return std::make_unique<WaitTreeConditionVariable>(
91 static_cast<const Kernel::ConditionVariable&>(object));
92 case Kernel::HandleType::Timer: 110 case Kernel::HandleType::Timer:
93 return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); 111 return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));
94 case Kernel::HandleType::Thread: 112 case Kernel::HandleType::Thread:
@@ -160,6 +178,9 @@ QString WaitTreeThread::GetText() const {
160 case THREADSTATUS_WAIT_SYNCH_ANY: 178 case THREADSTATUS_WAIT_SYNCH_ANY:
161 status = tr("waiting for objects"); 179 status = tr("waiting for objects");
162 break; 180 break;
181 case THREADSTATUS_WAIT_MUTEX:
182 status = tr("waiting for mutex");
183 break;
163 case THREADSTATUS_DORMANT: 184 case THREADSTATUS_DORMANT:
164 status = tr("dormant"); 185 status = tr("dormant");
165 break; 186 break;
@@ -186,6 +207,7 @@ QColor WaitTreeThread::GetColor() const {
186 return QColor(Qt::GlobalColor::darkYellow); 207 return QColor(Qt::GlobalColor::darkYellow);
187 case THREADSTATUS_WAIT_SYNCH_ALL: 208 case THREADSTATUS_WAIT_SYNCH_ALL:
188 case THREADSTATUS_WAIT_SYNCH_ANY: 209 case THREADSTATUS_WAIT_SYNCH_ANY:
210 case THREADSTATUS_WAIT_MUTEX:
189 return QColor(Qt::GlobalColor::red); 211 return QColor(Qt::GlobalColor::red);
190 case THREADSTATUS_DORMANT: 212 case THREADSTATUS_DORMANT:
191 return QColor(Qt::GlobalColor::darkCyan); 213 return QColor(Qt::GlobalColor::darkCyan);
@@ -225,11 +247,11 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
225 list.push_back(std::make_unique<WaitTreeText>( 247 list.push_back(std::make_unique<WaitTreeText>(
226 tr("last running ticks = %1").arg(thread.last_running_ticks))); 248 tr("last running ticks = %1").arg(thread.last_running_ticks)));
227 249
228 if (thread.held_mutexes.empty()) { 250 if (thread.mutex_wait_address != 0)
229 list.push_back(std::make_unique<WaitTreeText>(tr("not holding mutex"))); 251 list.push_back(std::make_unique<WaitTreeMutexInfo>(thread.mutex_wait_address));
230 } else { 252 else
231 list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); 253 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
232 } 254
233 if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY || 255 if (thread.status == THREADSTATUS_WAIT_SYNCH_ANY ||
234 thread.status == THREADSTATUS_WAIT_SYNCH_ALL) { 256 thread.status == THREADSTATUS_WAIT_SYNCH_ALL) {
235 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, 257 list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects,
@@ -250,33 +272,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
250 return list; 272 return list;
251} 273}
252 274
253WaitTreeMutex::WaitTreeMutex(const Kernel::Mutex& object) : WaitTreeWaitObject(object) {}
254
255std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutex::GetChildren() const {
256 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
257
258 const auto& mutex = static_cast<const Kernel::Mutex&>(object);
259 if (mutex.GetHasWaiters()) {
260 list.push_back(std::make_unique<WaitTreeText>(tr("locked by thread:")));
261 list.push_back(std::make_unique<WaitTreeThread>(*mutex.GetHoldingThread()));
262 } else {
263 list.push_back(std::make_unique<WaitTreeText>(tr("free")));
264 }
265 return list;
266}
267
268WaitTreeConditionVariable::WaitTreeConditionVariable(const Kernel::ConditionVariable& object)
269 : WaitTreeWaitObject(object) {}
270
271std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeConditionVariable::GetChildren() const {
272 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
273
274 const auto& condition_variable = static_cast<const Kernel::ConditionVariable&>(object);
275 list.push_back(std::make_unique<WaitTreeText>(
276 tr("available count = %1").arg(condition_variable.GetAvailableCount())));
277 return list;
278}
279
280WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {} 275WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {}
281 276
282std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const { 277std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
@@ -293,21 +288,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
293 return list; 288 return list;
294} 289}
295 290
296WaitTreeMutexList::WaitTreeMutexList(
297 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list)
298 : mutex_list(list) {}
299
300QString WaitTreeMutexList::GetText() const {
301 return tr("holding mutexes");
302}
303
304std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexList::GetChildren() const {
305 std::vector<std::unique_ptr<WaitTreeItem>> list(mutex_list.size());
306 std::transform(mutex_list.begin(), mutex_list.end(), list.begin(),
307 [](const auto& t) { return std::make_unique<WaitTreeMutex>(*t); });
308 return list;
309}
310
311WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) 291WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
312 : thread_list(list) {} 292 : thread_list(list) {}
313 293
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index e538174eb..300ba9ae4 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -16,8 +16,6 @@ class EmuThread;
16namespace Kernel { 16namespace Kernel {
17class WaitObject; 17class WaitObject;
18class Event; 18class Event;
19class Mutex;
20class ConditionVariable;
21class Thread; 19class Thread;
22class Timer; 20class Timer;
23} // namespace Kernel 21} // namespace Kernel
@@ -61,6 +59,20 @@ public:
61 bool IsExpandable() const override; 59 bool IsExpandable() const override;
62}; 60};
63 61
62class WaitTreeMutexInfo : public WaitTreeExpandableItem {
63 Q_OBJECT
64public:
65 explicit WaitTreeMutexInfo(VAddr mutex_address);
66 QString GetText() const override;
67 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
68
69private:
70 VAddr mutex_address;
71 u32 mutex_value;
72 Kernel::Handle owner_handle;
73 Kernel::SharedPtr<Kernel::Thread> owner;
74};
75
64class WaitTreeWaitObject : public WaitTreeExpandableItem { 76class WaitTreeWaitObject : public WaitTreeExpandableItem {
65 Q_OBJECT 77 Q_OBJECT
66public: 78public:
@@ -104,20 +116,6 @@ public:
104 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 116 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
105}; 117};
106 118
107class WaitTreeMutex : public WaitTreeWaitObject {
108 Q_OBJECT
109public:
110 explicit WaitTreeMutex(const Kernel::Mutex& object);
111 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
112};
113
114class WaitTreeConditionVariable : public WaitTreeWaitObject {
115 Q_OBJECT
116public:
117 explicit WaitTreeConditionVariable(const Kernel::ConditionVariable& object);
118 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
119};
120
121class WaitTreeTimer : public WaitTreeWaitObject { 119class WaitTreeTimer : public WaitTreeWaitObject {
122 Q_OBJECT 120 Q_OBJECT
123public: 121public:
@@ -125,19 +123,6 @@ public:
125 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 123 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
126}; 124};
127 125
128class WaitTreeMutexList : public WaitTreeExpandableItem {
129 Q_OBJECT
130public:
131 explicit WaitTreeMutexList(
132 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list);
133
134 QString GetText() const override;
135 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
136
137private:
138 const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& mutex_list;
139};
140
141class WaitTreeThreadList : public WaitTreeExpandableItem { 126class WaitTreeThreadList : public WaitTreeExpandableItem {
142 Q_OBJECT 127 Q_OBJECT
143public: 128public: