summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt5
-rw-r--r--src/audio_core/sdl2_sink.cpp163
-rw-r--r--src/audio_core/sdl2_sink.h29
-rw-r--r--src/audio_core/sink_details.cpp10
-rw-r--r--src/common/detached_tasks.cpp2
-rw-r--r--src/common/fs/file.cpp4
-rw-r--r--src/common/fs/file.h12
-rw-r--r--src/common/fs/fs.cpp5
-rw-r--r--src/common/fs/fs.h30
-rw-r--r--src/common/host_memory.cpp2
-rw-r--r--src/common/logging/backend.cpp4
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/common/settings.h2
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp3
-rw-r--r--src/core/core.cpp5
-rw-r--r--src/core/file_sys/system_archive/system_version.cpp48
-rw-r--r--src/core/file_sys/vfs_real.cpp7
-rw-r--r--src/core/hle/api_version.h38
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp1
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp3
-rw-r--r--src/core/hle/service/spl/csrng.cpp2
-rw-r--r--src/core/hle/service/spl/module.cpp124
-rw-r--r--src/core/hle/service/spl/module.h13
-rw-r--r--src/core/hle/service/spl/spl.cpp84
-rw-r--r--src/core/hle/service/spl/spl_results.h29
-rw-r--r--src/core/hle/service/spl/spl_types.h230
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp2
-rw-r--r--src/input_common/mouse/mouse_input.cpp16
-rw-r--r--src/input_common/mouse/mouse_input.h6
-rw-r--r--src/video_core/rasterizer_interface.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp18
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h9
-rw-r--r--src/video_core/texture_cache/util.cpp10
-rw-r--r--src/video_core/vulkan_common/nsight_aftermath_tracker.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.cpp8
-rw-r--r--src/web_service/web_backend.cpp3
-rw-r--r--src/yuzu/bootmanager.cpp12
-rw-r--r--src/yuzu/bootmanager.h6
-rw-r--r--src/yuzu/configuration/config.cpp11
-rw-r--r--src/yuzu/configuration/config.h2
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp9
-rw-r--r--src/yuzu/configuration/configure_cpu.h1
-rw-r--r--src/yuzu/configuration/configure_cpu.ui12
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp6
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h1
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui18
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp2
-rw-r--r--src/yuzu/configuration/configure_per_game.ui7
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp4
-rw-r--r--src/yuzu/main.cpp30
-rw-r--r--src/yuzu_cmd/config.cpp2
-rw-r--r--src/yuzu_cmd/default_ini.h8
-rw-r--r--src/yuzu_cmd/yuzu.cpp2
61 files changed, 908 insertions, 186 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index a0ae07752..d25a1a645 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -42,6 +42,7 @@ add_library(audio_core STATIC
42 voice_context.h 42 voice_context.h
43 43
44 $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h> 44 $<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h>
45 $<$<BOOL:${ENABLE_SDL2}>:sdl2_sink.cpp sdl2_sink.h>
45) 46)
46 47
47create_target_directory_groups(audio_core) 48create_target_directory_groups(audio_core)
@@ -71,3 +72,7 @@ if(ENABLE_CUBEB)
71 target_link_libraries(audio_core PRIVATE cubeb) 72 target_link_libraries(audio_core PRIVATE cubeb)
72 target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) 73 target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
73endif() 74endif()
75if(ENABLE_SDL2)
76 target_link_libraries(audio_core PRIVATE SDL2)
77 target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
78endif()
diff --git a/src/audio_core/sdl2_sink.cpp b/src/audio_core/sdl2_sink.cpp
new file mode 100644
index 000000000..62d3716a6
--- /dev/null
+++ b/src/audio_core/sdl2_sink.cpp
@@ -0,0 +1,163 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <atomic>
7#include <cstring>
8#include "audio_core/sdl2_sink.h"
9#include "audio_core/stream.h"
10#include "audio_core/time_stretch.h"
11#include "common/assert.h"
12#include "common/logging/log.h"
13//#include "common/settings.h"
14
15// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
16#ifdef __clang__
17#pragma clang diagnostic push
18#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
19#endif
20#include <SDL.h>
21#ifdef __clang__
22#pragma clang diagnostic pop
23#endif
24
25namespace AudioCore {
26
27class SDLSinkStream final : public SinkStream {
28public:
29 SDLSinkStream(u32 sample_rate, u32 num_channels_, const std::string& output_device)
30 : num_channels{std::min(num_channels_, 6u)}, time_stretch{sample_rate, num_channels} {
31
32 SDL_AudioSpec spec;
33 spec.freq = sample_rate;
34 spec.channels = static_cast<u8>(num_channels);
35 spec.format = AUDIO_S16SYS;
36 spec.samples = 4096;
37 spec.callback = nullptr;
38
39 SDL_AudioSpec obtained;
40 if (output_device.empty()) {
41 dev = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained, 0);
42 } else {
43 dev = SDL_OpenAudioDevice(output_device.c_str(), 0, &spec, &obtained, 0);
44 }
45
46 if (dev == 0) {
47 LOG_CRITICAL(Audio_Sink, "Error opening sdl audio device: {}", SDL_GetError());
48 return;
49 }
50
51 SDL_PauseAudioDevice(dev, 0);
52 }
53
54 ~SDLSinkStream() override {
55 if (dev == 0) {
56 return;
57 }
58
59 SDL_CloseAudioDevice(dev);
60 }
61
62 void EnqueueSamples(u32 source_num_channels, const std::vector<s16>& samples) override {
63 if (source_num_channels > num_channels) {
64 // Downsample 6 channels to 2
65 ASSERT_MSG(source_num_channels == 6, "Channel count must be 6");
66
67 std::vector<s16> buf;
68 buf.reserve(samples.size() * num_channels / source_num_channels);
69 for (std::size_t i = 0; i < samples.size(); i += source_num_channels) {
70 // Downmixing implementation taken from the ATSC standard
71 const s16 left{samples[i + 0]};
72 const s16 right{samples[i + 1]};
73 const s16 center{samples[i + 2]};
74 const s16 surround_left{samples[i + 4]};
75 const s16 surround_right{samples[i + 5]};
76 // Not used in the ATSC reference implementation
77 [[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]};
78
79 constexpr s32 clev{707}; // center mixing level coefficient
80 constexpr s32 slev{707}; // surround mixing level coefficient
81
82 buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
83 (slev * surround_left / 1000)));
84 buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
85 (slev * surround_right / 1000)));
86 }
87 int ret = SDL_QueueAudio(dev, static_cast<const void*>(buf.data()),
88 static_cast<u32>(buf.size() * sizeof(s16)));
89 if (ret < 0)
90 LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
91 return;
92 }
93
94 int ret = SDL_QueueAudio(dev, static_cast<const void*>(samples.data()),
95 static_cast<u32>(samples.size() * sizeof(s16)));
96 if (ret < 0)
97 LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
98 }
99
100 std::size_t SamplesInQueue(u32 channel_count) const override {
101 if (dev == 0)
102 return 0;
103
104 return SDL_GetQueuedAudioSize(dev) / (channel_count * sizeof(s16));
105 }
106
107 void Flush() override {
108 should_flush = true;
109 }
110
111 u32 GetNumChannels() const {
112 return num_channels;
113 }
114
115private:
116 SDL_AudioDeviceID dev = 0;
117 u32 num_channels{};
118 std::atomic<bool> should_flush{};
119 TimeStretcher time_stretch;
120};
121
122SDLSink::SDLSink(std::string_view target_device_name) {
123 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
124 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
125 LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
126 return;
127 }
128 }
129
130 if (target_device_name != auto_device_name && !target_device_name.empty()) {
131 output_device = target_device_name;
132 } else {
133 output_device.clear();
134 }
135}
136
137SDLSink::~SDLSink() = default;
138
139SinkStream& SDLSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, const std::string&) {
140 sink_streams.push_back(
141 std::make_unique<SDLSinkStream>(sample_rate, num_channels, output_device));
142 return *sink_streams.back();
143}
144
145std::vector<std::string> ListSDLSinkDevices() {
146 std::vector<std::string> device_list;
147
148 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
149 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
150 LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
151 return {};
152 }
153 }
154
155 const int device_count = SDL_GetNumAudioDevices(0);
156 for (int i = 0; i < device_count; ++i) {
157 device_list.emplace_back(SDL_GetAudioDeviceName(i, 0));
158 }
159
160 return device_list;
161}
162
163} // namespace AudioCore
diff --git a/src/audio_core/sdl2_sink.h b/src/audio_core/sdl2_sink.h
new file mode 100644
index 000000000..8ec1526d8
--- /dev/null
+++ b/src/audio_core/sdl2_sink.h
@@ -0,0 +1,29 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8#include <vector>
9
10#include "audio_core/sink.h"
11
12namespace AudioCore {
13
14class SDLSink final : public Sink {
15public:
16 explicit SDLSink(std::string_view device_id);
17 ~SDLSink() override;
18
19 SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels,
20 const std::string& name) override;
21
22private:
23 std::string output_device;
24 std::vector<SinkStreamPtr> sink_streams;
25};
26
27std::vector<std::string> ListSDLSinkDevices();
28
29} // namespace AudioCore
diff --git a/src/audio_core/sink_details.cpp b/src/audio_core/sink_details.cpp
index a848eb1c9..de10aecd2 100644
--- a/src/audio_core/sink_details.cpp
+++ b/src/audio_core/sink_details.cpp
@@ -11,6 +11,9 @@
11#ifdef HAVE_CUBEB 11#ifdef HAVE_CUBEB
12#include "audio_core/cubeb_sink.h" 12#include "audio_core/cubeb_sink.h"
13#endif 13#endif
14#ifdef HAVE_SDL2
15#include "audio_core/sdl2_sink.h"
16#endif
14#include "common/logging/log.h" 17#include "common/logging/log.h"
15 18
16namespace AudioCore { 19namespace AudioCore {
@@ -36,6 +39,13 @@ constexpr SinkDetails sink_details[] = {
36 }, 39 },
37 &ListCubebSinkDevices}, 40 &ListCubebSinkDevices},
38#endif 41#endif
42#ifdef HAVE_SDL2
43 SinkDetails{"sdl2",
44 [](std::string_view device_id) -> std::unique_ptr<Sink> {
45 return std::make_unique<SDLSink>(device_id);
46 },
47 &ListSDLSinkDevices},
48#endif
39 SinkDetails{"null", 49 SinkDetails{"null",
40 [](std::string_view device_id) -> std::unique_ptr<Sink> { 50 [](std::string_view device_id) -> std::unique_ptr<Sink> {
41 return std::make_unique<NullSink>(device_id); 51 return std::make_unique<NullSink>(device_id);
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp
index f2b4939df..c1362631e 100644
--- a/src/common/detached_tasks.cpp
+++ b/src/common/detached_tasks.cpp
@@ -21,6 +21,8 @@ void DetachedTasks::WaitForAllTasks() {
21} 21}
22 22
23DetachedTasks::~DetachedTasks() { 23DetachedTasks::~DetachedTasks() {
24 WaitForAllTasks();
25
24 std::unique_lock lock{mutex}; 26 std::unique_lock lock{mutex};
25 ASSERT(count == 0); 27 ASSERT(count == 0);
26 instance = nullptr; 28 instance = nullptr;
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp
index 710e88b39..077f34995 100644
--- a/src/common/fs/file.cpp
+++ b/src/common/fs/file.cpp
@@ -172,7 +172,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type)
172 172
173size_t WriteStringToFile(const std::filesystem::path& path, FileType type, 173size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
174 std::string_view string) { 174 std::string_view string) {
175 if (!IsFile(path)) { 175 if (Exists(path) && !IsFile(path)) {
176 return 0; 176 return 0;
177 } 177 }
178 178
@@ -183,7 +183,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
183 183
184size_t AppendStringToFile(const std::filesystem::path& path, FileType type, 184size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
185 std::string_view string) { 185 std::string_view string) {
186 if (!IsFile(path)) { 186 if (Exists(path) && !IsFile(path)) {
187 return 0; 187 return 0;
188 } 188 }
189 189
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index 0f10b6003..588fe619d 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -49,7 +49,7 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op
49 49
50/** 50/**
51 * Reads an entire file at path and returns a string of the contents read from the file. 51 * Reads an entire file at path and returns a string of the contents read from the file.
52 * If the filesystem object at path is not a file, this function returns an empty string. 52 * If the filesystem object at path is not a regular file, this function returns an empty string.
53 * 53 *
54 * @param path Filesystem path 54 * @param path Filesystem path
55 * @param type File type 55 * @param type File type
@@ -72,7 +72,8 @@ template <typename Path>
72/** 72/**
73 * Writes a string to a file at path and returns the number of characters successfully written. 73 * Writes a string to a file at path and returns the number of characters successfully written.
74 * If a file already exists at path, its contents will be erased. 74 * If a file already exists at path, its contents will be erased.
75 * If the filesystem object at path is not a file, this function returns 0. 75 * If a file does not exist at path, it creates and opens a new empty file for writing.
76 * If the filesystem object at path exists and is not a regular file, this function returns 0.
76 * 77 *
77 * @param path Filesystem path 78 * @param path Filesystem path
78 * @param type File type 79 * @param type File type
@@ -95,7 +96,8 @@ template <typename Path>
95 96
96/** 97/**
97 * Appends a string to a file at path and returns the number of characters successfully written. 98 * Appends a string to a file at path and returns the number of characters successfully written.
98 * If the filesystem object at path is not a file, this function returns 0. 99 * If a file does not exist at path, it creates and opens a new empty file for appending.
100 * If the filesystem object at path exists and is not a regular file, this function returns 0.
99 * 101 *
100 * @param path Filesystem path 102 * @param path Filesystem path
101 * @param type File type 103 * @param type File type
@@ -394,11 +396,11 @@ public:
394 [[nodiscard]] size_t WriteString(std::span<const char> string) const; 396 [[nodiscard]] size_t WriteString(std::span<const char> string) const;
395 397
396 /** 398 /**
397 * Flushes any unwritten buffered data into the file. 399 * Attempts to flush any unwritten buffered data into the file and flush the file into the disk.
398 * 400 *
399 * @returns True if the flush was successful, false otherwise. 401 * @returns True if the flush was successful, false otherwise.
400 */ 402 */
401 [[nodiscard]] bool Flush() const; 403 bool Flush() const;
402 404
403 /** 405 /**
404 * Resizes the file to a given size. 406 * Resizes the file to a given size.
diff --git a/src/common/fs/fs.cpp b/src/common/fs/fs.cpp
index d3159e908..9089cad67 100644
--- a/src/common/fs/fs.cpp
+++ b/src/common/fs/fs.cpp
@@ -135,8 +135,9 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File
135 return nullptr; 135 return nullptr;
136 } 136 }
137 137
138 if (!IsFile(path)) { 138 if (Exists(path) && !IsFile(path)) {
139 LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file", 139 LOG_ERROR(Common_Filesystem,
140 "Filesystem object at path={} exists and is not a regular file",
140 PathToUTF8String(path)); 141 PathToUTF8String(path));
141 return nullptr; 142 return nullptr;
142 } 143 }
diff --git a/src/common/fs/fs.h b/src/common/fs/fs.h
index f6f256349..183126de3 100644
--- a/src/common/fs/fs.h
+++ b/src/common/fs/fs.h
@@ -48,18 +48,18 @@ template <typename Path>
48 * 48 *
49 * Failures occur when: 49 * Failures occur when:
50 * - Input path is not valid 50 * - Input path is not valid
51 * - Filesystem object at path is not a file 51 * - Filesystem object at path is not a regular file
52 * - Filesystem at path is read only 52 * - Filesystem at path is read only
53 * 53 *
54 * @param path Filesystem path 54 * @param path Filesystem path
55 * 55 *
56 * @returns True if file removal succeeds or file does not exist, false otherwise. 56 * @returns True if file removal succeeds or file does not exist, false otherwise.
57 */ 57 */
58[[nodiscard]] bool RemoveFile(const std::filesystem::path& path); 58bool RemoveFile(const std::filesystem::path& path);
59 59
60#ifdef _WIN32 60#ifdef _WIN32
61template <typename Path> 61template <typename Path>
62[[nodiscard]] bool RemoveFile(const Path& path) { 62bool RemoveFile(const Path& path) {
63 if constexpr (IsChar<typename Path::value_type>) { 63 if constexpr (IsChar<typename Path::value_type>) {
64 return RemoveFile(ToU8String(path)); 64 return RemoveFile(ToU8String(path));
65 } else { 65 } else {
@@ -74,7 +74,7 @@ template <typename Path>
74 * Failures occur when: 74 * Failures occur when:
75 * - One or both input path(s) is not valid 75 * - One or both input path(s) is not valid
76 * - Filesystem object at old_path does not exist 76 * - Filesystem object at old_path does not exist
77 * - Filesystem object at old_path is not a file 77 * - Filesystem object at old_path is not a regular file
78 * - Filesystem object at new_path exists 78 * - Filesystem object at new_path exists
79 * - Filesystem at either path is read only 79 * - Filesystem at either path is read only
80 * 80 *
@@ -110,8 +110,8 @@ template <typename Path1, typename Path2>
110 * 110 *
111 * Failures occur when: 111 * Failures occur when:
112 * - Input path is not valid 112 * - Input path is not valid
113 * - Filesystem object at path is not a file 113 * - Filesystem object at path exists and is not a regular file
114 * - The file is not opened 114 * - The file is not open
115 * 115 *
116 * @param path Filesystem path 116 * @param path Filesystem path
117 * @param mode File access mode 117 * @param mode File access mode
@@ -251,11 +251,11 @@ template <typename Path>
251 * 251 *
252 * @returns True if directory removal succeeds or directory does not exist, false otherwise. 252 * @returns True if directory removal succeeds or directory does not exist, false otherwise.
253 */ 253 */
254[[nodiscard]] bool RemoveDir(const std::filesystem::path& path); 254bool RemoveDir(const std::filesystem::path& path);
255 255
256#ifdef _WIN32 256#ifdef _WIN32
257template <typename Path> 257template <typename Path>
258[[nodiscard]] bool RemoveDir(const Path& path) { 258bool RemoveDir(const Path& path) {
259 if constexpr (IsChar<typename Path::value_type>) { 259 if constexpr (IsChar<typename Path::value_type>) {
260 return RemoveDir(ToU8String(path)); 260 return RemoveDir(ToU8String(path));
261 } else { 261 } else {
@@ -276,11 +276,11 @@ template <typename Path>
276 * 276 *
277 * @returns True if the directory and all of its contents are removed successfully, false otherwise. 277 * @returns True if the directory and all of its contents are removed successfully, false otherwise.
278 */ 278 */
279[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path); 279bool RemoveDirRecursively(const std::filesystem::path& path);
280 280
281#ifdef _WIN32 281#ifdef _WIN32
282template <typename Path> 282template <typename Path>
283[[nodiscard]] bool RemoveDirRecursively(const Path& path) { 283bool RemoveDirRecursively(const Path& path) {
284 if constexpr (IsChar<typename Path::value_type>) { 284 if constexpr (IsChar<typename Path::value_type>) {
285 return RemoveDirRecursively(ToU8String(path)); 285 return RemoveDirRecursively(ToU8String(path));
286 } else { 286 } else {
@@ -301,11 +301,11 @@ template <typename Path>
301 * 301 *
302 * @returns True if all of the directory's contents are removed successfully, false otherwise. 302 * @returns True if all of the directory's contents are removed successfully, false otherwise.
303 */ 303 */
304[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path); 304bool RemoveDirContentsRecursively(const std::filesystem::path& path);
305 305
306#ifdef _WIN32 306#ifdef _WIN32
307template <typename Path> 307template <typename Path>
308[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) { 308bool RemoveDirContentsRecursively(const Path& path) {
309 if constexpr (IsChar<typename Path::value_type>) { 309 if constexpr (IsChar<typename Path::value_type>) {
310 return RemoveDirContentsRecursively(ToU8String(path)); 310 return RemoveDirContentsRecursively(ToU8String(path));
311 } else { 311 } else {
@@ -435,11 +435,13 @@ template <typename Path>
435#endif 435#endif
436 436
437/** 437/**
438 * Returns whether a filesystem object at path is a file. 438 * Returns whether a filesystem object at path is a regular file.
439 * A regular file is a file that stores text or binary data.
440 * It is not a directory, symlink, FIFO, socket, block device, or character device.
439 * 441 *
440 * @param path Filesystem path 442 * @param path Filesystem path
441 * 443 *
442 * @returns True if a filesystem object at path is a file, false otherwise. 444 * @returns True if a filesystem object at path is a regular file, false otherwise.
443 */ 445 */
444[[nodiscard]] bool IsFile(const std::filesystem::path& path); 446[[nodiscard]] bool IsFile(const std::filesystem::path& path);
445 447
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 8bd70abc7..2a5a7596c 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -34,7 +34,7 @@ constexpr size_t HugePageSize = 0x200000;
34 34
35// Manually imported for MinGW compatibility 35// Manually imported for MinGW compatibility
36#ifndef MEM_RESERVE_PLACEHOLDER 36#ifndef MEM_RESERVE_PLACEHOLDER
37#define MEM_RESERVE_PLACEHOLDER 0x0004000 37#define MEM_RESERVE_PLACEHOLDER 0x00040000
38#endif 38#endif
39#ifndef MEM_REPLACE_PLACEHOLDER 39#ifndef MEM_REPLACE_PLACEHOLDER
40#define MEM_REPLACE_PLACEHOLDER 0x00004000 40#define MEM_REPLACE_PLACEHOLDER 0x00004000
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index d5cff400f..47ce06478 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -159,7 +159,7 @@ FileBackend::FileBackend(const std::filesystem::path& filename) {
159 159
160 // Existence checks are done within the functions themselves. 160 // Existence checks are done within the functions themselves.
161 // We don't particularly care if these succeed or not. 161 // We don't particularly care if these succeed or not.
162 void(FS::RemoveFile(old_filename)); 162 FS::RemoveFile(old_filename);
163 void(FS::RenameFile(filename, old_filename)); 163 void(FS::RenameFile(filename, old_filename));
164 164
165 file = 165 file =
@@ -186,7 +186,7 @@ void FileBackend::Write(const Entry& entry) {
186 186
187 bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); 187 bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
188 if (entry.log_level >= Level::Error) { 188 if (entry.log_level >= Level::Error) {
189 void(file->Flush()); 189 file->Flush();
190 } 190 }
191} 191}
192 192
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index ab5cbe67b..e1bb4b7ff 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -123,6 +123,7 @@ void RestoreGlobalState(bool is_powered_on) {
123 values.cpu_accuracy.SetGlobal(true); 123 values.cpu_accuracy.SetGlobal(true);
124 values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); 124 values.cpuopt_unsafe_unfuse_fma.SetGlobal(true);
125 values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); 125 values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true);
126 values.cpuopt_unsafe_ignore_standard_fpcr.SetGlobal(true);
126 values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); 127 values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true);
127 values.cpuopt_unsafe_fastmem_check.SetGlobal(true); 128 values.cpuopt_unsafe_fastmem_check.SetGlobal(true);
128 129
diff --git a/src/common/settings.h b/src/common/settings.h
index a1c0bf3ad..82ec18e27 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -129,6 +129,7 @@ struct Values {
129 129
130 Setting<bool> cpuopt_unsafe_unfuse_fma; 130 Setting<bool> cpuopt_unsafe_unfuse_fma;
131 Setting<bool> cpuopt_unsafe_reduce_fp_error; 131 Setting<bool> cpuopt_unsafe_reduce_fp_error;
132 Setting<bool> cpuopt_unsafe_ignore_standard_fpcr;
132 Setting<bool> cpuopt_unsafe_inaccurate_nan; 133 Setting<bool> cpuopt_unsafe_inaccurate_nan;
133 Setting<bool> cpuopt_unsafe_fastmem_check; 134 Setting<bool> cpuopt_unsafe_fastmem_check;
134 135
@@ -149,6 +150,7 @@ struct Values {
149 Setting<bool> use_nvdec_emulation; 150 Setting<bool> use_nvdec_emulation;
150 Setting<bool> accelerate_astc; 151 Setting<bool> accelerate_astc;
151 Setting<bool> use_vsync; 152 Setting<bool> use_vsync;
153 Setting<bool> disable_fps_limit;
152 Setting<bool> use_assembly_shaders; 154 Setting<bool> use_assembly_shaders;
153 Setting<bool> use_asynchronous_shaders; 155 Setting<bool> use_asynchronous_shaders;
154 Setting<bool> use_fast_gpu_time; 156 Setting<bool> use_fast_gpu_time;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index efb851f5a..83b5b7676 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -139,6 +139,7 @@ add_library(core STATIC
139 frontend/input.h 139 frontend/input.h
140 hardware_interrupt_manager.cpp 140 hardware_interrupt_manager.cpp
141 hardware_interrupt_manager.h 141 hardware_interrupt_manager.h
142 hle/api_version.h
142 hle/ipc.h 143 hle/ipc.h
143 hle/ipc_helpers.h 144 hle/ipc_helpers.h
144 hle/kernel/board/nintendo/nx/k_system_control.cpp 145 hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -550,6 +551,8 @@ add_library(core STATIC
550 hle/service/spl/module.h 551 hle/service/spl/module.h
551 hle/service/spl/spl.cpp 552 hle/service/spl/spl.cpp
552 hle/service/spl/spl.h 553 hle/service/spl/spl.h
554 hle/service/spl/spl_results.h
555 hle/service/spl/spl_types.h
553 hle/service/ssl/ssl.cpp 556 hle/service/ssl/ssl.cpp
554 hle/service/ssl/ssl.h 557 hle/service/ssl/ssl.h
555 hle/service/time/clock_types.h 558 hle/service/time/clock_types.h
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index c8f6dc765..f871f7bf4 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -186,6 +186,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
186 if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { 186 if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) {
187 config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; 187 config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
188 } 188 }
189 if (Settings::values.cpuopt_unsafe_ignore_standard_fpcr.GetValue()) {
190 config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
191 }
189 if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { 192 if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) {
190 config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; 193 config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
191 } 194 }
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c5004b7b4..e6f1aa0e7 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
6#include <atomic>
6#include <memory> 7#include <memory>
7#include <utility> 8#include <utility>
8 9
@@ -377,7 +378,7 @@ struct System::Impl {
377 std::unique_ptr<Core::DeviceMemory> device_memory; 378 std::unique_ptr<Core::DeviceMemory> device_memory;
378 Core::Memory::Memory memory; 379 Core::Memory::Memory memory;
379 CpuManager cpu_manager; 380 CpuManager cpu_manager;
380 bool is_powered_on = false; 381 std::atomic_bool is_powered_on{};
381 bool exit_lock = false; 382 bool exit_lock = false;
382 383
383 Reporter reporter; 384 Reporter reporter;
@@ -463,7 +464,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
463} 464}
464 465
465bool System::IsPoweredOn() const { 466bool System::IsPoweredOn() const {
466 return impl->is_powered_on; 467 return impl->is_powered_on.load(std::memory_order::relaxed);
467} 468}
468 469
469void System::PrepareReschedule() { 470void System::PrepareReschedule() {
diff --git a/src/core/file_sys/system_archive/system_version.cpp b/src/core/file_sys/system_archive/system_version.cpp
index 54704105b..9b76d007e 100644
--- a/src/core/file_sys/system_archive/system_version.cpp
+++ b/src/core/file_sys/system_archive/system_version.cpp
@@ -4,47 +4,29 @@
4 4
5#include "core/file_sys/system_archive/system_version.h" 5#include "core/file_sys/system_archive/system_version.h"
6#include "core/file_sys/vfs_vector.h" 6#include "core/file_sys/vfs_vector.h"
7#include "core/hle/api_version.h"
7 8
8namespace FileSys::SystemArchive { 9namespace FileSys::SystemArchive {
9 10
10namespace SystemVersionData {
11
12// This section should reflect the best system version to describe yuzu's HLE api.
13// TODO(DarkLordZach): Update when HLE gets better.
14
15constexpr u8 VERSION_MAJOR = 11;
16constexpr u8 VERSION_MINOR = 0;
17constexpr u8 VERSION_MICRO = 1;
18
19constexpr u8 REVISION_MAJOR = 1;
20constexpr u8 REVISION_MINOR = 0;
21
22constexpr char PLATFORM_STRING[] = "NX";
23constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
24constexpr char DISPLAY_VERSION[] = "11.0.1";
25constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
26
27} // namespace SystemVersionData
28
29std::string GetLongDisplayVersion() { 11std::string GetLongDisplayVersion() {
30 return SystemVersionData::DISPLAY_TITLE; 12 return HLE::ApiVersion::DISPLAY_TITLE;
31} 13}
32 14
33VirtualDir SystemVersion() { 15VirtualDir SystemVersion() {
34 VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file"); 16 VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
35 file->WriteObject(SystemVersionData::VERSION_MAJOR, 0); 17 file->WriteObject(HLE::ApiVersion::HOS_VERSION_MAJOR, 0);
36 file->WriteObject(SystemVersionData::VERSION_MINOR, 1); 18 file->WriteObject(HLE::ApiVersion::HOS_VERSION_MINOR, 1);
37 file->WriteObject(SystemVersionData::VERSION_MICRO, 2); 19 file->WriteObject(HLE::ApiVersion::HOS_VERSION_MICRO, 2);
38 file->WriteObject(SystemVersionData::REVISION_MAJOR, 4); 20 file->WriteObject(HLE::ApiVersion::SDK_REVISION_MAJOR, 4);
39 file->WriteObject(SystemVersionData::REVISION_MINOR, 5); 21 file->WriteObject(HLE::ApiVersion::SDK_REVISION_MINOR, 5);
40 file->WriteArray(SystemVersionData::PLATFORM_STRING, 22 file->WriteArray(HLE::ApiVersion::PLATFORM_STRING,
41 std::min<u64>(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ULL), 0x8); 23 std::min<u64>(sizeof(HLE::ApiVersion::PLATFORM_STRING), 0x20ULL), 0x8);
42 file->WriteArray(SystemVersionData::VERSION_HASH, 24 file->WriteArray(HLE::ApiVersion::VERSION_HASH,
43 std::min<u64>(sizeof(SystemVersionData::VERSION_HASH), 0x40ULL), 0x28); 25 std::min<u64>(sizeof(HLE::ApiVersion::VERSION_HASH), 0x40ULL), 0x28);
44 file->WriteArray(SystemVersionData::DISPLAY_VERSION, 26 file->WriteArray(HLE::ApiVersion::DISPLAY_VERSION,
45 std::min<u64>(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ULL), 0x68); 27 std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_VERSION), 0x18ULL), 0x68);
46 file->WriteArray(SystemVersionData::DISPLAY_TITLE, 28 file->WriteArray(HLE::ApiVersion::DISPLAY_TITLE,
47 std::min<u64>(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ULL), 0x80); 29 std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_TITLE), 0x80ULL), 0x80);
48 return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file}, 30 return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file},
49 std::vector<VirtualDir>{}, "data"); 31 std::vector<VirtualDir>{}, "data");
50} 32}
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index d0b8fd046..3dad54f49 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -24,17 +24,12 @@ constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) {
24 case Mode::Read: 24 case Mode::Read:
25 return FS::FileAccessMode::Read; 25 return FS::FileAccessMode::Read;
26 case Mode::Write: 26 case Mode::Write:
27 return FS::FileAccessMode::Write;
28 case Mode::ReadWrite: 27 case Mode::ReadWrite:
29 return FS::FileAccessMode::ReadWrite;
30 case Mode::Append: 28 case Mode::Append:
31 return FS::FileAccessMode::Append;
32 case Mode::ReadAppend: 29 case Mode::ReadAppend:
33 return FS::FileAccessMode::ReadAppend;
34 case Mode::WriteAppend: 30 case Mode::WriteAppend:
35 return FS::FileAccessMode::Append;
36 case Mode::All: 31 case Mode::All:
37 return FS::FileAccessMode::ReadAppend; 32 return FS::FileAccessMode::ReadWrite;
38 default: 33 default:
39 return {}; 34 return {};
40 } 35 }
diff --git a/src/core/hle/api_version.h b/src/core/hle/api_version.h
new file mode 100644
index 000000000..811732179
--- /dev/null
+++ b/src/core/hle/api_version.h
@@ -0,0 +1,38 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/common_types.h"
6
7// This file contains yuzu's HLE API version constants.
8
9namespace HLE::ApiVersion {
10
11// Horizon OS version constants.
12
13constexpr u8 HOS_VERSION_MAJOR = 11;
14constexpr u8 HOS_VERSION_MINOR = 0;
15constexpr u8 HOS_VERSION_MICRO = 1;
16
17// NintendoSDK version constants.
18
19constexpr u8 SDK_REVISION_MAJOR = 1;
20constexpr u8 SDK_REVISION_MINOR = 0;
21
22constexpr char PLATFORM_STRING[] = "NX";
23constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
24constexpr char DISPLAY_VERSION[] = "11.0.1";
25constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
26
27// Atmosphere version constants.
28
29constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
30constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
31constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 4;
32
33constexpr u32 GetTargetFirmware() {
34 return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
35 u32{HOS_VERSION_MICRO} << 8 | 0U;
36}
37
38} // namespace HLE::ApiVersion
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index da88f35bc..0c4bba66b 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -79,6 +79,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
79 R_UNLESS(current_values[index] <= value, ResultInvalidState); 79 R_UNLESS(current_values[index] <= value, ResultInvalidState);
80 80
81 limit_values[index] = value; 81 limit_values[index] = value;
82 peak_values[index] = current_values[index];
82 83
83 return ResultSuccess; 84 return ResultSuccess;
84} 85}
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index a2844ea8c..dc15cf58b 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -313,7 +313,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe
313 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); 313 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
314 314
315 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { 315 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
316 void(Common::FS::RemoveFile(zip_path)); 316 Common::FS::RemoveFile(zip_path);
317 } 317 }
318 318
319 HandleDownloadDisplayResult(applet_manager, res); 319 HandleDownloadDisplayResult(applet_manager, res);
@@ -445,7 +445,7 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title)
445 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res); 445 LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
446 446
447 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) { 447 if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
448 void(Common::FS::RemoveFile(bin_file_path)); 448 Common::FS::RemoveFile(bin_file_path);
449 } 449 }
450 450
451 HandleDownloadDisplayResult(applet_manager, res); 451 HandleDownloadDisplayResult(applet_manager, res);
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 7acad3798..1eb02aee2 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -314,6 +314,8 @@ void Controller_NPad::OnInit() {
314 314
315void Controller_NPad::OnLoadInputDevices() { 315void Controller_NPad::OnLoadInputDevices() {
316 const auto& players = Settings::values.players.GetValue(); 316 const auto& players = Settings::values.players.GetValue();
317
318 std::lock_guard lock{mutex};
317 for (std::size_t i = 0; i < players.size(); ++i) { 319 for (std::size_t i = 0; i < players.size(); ++i) {
318 std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, 320 std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
319 players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, 321 players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
@@ -348,6 +350,8 @@ void Controller_NPad::OnRelease() {
348} 350}
349 351
350void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { 352void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
353 std::lock_guard lock{mutex};
354
351 const auto controller_idx = NPadIdToIndex(npad_id); 355 const auto controller_idx = NPadIdToIndex(npad_id);
352 const auto controller_type = connected_controllers[controller_idx].type; 356 const auto controller_type = connected_controllers[controller_idx].type;
353 if (!connected_controllers[controller_idx].is_connected) { 357 if (!connected_controllers[controller_idx].is_connected) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index c050c9a44..1409d82a2 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -6,6 +6,8 @@
6 6
7#include <array> 7#include <array>
8#include <atomic> 8#include <atomic>
9#include <mutex>
10
9#include "common/bit_field.h" 11#include "common/bit_field.h"
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "common/quaternion.h" 13#include "common/quaternion.h"
@@ -563,6 +565,8 @@ private:
563 using MotionArray = std::array< 565 using MotionArray = std::array<
564 std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>, 566 std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
565 10>; 567 10>;
568
569 std::mutex mutex;
566 ButtonArray buttons; 570 ButtonArray buttons;
567 StickArray sticks; 571 StickArray sticks;
568 VibrationArray vibrations; 572 VibrationArray vibrations;
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index d1dbc659b..1d810562f 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -307,6 +307,9 @@ void NVFlinger::Compose() {
307} 307}
308 308
309s64 NVFlinger::GetNextTicks() const { 309s64 NVFlinger::GetNextTicks() const {
310 if (Settings::values.disable_fps_limit.GetValue()) {
311 return 0;
312 }
310 constexpr s64 max_hertz = 120LL; 313 constexpr s64 max_hertz = 120LL;
311 return (1000000000 * (1LL << swap_interval)) / max_hertz; 314 return (1000000000 * (1LL << swap_interval)) / max_hertz;
312} 315}
diff --git a/src/core/hle/service/spl/csrng.cpp b/src/core/hle/service/spl/csrng.cpp
index 1beca417c..9c7f89475 100644
--- a/src/core/hle/service/spl/csrng.cpp
+++ b/src/core/hle/service/spl/csrng.cpp
@@ -9,7 +9,7 @@ namespace Service::SPL {
9CSRNG::CSRNG(Core::System& system_, std::shared_ptr<Module> module_) 9CSRNG::CSRNG(Core::System& system_, std::shared_ptr<Module> module_)
10 : Interface(system_, std::move(module_), "csrng") { 10 : Interface(system_, std::move(module_), "csrng") {
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, &CSRNG::GetRandomBytes, "GetRandomBytes"}, 12 {0, &CSRNG::GenerateRandomBytes, "GenerateRandomBytes"},
13 }; 13 };
14 RegisterHandlers(functions); 14 RegisterHandlers(functions);
15} 15}
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 0b5e2b7c3..ebb179aa8 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -10,6 +10,7 @@
10#include <vector> 10#include <vector>
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/settings.h" 12#include "common/settings.h"
13#include "core/hle/api_version.h"
13#include "core/hle/ipc_helpers.h" 14#include "core/hle/ipc_helpers.h"
14#include "core/hle/service/spl/csrng.h" 15#include "core/hle/service/spl/csrng.h"
15#include "core/hle/service/spl/module.h" 16#include "core/hle/service/spl/module.h"
@@ -24,7 +25,46 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
24 25
25Module::Interface::~Interface() = default; 26Module::Interface::~Interface() = default;
26 27
27void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { 28void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) {
29 IPC::RequestParser rp{ctx};
30 const auto config_item = rp.PopEnum<ConfigItem>();
31
32 // This should call svcCallSecureMonitor with the appropriate args.
33 // Since we do not have it implemented yet, we will use this for now.
34 const auto smc_result = GetConfigImpl(config_item);
35 const auto result_code = smc_result.Code();
36
37 if (smc_result.Failed()) {
38 LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
39 result_code.raw);
40
41 IPC::ResponseBuilder rb{ctx, 2};
42 rb.Push(result_code);
43 }
44
45 LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
46 result_code.raw, *smc_result);
47
48 IPC::ResponseBuilder rb{ctx, 4};
49 rb.Push(result_code);
50 rb.Push(*smc_result);
51}
52
53void Module::Interface::ModularExponentiate(Kernel::HLERequestContext& ctx) {
54 UNIMPLEMENTED_MSG("ModularExponentiate is not implemented!");
55
56 IPC::ResponseBuilder rb{ctx, 2};
57 rb.Push(ResultSecureMonitorNotImplemented);
58}
59
60void Module::Interface::SetConfig(Kernel::HLERequestContext& ctx) {
61 UNIMPLEMENTED_MSG("SetConfig is not implemented!");
62
63 IPC::ResponseBuilder rb{ctx, 2};
64 rb.Push(ResultSecureMonitorNotImplemented);
65}
66
67void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) {
28 LOG_DEBUG(Service_SPL, "called"); 68 LOG_DEBUG(Service_SPL, "called");
29 69
30 const std::size_t size = ctx.GetWriteBufferSize(); 70 const std::size_t size = ctx.GetWriteBufferSize();
@@ -39,6 +79,88 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
39 rb.Push(ResultSuccess); 79 rb.Push(ResultSuccess);
40} 80}
41 81
82void Module::Interface::IsDevelopment(Kernel::HLERequestContext& ctx) {
83 UNIMPLEMENTED_MSG("IsDevelopment is not implemented!");
84
85 IPC::ResponseBuilder rb{ctx, 2};
86 rb.Push(ResultSecureMonitorNotImplemented);
87}
88
89void Module::Interface::SetBootReason(Kernel::HLERequestContext& ctx) {
90 UNIMPLEMENTED_MSG("SetBootReason is not implemented!");
91
92 IPC::ResponseBuilder rb{ctx, 2};
93 rb.Push(ResultSecureMonitorNotImplemented);
94}
95
96void Module::Interface::GetBootReason(Kernel::HLERequestContext& ctx) {
97 UNIMPLEMENTED_MSG("GetBootReason is not implemented!");
98
99 IPC::ResponseBuilder rb{ctx, 2};
100 rb.Push(ResultSecureMonitorNotImplemented);
101}
102
103ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
104 switch (config_item) {
105 case ConfigItem::DisableProgramVerification:
106 case ConfigItem::DramId:
107 case ConfigItem::SecurityEngineInterruptNumber:
108 case ConfigItem::FuseVersion:
109 case ConfigItem::HardwareType:
110 case ConfigItem::HardwareState:
111 case ConfigItem::IsRecoveryBoot:
112 case ConfigItem::DeviceId:
113 case ConfigItem::BootReason:
114 case ConfigItem::MemoryMode:
115 case ConfigItem::IsDevelopmentFunctionEnabled:
116 case ConfigItem::KernelConfiguration:
117 case ConfigItem::IsChargerHiZModeEnabled:
118 case ConfigItem::QuestState:
119 case ConfigItem::RegulatorType:
120 case ConfigItem::DeviceUniqueKeyGeneration:
121 case ConfigItem::Package2Hash:
122 return ResultSecureMonitorNotImplemented;
123 case ConfigItem::ExosphereApiVersion:
124 // Get information about the current exosphere version.
125 return MakeResult((u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
126 (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
127 (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
128 (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())));
129 case ConfigItem::ExosphereNeedsReboot:
130 // We are executing, so we aren't in the process of rebooting.
131 return MakeResult(u64{0});
132 case ConfigItem::ExosphereNeedsShutdown:
133 // We are executing, so we aren't in the process of shutting down.
134 return MakeResult(u64{0});
135 case ConfigItem::ExosphereGitCommitHash:
136 // Get information about the current exosphere git commit hash.
137 return MakeResult(u64{0});
138 case ConfigItem::ExosphereHasRcmBugPatch:
139 // Get information about whether this unit has the RCM bug patched.
140 return MakeResult(u64{0});
141 case ConfigItem::ExosphereBlankProdInfo:
142 // Get whether this unit should simulate a "blanked" PRODINFO.
143 return MakeResult(u64{0});
144 case ConfigItem::ExosphereAllowCalWrites:
145 // Get whether this unit should allow writing to the calibration partition.
146 return MakeResult(u64{0});
147 case ConfigItem::ExosphereEmummcType:
148 // Get what kind of emummc this unit has active.
149 return MakeResult(u64{0});
150 case ConfigItem::ExospherePayloadAddress:
151 // Gets the physical address of the reboot payload buffer, if one exists.
152 return ResultSecureMonitorNotInitialized;
153 case ConfigItem::ExosphereLogConfiguration:
154 // Get the log configuration.
155 return MakeResult(u64{0});
156 case ConfigItem::ExosphereForceEnableUsb30:
157 // Get whether usb 3.0 should be force-enabled.
158 return MakeResult(u64{0});
159 default:
160 return ResultSecureMonitorInvalidArgument;
161 }
162}
163
42void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 164void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
43 auto module = std::make_shared<Module>(); 165 auto module = std::make_shared<Module>();
44 std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager); 166 std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h
index 71855c1bf..61630df80 100644
--- a/src/core/hle/service/spl/module.h
+++ b/src/core/hle/service/spl/module.h
@@ -6,6 +6,8 @@
6 6
7#include <random> 7#include <random>
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9#include "core/hle/service/spl/spl_results.h"
10#include "core/hle/service/spl/spl_types.h"
9 11
10namespace Core { 12namespace Core {
11class System; 13class System;
@@ -21,12 +23,21 @@ public:
21 const char* name); 23 const char* name);
22 ~Interface() override; 24 ~Interface() override;
23 25
24 void GetRandomBytes(Kernel::HLERequestContext& ctx); 26 // General
27 void GetConfig(Kernel::HLERequestContext& ctx);
28 void ModularExponentiate(Kernel::HLERequestContext& ctx);
29 void SetConfig(Kernel::HLERequestContext& ctx);
30 void GenerateRandomBytes(Kernel::HLERequestContext& ctx);
31 void IsDevelopment(Kernel::HLERequestContext& ctx);
32 void SetBootReason(Kernel::HLERequestContext& ctx);
33 void GetBootReason(Kernel::HLERequestContext& ctx);
25 34
26 protected: 35 protected:
27 std::shared_ptr<Module> module; 36 std::shared_ptr<Module> module;
28 37
29 private: 38 private:
39 ResultVal<u64> GetConfigImpl(ConfigItem config_item) const;
40
30 std::mt19937 rng; 41 std::mt19937 rng;
31 }; 42 };
32}; 43};
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp
index fff3f3c42..20384042f 100644
--- a/src/core/hle/service/spl/spl.cpp
+++ b/src/core/hle/service/spl/spl.cpp
@@ -10,13 +10,13 @@ SPL::SPL(Core::System& system_, std::shared_ptr<Module> module_)
10 : Interface(system_, std::move(module_), "spl:") { 10 : Interface(system_, std::move(module_), "spl:") {
11 // clang-format off 11 // clang-format off
12 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
13 {0, nullptr, "GetConfig"}, 13 {0, &SPL::GetConfig, "GetConfig"},
14 {1, nullptr, "ModularExponentiate"}, 14 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
15 {5, nullptr, "SetConfig"}, 15 {5, &SPL::SetConfig, "SetConfig"},
16 {7, &SPL::GetRandomBytes, "GetRandomBytes"}, 16 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
17 {11, nullptr, "IsDevelopment"}, 17 {11, &SPL::IsDevelopment, "IsDevelopment"},
18 {24, nullptr, "SetBootReason"}, 18 {24, &SPL::SetBootReason, "SetBootReason"},
19 {25, nullptr, "GetBootReason"}, 19 {25, &SPL::GetBootReason, "GetBootReason"},
20 }; 20 };
21 // clang-format on 21 // clang-format on
22 22
@@ -27,22 +27,22 @@ SPL_MIG::SPL_MIG(Core::System& system_, std::shared_ptr<Module> module_)
27 : Interface(system_, std::move(module_), "spl:mig") { 27 : Interface(system_, std::move(module_), "spl:mig") {
28 // clang-format off 28 // clang-format off
29 static const FunctionInfo functions[] = { 29 static const FunctionInfo functions[] = {
30 {0, nullptr, "GetConfig"}, 30 {0, &SPL::GetConfig, "GetConfig"},
31 {1, nullptr, "ModularExponentiate"}, 31 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
32 {2, nullptr, "GenerateAesKek"}, 32 {2, nullptr, "GenerateAesKek"},
33 {3, nullptr, "LoadAesKey"}, 33 {3, nullptr, "LoadAesKey"},
34 {4, nullptr, "GenerateAesKey"}, 34 {4, nullptr, "GenerateAesKey"},
35 {5, nullptr, "SetConfig"}, 35 {5, &SPL::SetConfig, "SetConfig"},
36 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, 36 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
37 {11, nullptr, "IsDevelopment"}, 37 {11, &SPL::IsDevelopment, "IsDevelopment"},
38 {14, nullptr, "DecryptAesKey"}, 38 {14, nullptr, "DecryptAesKey"},
39 {15, nullptr, "CryptAesCtr"}, 39 {15, nullptr, "CryptAesCtr"},
40 {16, nullptr, "ComputeCmac"}, 40 {16, nullptr, "ComputeCmac"},
41 {21, nullptr, "AllocateAesKeyslot"}, 41 {21, nullptr, "AllocateAesKeyslot"},
42 {22, nullptr, "DeallocateAesKeySlot"}, 42 {22, nullptr, "DeallocateAesKeySlot"},
43 {23, nullptr, "GetAesKeyslotAvailableEvent"}, 43 {23, nullptr, "GetAesKeyslotAvailableEvent"},
44 {24, nullptr, "SetBootReason"}, 44 {24, &SPL::SetBootReason, "SetBootReason"},
45 {25, nullptr, "GetBootReason"}, 45 {25, &SPL::GetBootReason, "GetBootReason"},
46 }; 46 };
47 // clang-format on 47 // clang-format on
48 48
@@ -53,16 +53,16 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
53 : Interface(system_, std::move(module_), "spl:fs") { 53 : Interface(system_, std::move(module_), "spl:fs") {
54 // clang-format off 54 // clang-format off
55 static const FunctionInfo functions[] = { 55 static const FunctionInfo functions[] = {
56 {0, nullptr, "GetConfig"}, 56 {0, &SPL::GetConfig, "GetConfig"},
57 {1, nullptr, "ModularExponentiate"}, 57 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
58 {2, nullptr, "GenerateAesKek"}, 58 {2, nullptr, "GenerateAesKek"},
59 {3, nullptr, "LoadAesKey"}, 59 {3, nullptr, "LoadAesKey"},
60 {4, nullptr, "GenerateAesKey"}, 60 {4, nullptr, "GenerateAesKey"},
61 {5, nullptr, "SetConfig"}, 61 {5, &SPL::SetConfig, "SetConfig"},
62 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, 62 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
63 {9, nullptr, "ImportLotusKey"}, 63 {9, nullptr, "ImportLotusKey"},
64 {10, nullptr, "DecryptLotusMessage"}, 64 {10, nullptr, "DecryptLotusMessage"},
65 {11, nullptr, "IsDevelopment"}, 65 {11, &SPL::IsDevelopment, "IsDevelopment"},
66 {12, nullptr, "GenerateSpecificAesKey"}, 66 {12, nullptr, "GenerateSpecificAesKey"},
67 {14, nullptr, "DecryptAesKey"}, 67 {14, nullptr, "DecryptAesKey"},
68 {15, nullptr, "CryptAesCtr"}, 68 {15, nullptr, "CryptAesCtr"},
@@ -71,8 +71,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
71 {21, nullptr, "AllocateAesKeyslot"}, 71 {21, nullptr, "AllocateAesKeyslot"},
72 {22, nullptr, "DeallocateAesKeySlot"}, 72 {22, nullptr, "DeallocateAesKeySlot"},
73 {23, nullptr, "GetAesKeyslotAvailableEvent"}, 73 {23, nullptr, "GetAesKeyslotAvailableEvent"},
74 {24, nullptr, "SetBootReason"}, 74 {24, &SPL::SetBootReason, "SetBootReason"},
75 {25, nullptr, "GetBootReason"}, 75 {25, &SPL::GetBootReason, "GetBootReason"},
76 {31, nullptr, "GetPackage2Hash"}, 76 {31, nullptr, "GetPackage2Hash"},
77 }; 77 };
78 // clang-format on 78 // clang-format on
@@ -84,14 +84,14 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
84 : Interface(system_, std::move(module_), "spl:ssl") { 84 : Interface(system_, std::move(module_), "spl:ssl") {
85 // clang-format off 85 // clang-format off
86 static const FunctionInfo functions[] = { 86 static const FunctionInfo functions[] = {
87 {0, nullptr, "GetConfig"}, 87 {0, &SPL::GetConfig, "GetConfig"},
88 {1, nullptr, "ModularExponentiate"}, 88 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
89 {2, nullptr, "GenerateAesKek"}, 89 {2, nullptr, "GenerateAesKek"},
90 {3, nullptr, "LoadAesKey"}, 90 {3, nullptr, "LoadAesKey"},
91 {4, nullptr, "GenerateAesKey"}, 91 {4, nullptr, "GenerateAesKey"},
92 {5, nullptr, "SetConfig"}, 92 {5, &SPL::SetConfig, "SetConfig"},
93 {7, &SPL::GetRandomBytes, "GetRandomBytes"}, 93 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
94 {11, nullptr, "IsDevelopment"}, 94 {11, &SPL::IsDevelopment, "IsDevelopment"},
95 {13, nullptr, "DecryptDeviceUniqueData"}, 95 {13, nullptr, "DecryptDeviceUniqueData"},
96 {14, nullptr, "DecryptAesKey"}, 96 {14, nullptr, "DecryptAesKey"},
97 {15, nullptr, "CryptAesCtr"}, 97 {15, nullptr, "CryptAesCtr"},
@@ -99,8 +99,8 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
99 {21, nullptr, "AllocateAesKeyslot"}, 99 {21, nullptr, "AllocateAesKeyslot"},
100 {22, nullptr, "DeallocateAesKeySlot"}, 100 {22, nullptr, "DeallocateAesKeySlot"},
101 {23, nullptr, "GetAesKeyslotAvailableEvent"}, 101 {23, nullptr, "GetAesKeyslotAvailableEvent"},
102 {24, nullptr, "SetBootReason"}, 102 {24, &SPL::SetBootReason, "SetBootReason"},
103 {25, nullptr, "GetBootReason"}, 103 {25, &SPL::GetBootReason, "GetBootReason"},
104 {26, nullptr, "DecryptAndStoreSslClientCertKey"}, 104 {26, nullptr, "DecryptAndStoreSslClientCertKey"},
105 {27, nullptr, "ModularExponentiateWithSslClientCertKey"}, 105 {27, nullptr, "ModularExponentiateWithSslClientCertKey"},
106 }; 106 };
@@ -113,14 +113,14 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
113 : Interface(system_, std::move(module_), "spl:es") { 113 : Interface(system_, std::move(module_), "spl:es") {
114 // clang-format off 114 // clang-format off
115 static const FunctionInfo functions[] = { 115 static const FunctionInfo functions[] = {
116 {0, nullptr, "GetConfig"}, 116 {0, &SPL::GetConfig, "GetConfig"},
117 {1, nullptr, "ModularExponentiate"}, 117 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
118 {2, nullptr, "GenerateAesKek"}, 118 {2, nullptr, "GenerateAesKek"},
119 {3, nullptr, "LoadAesKey"}, 119 {3, nullptr, "LoadAesKey"},
120 {4, nullptr, "GenerateAesKey"}, 120 {4, nullptr, "GenerateAesKey"},
121 {5, nullptr, "SetConfig"}, 121 {5, &SPL::SetConfig, "SetConfig"},
122 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, 122 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
123 {11, nullptr, "IsDevelopment"}, 123 {11, &SPL::IsDevelopment, "IsDevelopment"},
124 {13, nullptr, "DecryptDeviceUniqueData"}, 124 {13, nullptr, "DecryptDeviceUniqueData"},
125 {14, nullptr, "DecryptAesKey"}, 125 {14, nullptr, "DecryptAesKey"},
126 {15, nullptr, "CryptAesCtr"}, 126 {15, nullptr, "CryptAesCtr"},
@@ -131,8 +131,8 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
131 {21, nullptr, "AllocateAesKeyslot"}, 131 {21, nullptr, "AllocateAesKeyslot"},
132 {22, nullptr, "DeallocateAesKeySlot"}, 132 {22, nullptr, "DeallocateAesKeySlot"},
133 {23, nullptr, "GetAesKeyslotAvailableEvent"}, 133 {23, nullptr, "GetAesKeyslotAvailableEvent"},
134 {24, nullptr, "SetBootReason"}, 134 {24, &SPL::SetBootReason, "SetBootReason"},
135 {25, nullptr, "GetBootReason"}, 135 {25, &SPL::GetBootReason, "GetBootReason"},
136 {28, nullptr, "DecryptAndStoreDrmDeviceCertKey"}, 136 {28, nullptr, "DecryptAndStoreDrmDeviceCertKey"},
137 {29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"}, 137 {29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"},
138 {31, nullptr, "PrepareEsArchiveKey"}, 138 {31, nullptr, "PrepareEsArchiveKey"},
@@ -147,14 +147,14 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
147 : Interface(system_, std::move(module_), "spl:manu") { 147 : Interface(system_, std::move(module_), "spl:manu") {
148 // clang-format off 148 // clang-format off
149 static const FunctionInfo functions[] = { 149 static const FunctionInfo functions[] = {
150 {0, nullptr, "GetConfig"}, 150 {0, &SPL::GetConfig, "GetConfig"},
151 {1, nullptr, "ModularExponentiate"}, 151 {1, &SPL::ModularExponentiate, "ModularExponentiate"},
152 {2, nullptr, "GenerateAesKek"}, 152 {2, nullptr, "GenerateAesKek"},
153 {3, nullptr, "LoadAesKey"}, 153 {3, nullptr, "LoadAesKey"},
154 {4, nullptr, "GenerateAesKey"}, 154 {4, nullptr, "GenerateAesKey"},
155 {5, nullptr, "SetConfig"}, 155 {5, &SPL::SetConfig, "SetConfig"},
156 {7, &SPL::GetRandomBytes, "GetRandomBytes"}, 156 {7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
157 {11, nullptr, "IsDevelopment"}, 157 {11, &SPL::IsDevelopment, "IsDevelopment"},
158 {13, nullptr, "DecryptDeviceUniqueData"}, 158 {13, nullptr, "DecryptDeviceUniqueData"},
159 {14, nullptr, "DecryptAesKey"}, 159 {14, nullptr, "DecryptAesKey"},
160 {15, nullptr, "CryptAesCtr"}, 160 {15, nullptr, "CryptAesCtr"},
@@ -162,8 +162,8 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
162 {21, nullptr, "AllocateAesKeyslot"}, 162 {21, nullptr, "AllocateAesKeyslot"},
163 {22, nullptr, "DeallocateAesKeySlot"}, 163 {22, nullptr, "DeallocateAesKeySlot"},
164 {23, nullptr, "GetAesKeyslotAvailableEvent"}, 164 {23, nullptr, "GetAesKeyslotAvailableEvent"},
165 {24, nullptr, "SetBootReason"}, 165 {24, &SPL::SetBootReason, "SetBootReason"},
166 {25, nullptr, "GetBootReason"}, 166 {25, &SPL::GetBootReason, "GetBootReason"},
167 {30, nullptr, "ReencryptDeviceUniqueData"}, 167 {30, nullptr, "ReencryptDeviceUniqueData"},
168 }; 168 };
169 // clang-format on 169 // clang-format on
diff --git a/src/core/hle/service/spl/spl_results.h b/src/core/hle/service/spl/spl_results.h
new file mode 100644
index 000000000..878fa91b7
--- /dev/null
+++ b/src/core/hle/service/spl/spl_results.h
@@ -0,0 +1,29 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/result.h"
6
7namespace Service::SPL {
8
9// Description 0 - 99
10constexpr ResultCode ResultSecureMonitorError{ErrorModule::SPL, 0};
11constexpr ResultCode ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1};
12constexpr ResultCode ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2};
13constexpr ResultCode ResultSecureMonitorBusy{ErrorModule::SPL, 3};
14constexpr ResultCode ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4};
15constexpr ResultCode ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5};
16constexpr ResultCode ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6};
17constexpr ResultCode ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7};
18
19constexpr ResultCode ResultInvalidSize{ErrorModule::SPL, 100};
20constexpr ResultCode ResultUnknownSecureMonitorError{ErrorModule::SPL, 101};
21constexpr ResultCode ResultDecryptionFailed{ErrorModule::SPL, 102};
22
23constexpr ResultCode ResultOutOfKeySlots{ErrorModule::SPL, 104};
24constexpr ResultCode ResultInvalidKeySlot{ErrorModule::SPL, 105};
25constexpr ResultCode ResultBootReasonAlreadySet{ErrorModule::SPL, 106};
26constexpr ResultCode ResultBootReasonNotSet{ErrorModule::SPL, 107};
27constexpr ResultCode ResultInvalidArgument{ErrorModule::SPL, 108};
28
29} // namespace Service::SPL
diff --git a/src/core/hle/service/spl/spl_types.h b/src/core/hle/service/spl/spl_types.h
new file mode 100644
index 000000000..23c39f7ed
--- /dev/null
+++ b/src/core/hle/service/spl/spl_types.h
@@ -0,0 +1,230 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <span>
6
7#include "common/bit_field.h"
8#include "common/common_types.h"
9
10namespace Service::SPL {
11
12constexpr size_t AES_128_KEY_SIZE = 0x10;
13
14namespace Smc {
15
16enum class FunctionId : u32 {
17 SetConfig = 0xC3000401,
18 GetConfig = 0xC3000002,
19 GetResult = 0xC3000003,
20 GetResultData = 0xC3000404,
21 ModularExponentiate = 0xC3000E05,
22 GenerateRandomBytes = 0xC3000006,
23 GenerateAesKek = 0xC3000007,
24 LoadAesKey = 0xC3000008,
25 ComputeAes = 0xC3000009,
26 GenerateSpecificAesKey = 0xC300000A,
27 ComputeCmac = 0xC300040B,
28 ReencryptDeviceUniqueData = 0xC300D60C,
29 DecryptDeviceUniqueData = 0xC300100D,
30
31 ModularExponentiateWithStorageKey = 0xC300060F,
32 PrepareEsDeviceUniqueKey = 0xC3000610,
33 LoadPreparedAesKey = 0xC3000011,
34 PrepareCommonEsTitleKey = 0xC3000012,
35
36 // Deprecated functions.
37 LoadEsDeviceKey = 0xC300100C,
38 DecryptAndStoreGcKey = 0xC300100E,
39
40 // Atmosphere functions.
41 AtmosphereIramCopy = 0xF0000201,
42 AtmosphereReadWriteRegister = 0xF0000002,
43
44 AtmosphereGetEmummcConfig = 0xF0000404,
45};
46
47enum class CipherMode {
48 CbcEncrypt = 0,
49 CbcDecrypt = 1,
50 Ctr = 2,
51};
52
53enum class DeviceUniqueDataMode {
54 DecryptDeviceUniqueData = 0,
55 DecryptAndStoreGcKey = 1,
56 DecryptAndStoreEsDeviceKey = 2,
57 DecryptAndStoreSslKey = 3,
58 DecryptAndStoreDrmDeviceCertKey = 4,
59};
60
61enum class ModularExponentiateWithStorageKeyMode {
62 Gc = 0,
63 Ssl = 1,
64 DrmDeviceCert = 2,
65};
66
67enum class EsCommonKeyType {
68 TitleKey = 0,
69 ArchiveKey = 1,
70};
71
72struct AsyncOperationKey {
73 u64 value;
74};
75
76} // namespace Smc
77
78enum class HardwareType {
79 Icosa = 0,
80 Copper = 1,
81 Hoag = 2,
82 Iowa = 3,
83 Calcio = 4,
84 Aula = 5,
85};
86
87enum class SocType {
88 Erista = 0,
89 Mariko = 1,
90};
91
92enum class HardwareState {
93 Development = 0,
94 Production = 1,
95};
96
97enum class MemoryArrangement {
98 Standard = 0,
99 StandardForAppletDev = 1,
100 StandardForSystemDev = 2,
101 Expanded = 3,
102 ExpandedForAppletDev = 4,
103
104 // Note: Dynamic is not official.
105 // Atmosphere uses it to maintain compatibility with firmwares prior to 6.0.0,
106 // which removed the explicit retrieval of memory arrangement from PM.
107 Dynamic = 5,
108 Count,
109};
110
111enum class BootReason {
112 Unknown = 0,
113 AcOk = 1,
114 OnKey = 2,
115 RtcAlarm1 = 3,
116 RtcAlarm2 = 4,
117};
118
119struct BootReasonValue {
120 union {
121 u32 value{};
122
123 BitField<0, 8, u32> power_intr;
124 BitField<8, 8, u32> rtc_intr;
125 BitField<16, 8, u32> nv_erc;
126 BitField<24, 8, u32> boot_reason;
127 };
128};
129static_assert(sizeof(BootReasonValue) == sizeof(u32), "BootReasonValue definition!");
130
131struct AesKey {
132 std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
133
134 std::span<u8> AsBytes() {
135 return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
136 }
137
138 std::span<const u8> AsBytes() const {
139 return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
140 }
141};
142static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AesKey definition!");
143
144struct IvCtr {
145 std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
146
147 std::span<u8> AsBytes() {
148 return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
149 }
150
151 std::span<const u8> AsBytes() const {
152 return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
153 }
154};
155static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "IvCtr definition!");
156
157struct Cmac {
158 std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
159
160 std::span<u8> AsBytes() {
161 return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
162 }
163
164 std::span<const u8> AsBytes() const {
165 return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
166 }
167};
168static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "Cmac definition!");
169
170struct AccessKey {
171 std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
172
173 std::span<u8> AsBytes() {
174 return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
175 }
176
177 std::span<const u8> AsBytes() const {
178 return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
179 }
180};
181static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AccessKey definition!");
182
183struct KeySource {
184 std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
185
186 std::span<u8> AsBytes() {
187 return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
188 }
189
190 std::span<const u8> AsBytes() const {
191 return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
192 }
193};
194static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "KeySource definition!");
195
196enum class ConfigItem : u32 {
197 // Standard config items.
198 DisableProgramVerification = 1,
199 DramId = 2,
200 SecurityEngineInterruptNumber = 3,
201 FuseVersion = 4,
202 HardwareType = 5,
203 HardwareState = 6,
204 IsRecoveryBoot = 7,
205 DeviceId = 8,
206 BootReason = 9,
207 MemoryMode = 10,
208 IsDevelopmentFunctionEnabled = 11,
209 KernelConfiguration = 12,
210 IsChargerHiZModeEnabled = 13,
211 QuestState = 14,
212 RegulatorType = 15,
213 DeviceUniqueKeyGeneration = 16,
214 Package2Hash = 17,
215
216 // Extension config items for exosphere.
217 ExosphereApiVersion = 65000,
218 ExosphereNeedsReboot = 65001,
219 ExosphereNeedsShutdown = 65002,
220 ExosphereGitCommitHash = 65003,
221 ExosphereHasRcmBugPatch = 65004,
222 ExosphereBlankProdInfo = 65005,
223 ExosphereAllowCalWrites = 65006,
224 ExosphereEmummcType = 65007,
225 ExospherePayloadAddress = 65008,
226 ExosphereLogConfiguration = 65009,
227 ExosphereForceEnableUsb30 = 65010,
228};
229
230} // namespace Service::SPL
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index bf4402308..c634b6abd 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -125,7 +125,7 @@ ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& locati
125 return ERROR_TIME_NOT_FOUND; 125 return ERROR_TIME_NOT_FOUND;
126 } 126 }
127 127
128 vfs_file = zoneinfo_dir->GetFile(location_name); 128 vfs_file = zoneinfo_dir->GetFileRelative(location_name);
129 if (!vfs_file) { 129 if (!vfs_file) {
130 LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.", 130 LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
131 time_zone_binary_titleid, location_name); 131 time_zone_binary_titleid, location_name);
diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp
index a335e6da1..3b052ffb2 100644
--- a/src/input_common/mouse/mouse_input.cpp
+++ b/src/input_common/mouse/mouse_input.cpp
@@ -2,25 +2,23 @@
2// Licensed under GPLv2+ 2// Licensed under GPLv2+
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <stop_token>
6#include <thread>
7
5#include "common/settings.h" 8#include "common/settings.h"
6#include "input_common/mouse/mouse_input.h" 9#include "input_common/mouse/mouse_input.h"
7 10
8namespace MouseInput { 11namespace MouseInput {
9 12
10Mouse::Mouse() { 13Mouse::Mouse() {
11 update_thread = std::thread(&Mouse::UpdateThread, this); 14 update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
12} 15}
13 16
14Mouse::~Mouse() { 17Mouse::~Mouse() = default;
15 update_thread_running = false;
16 if (update_thread.joinable()) {
17 update_thread.join();
18 }
19}
20 18
21void Mouse::UpdateThread() { 19void Mouse::UpdateThread(std::stop_token stop_token) {
22 constexpr int update_time = 10; 20 constexpr int update_time = 10;
23 while (update_thread_running) { 21 while (!stop_token.stop_requested()) {
24 for (MouseInfo& info : mouse_info) { 22 for (MouseInfo& info : mouse_info) {
25 const Common::Vec3f angular_direction{ 23 const Common::Vec3f angular_direction{
26 -info.tilt_direction.y, 24 -info.tilt_direction.y,
diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h
index 5a971ad67..c8bae99c1 100644
--- a/src/input_common/mouse/mouse_input.h
+++ b/src/input_common/mouse/mouse_input.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <mutex> 8#include <mutex>
9#include <stop_token>
9#include <thread> 10#include <thread>
10 11
11#include "common/common_types.h" 12#include "common/common_types.h"
@@ -85,7 +86,7 @@ public:
85 [[nodiscard]] const MouseData& GetMouseState(std::size_t button) const; 86 [[nodiscard]] const MouseData& GetMouseState(std::size_t button) const;
86 87
87private: 88private:
88 void UpdateThread(); 89 void UpdateThread(std::stop_token stop_token);
89 void UpdateYuzuSettings(); 90 void UpdateYuzuSettings();
90 void StopPanning(); 91 void StopPanning();
91 92
@@ -105,12 +106,11 @@ private:
105 u16 buttons{}; 106 u16 buttons{};
106 u16 toggle_buttons{}; 107 u16 toggle_buttons{};
107 u16 lock_buttons{}; 108 u16 lock_buttons{};
108 std::thread update_thread; 109 std::jthread update_thread;
109 MouseButton last_button{MouseButton::Undefined}; 110 MouseButton last_button{MouseButton::Undefined};
110 std::array<MouseInfo, 7> mouse_info; 111 std::array<MouseInfo, 7> mouse_info;
111 Common::SPSCQueue<MouseStatus> mouse_queue; 112 Common::SPSCQueue<MouseStatus> mouse_queue;
112 bool configuring{false}; 113 bool configuring{false};
113 bool update_thread_running{true};
114 int mouse_panning_timout{}; 114 int mouse_panning_timout{};
115}; 115};
116} // namespace MouseInput 116} // namespace MouseInput
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index f968b5b16..07939432f 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -4,10 +4,10 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
8#include <functional> 7#include <functional>
9#include <optional> 8#include <optional>
10#include <span> 9#include <span>
10#include <stop_token>
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/fermi_2d.h" 12#include "video_core/engines/fermi_2d.h"
13#include "video_core/gpu.h" 13#include "video_core/gpu.h"
@@ -123,7 +123,7 @@ public:
123 virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {} 123 virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {}
124 124
125 /// Initialize disk cached resources for the game being emulated 125 /// Initialize disk cached resources for the game being emulated
126 virtual void LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, 126 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
127 const DiskResourceLoadCallback& callback) {} 127 const DiskResourceLoadCallback& callback) {}
128 128
129 /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver. 129 /// Grant access to the Guest Driver Profile for recording/obtaining info on the guest driver.
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index f87bb269b..eb8bdaa85 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -351,7 +351,7 @@ void RasterizerOpenGL::SetupShaders(bool is_indexed) {
351 } 351 }
352} 352}
353 353
354void RasterizerOpenGL::LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, 354void RasterizerOpenGL::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
355 const VideoCore::DiskResourceLoadCallback& callback) { 355 const VideoCore::DiskResourceLoadCallback& callback) {
356 shader_cache.LoadDiskCache(title_id, stop_loading, callback); 356 shader_cache.LoadDiskCache(title_id, stop_loading, callback);
357} 357}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 76298517f..9995a563b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -94,7 +94,7 @@ public:
94 const Tegra::Engines::Fermi2D::Config& copy_config) override; 94 const Tegra::Engines::Fermi2D::Config& copy_config) override;
95 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 95 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
96 u32 pixel_stride) override; 96 u32 pixel_stride) override;
97 void LoadDiskResources(u64 title_id, const std::atomic_bool& stop_loading, 97 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
98 const VideoCore::DiskResourceLoadCallback& callback) override; 98 const VideoCore::DiskResourceLoadCallback& callback) override;
99 99
100 /// Returns true when there are commands queued to the OpenGL server. 100 /// Returns true when there are commands queued to the OpenGL server.
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 5cf7cd151..5a01c59ec 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -331,7 +331,7 @@ ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer_,
331 331
332ShaderCacheOpenGL::~ShaderCacheOpenGL() = default; 332ShaderCacheOpenGL::~ShaderCacheOpenGL() = default;
333 333
334void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop_loading, 334void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, std::stop_token stop_loading,
335 const VideoCore::DiskResourceLoadCallback& callback) { 335 const VideoCore::DiskResourceLoadCallback& callback) {
336 disk_cache.BindTitleID(title_id); 336 disk_cache.BindTitleID(title_id);
337 const std::optional transferable = disk_cache.LoadTransferable(); 337 const std::optional transferable = disk_cache.LoadTransferable();
@@ -372,7 +372,7 @@ void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop
372 const auto scope = context->Acquire(); 372 const auto scope = context->Acquire();
373 373
374 for (std::size_t i = begin; i < end; ++i) { 374 for (std::size_t i = begin; i < end; ++i) {
375 if (stop_loading) { 375 if (stop_loading.stop_requested()) {
376 return; 376 return;
377 } 377 }
378 const auto& entry = (*transferable)[i]; 378 const auto& entry = (*transferable)[i];
@@ -435,7 +435,7 @@ void ShaderCacheOpenGL::LoadDiskCache(u64 title_id, const std::atomic_bool& stop
435 precompiled_cache_altered = true; 435 precompiled_cache_altered = true;
436 return; 436 return;
437 } 437 }
438 if (stop_loading) { 438 if (stop_loading.stop_requested()) {
439 return; 439 return;
440 } 440 }
441 441
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 2aed0697e..b30308b6f 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -127,7 +127,7 @@ public:
127 ~ShaderCacheOpenGL() override; 127 ~ShaderCacheOpenGL() override;
128 128
129 /// Loads disk cache for the current game 129 /// Loads disk cache for the current game
130 void LoadDiskCache(u64 title_id, const std::atomic_bool& stop_loading, 130 void LoadDiskCache(u64 title_id, std::stop_token stop_loading,
131 const VideoCore::DiskResourceLoadCallback& callback); 131 const VideoCore::DiskResourceLoadCallback& callback);
132 132
133 /// Gets the current specified shader stage program 133 /// Gets the current specified shader stage program
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index db78ce3d9..6852c11b0 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -2,8 +2,7 @@
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 <atomic> 5#include <thread>
6#include <chrono>
7 6
8#include "common/settings.h" 7#include "common/settings.h"
9#include "video_core/renderer_vulkan/vk_master_semaphore.h" 8#include "video_core/renderer_vulkan/vk_master_semaphore.h"
@@ -12,8 +11,6 @@
12 11
13namespace Vulkan { 12namespace Vulkan {
14 13
15using namespace std::chrono_literals;
16
17MasterSemaphore::MasterSemaphore(const Device& device) { 14MasterSemaphore::MasterSemaphore(const Device& device) {
18 static constexpr VkSemaphoreTypeCreateInfoKHR semaphore_type_ci{ 15 static constexpr VkSemaphoreTypeCreateInfoKHR semaphore_type_ci{
19 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, 16 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR,
@@ -34,9 +31,9 @@ MasterSemaphore::MasterSemaphore(const Device& device) {
34 // Validation layers have a bug where they fail to track resource usage when using timeline 31 // Validation layers have a bug where they fail to track resource usage when using timeline
35 // semaphores and synchronizing with GetSemaphoreCounterValueKHR. To workaround this issue, have 32 // semaphores and synchronizing with GetSemaphoreCounterValueKHR. To workaround this issue, have
36 // a separate thread waiting for each timeline semaphore value. 33 // a separate thread waiting for each timeline semaphore value.
37 debug_thread = std::thread([this] { 34 debug_thread = std::jthread([this](std::stop_token stop_token) {
38 u64 counter = 0; 35 u64 counter = 0;
39 while (!shutdown) { 36 while (!stop_token.stop_requested()) {
40 if (semaphore.Wait(counter, 10'000'000)) { 37 if (semaphore.Wait(counter, 10'000'000)) {
41 ++counter; 38 ++counter;
42 } 39 }
@@ -44,13 +41,6 @@ MasterSemaphore::MasterSemaphore(const Device& device) {
44 }); 41 });
45} 42}
46 43
47MasterSemaphore::~MasterSemaphore() { 44MasterSemaphore::~MasterSemaphore() = default;
48 shutdown = true;
49
50 // This thread might not be started
51 if (debug_thread.joinable()) {
52 debug_thread.join();
53 }
54}
55 45
56} // namespace Vulkan 46} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index 4b6d64daa..ee3cd35d0 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -65,11 +65,10 @@ public:
65 } 65 }
66 66
67private: 67private:
68 vk::Semaphore semaphore; ///< Timeline semaphore. 68 vk::Semaphore semaphore; ///< Timeline semaphore.
69 std::atomic<u64> gpu_tick{0}; ///< Current known GPU tick. 69 std::atomic<u64> gpu_tick{0}; ///< Current known GPU tick.
70 std::atomic<u64> current_tick{1}; ///< Current logical tick. 70 std::atomic<u64> current_tick{1}; ///< Current logical tick.
71 std::atomic<bool> shutdown{false}; ///< True when the object is being destroyed. 71 std::jthread debug_thread; ///< Debug thread to workaround validation layer bugs.
72 std::thread debug_thread; ///< Debug thread to workaround validation layer bugs.
73}; 72};
74 73
75} // namespace Vulkan 74} // namespace Vulkan
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 9680167ee..4efe042b6 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1098,7 +1098,15 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const
1098 return std::nullopt; 1098 return std::nullopt;
1099 } 1099 }
1100 const ImageInfo& existing = image.info; 1100 const ImageInfo& existing = image.info;
1101 if (False(options & RelaxedOptions::Format)) { 1101 if (True(options & RelaxedOptions::Format)) {
1102 // Format checking is relaxed, but we still have to check for matching bytes per block.
1103 // This avoids creating a view for blits on UE4 titles where formats with different bytes
1104 // per block are aliased.
1105 if (BytesPerBlock(existing.format) != BytesPerBlock(candidate.format)) {
1106 return std::nullopt;
1107 }
1108 } else {
1109 // Format comaptibility is not relaxed, ensure we are creating a view on a compatible format
1102 if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) { 1110 if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) {
1103 return std::nullopt; 1111 return std::nullopt;
1104 } 1112 }
diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp
index f0ee76519..758c038ba 100644
--- a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp
+++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp
@@ -50,7 +50,7 @@ NsightAftermathTracker::NsightAftermathTracker() {
50 } 50 }
51 dump_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / "gpucrash"; 51 dump_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::LogDir) / "gpucrash";
52 52
53 void(Common::FS::RemoveDirRecursively(dump_dir)); 53 Common::FS::RemoveDirRecursively(dump_dir);
54 if (!Common::FS::CreateDir(dump_dir)) { 54 if (!Common::FS::CreateDir(dump_dir)) {
55 LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory"); 55 LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory");
56 return; 56 return;
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
index 5c64c9bf7..0f60765bb 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
@@ -12,6 +12,14 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
12 VkDebugUtilsMessageTypeFlagsEXT type, 12 VkDebugUtilsMessageTypeFlagsEXT type,
13 const VkDebugUtilsMessengerCallbackDataEXT* data, 13 const VkDebugUtilsMessengerCallbackDataEXT* data,
14 [[maybe_unused]] void* user_data) { 14 [[maybe_unused]] void* user_data) {
15 // Skip logging known false-positive validation errors
16 switch (static_cast<u32>(data->messageIdNumber)) {
17 case 0x682a878au: // VUID-vkCmdBindVertexBuffers2EXT-pBuffers-parameter
18 case 0x99fb7dfdu: // UNASSIGNED-RequiredParameter (vkCmdBindVertexBuffers2EXT pBuffers[0])
19 return VK_FALSE;
20 default:
21 break;
22 }
15 const std::string_view message{data->pMessage}; 23 const std::string_view message{data->pMessage};
16 if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { 24 if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
17 LOG_CRITICAL(Render_Vulkan, "{}", message); 25 LOG_CRITICAL(Render_Vulkan, "{}", message);
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index 67183e64c..e04f7dfc6 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -100,8 +100,9 @@ struct Client::Impl {
100 request.body = data; 100 request.body = data;
101 101
102 httplib::Response response; 102 httplib::Response response;
103 httplib::Error error;
103 104
104 if (!cli->send(request, response)) { 105 if (!cli->send(request, response, error)) {
105 LOG_ERROR(WebService, "{} to {} returned null", method, host + path); 106 LOG_ERROR(WebService, "{} to {} returned null", method, host + path);
106 return WebResult{WebResult::Code::LibError, "Null response", ""}; 107 return WebResult{WebResult::Code::LibError, "Null response", ""};
107 } 108 }
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 86495803e..7524e3c40 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -51,11 +51,11 @@ void EmuThread::run() {
51 Common::SetCurrentThreadName(name.c_str()); 51 Common::SetCurrentThreadName(name.c_str());
52 52
53 auto& system = Core::System::GetInstance(); 53 auto& system = Core::System::GetInstance();
54 auto& gpu = system.GPU();
55 auto stop_token = stop_source.get_token();
54 56
55 system.RegisterHostThread(); 57 system.RegisterHostThread();
56 58
57 auto& gpu = system.GPU();
58
59 // Main process has been loaded. Make the context current to this thread and begin GPU and CPU 59 // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
60 // execution. 60 // execution.
61 gpu.Start(); 61 gpu.Start();
@@ -65,7 +65,7 @@ void EmuThread::run() {
65 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); 65 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
66 66
67 system.Renderer().ReadRasterizer()->LoadDiskResources( 67 system.Renderer().ReadRasterizer()->LoadDiskResources(
68 system.CurrentProcess()->GetTitleID(), stop_run, 68 system.CurrentProcess()->GetTitleID(), stop_token,
69 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { 69 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
70 emit LoadProgress(stage, value, total); 70 emit LoadProgress(stage, value, total);
71 }); 71 });
@@ -78,7 +78,7 @@ void EmuThread::run() {
78 // so that the DebugModeLeft signal can be emitted before the 78 // so that the DebugModeLeft signal can be emitted before the
79 // next execution step 79 // next execution step
80 bool was_active = false; 80 bool was_active = false;
81 while (!stop_run) { 81 while (!stop_token.stop_requested()) {
82 if (running) { 82 if (running) {
83 if (was_active) { 83 if (was_active) {
84 emit DebugModeLeft(); 84 emit DebugModeLeft();
@@ -100,7 +100,7 @@ void EmuThread::run() {
100 } 100 }
101 running_guard = false; 101 running_guard = false;
102 102
103 if (!stop_run) { 103 if (!stop_token.stop_requested()) {
104 was_active = true; 104 was_active = true;
105 emit DebugModeEntered(); 105 emit DebugModeEntered();
106 } 106 }
@@ -108,7 +108,7 @@ void EmuThread::run() {
108 UNIMPLEMENTED(); 108 UNIMPLEMENTED();
109 } else { 109 } else {
110 std::unique_lock lock{running_mutex}; 110 std::unique_lock lock{running_mutex};
111 running_cv.wait(lock, [this] { return IsRunning() || exec_step || stop_run; }); 111 running_cv.wait(lock, stop_token, [this] { return IsRunning() || exec_step; });
112 } 112 }
113 } 113 }
114 114
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index acfe2bc8c..402dd2ee1 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -89,16 +89,16 @@ public:
89 * Requests for the emulation thread to stop running 89 * Requests for the emulation thread to stop running
90 */ 90 */
91 void RequestStop() { 91 void RequestStop() {
92 stop_run = true; 92 stop_source.request_stop();
93 SetRunning(false); 93 SetRunning(false);
94 } 94 }
95 95
96private: 96private:
97 bool exec_step = false; 97 bool exec_step = false;
98 bool running = false; 98 bool running = false;
99 std::atomic_bool stop_run{false}; 99 std::stop_source stop_source;
100 std::mutex running_mutex; 100 std::mutex running_mutex;
101 std::condition_variable running_cv; 101 std::condition_variable_any running_cv;
102 Common::Event running_wait{}; 102 Common::Event running_wait{};
103 std::atomic_bool running_guard{false}; 103 std::atomic_bool running_guard{false};
104 104
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 57843ac5a..62bafc453 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -221,7 +221,7 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default
221// This must be in alphabetical order according to action name as it must have the same order as 221// This must be in alphabetical order according to action name as it must have the same order as
222// UISetting::values.shortcuts, which is alphabetically ordered. 222// UISetting::values.shortcuts, which is alphabetically ordered.
223// clang-format off 223// clang-format off
224const std::array<UISettings::Shortcut, 17> Config::default_hotkeys{{ 224const std::array<UISettings::Shortcut, 18> Config::default_hotkeys{{
225 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}}, 225 {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}},
226 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, 226 {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}},
227 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, 227 {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}},
@@ -236,6 +236,7 @@ const std::array<UISettings::Shortcut, 17> Config::default_hotkeys{{
236 {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, 236 {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}},
237 {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, 237 {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}},
238 {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, 238 {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}},
239 {QStringLiteral("Toggle Framerate Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+U"), Qt::ApplicationShortcut}},
239 {QStringLiteral("Toggle Mouse Panning"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F9"), Qt::ApplicationShortcut}}, 240 {QStringLiteral("Toggle Mouse Panning"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F9"), Qt::ApplicationShortcut}},
240 {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, 241 {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}},
241 {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}}, 242 {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}},
@@ -756,6 +757,8 @@ void Config::ReadCpuValues() {
756 QStringLiteral("cpuopt_unsafe_unfuse_fma"), true); 757 QStringLiteral("cpuopt_unsafe_unfuse_fma"), true);
757 ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error, 758 ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error,
758 QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true); 759 QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true);
760 ReadSettingGlobal(Settings::values.cpuopt_unsafe_ignore_standard_fpcr,
761 QStringLiteral("cpuopt_unsafe_ignore_standard_fpcr"), true);
759 ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan, 762 ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan,
760 QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true); 763 QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true);
761 ReadSettingGlobal(Settings::values.cpuopt_unsafe_fastmem_check, 764 ReadSettingGlobal(Settings::values.cpuopt_unsafe_fastmem_check,
@@ -811,6 +814,8 @@ void Config::ReadRendererValues() {
811 true); 814 true);
812 ReadSettingGlobal(Settings::values.accelerate_astc, QStringLiteral("accelerate_astc"), true); 815 ReadSettingGlobal(Settings::values.accelerate_astc, QStringLiteral("accelerate_astc"), true);
813 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); 816 ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true);
817 ReadSettingGlobal(Settings::values.disable_fps_limit, QStringLiteral("disable_fps_limit"),
818 false);
814 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), 819 ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"),
815 false); 820 false);
816 ReadSettingGlobal(Settings::values.use_asynchronous_shaders, 821 ReadSettingGlobal(Settings::values.use_asynchronous_shaders,
@@ -1340,6 +1345,8 @@ void Config::SaveCpuValues() {
1340 Settings::values.cpuopt_unsafe_unfuse_fma, true); 1345 Settings::values.cpuopt_unsafe_unfuse_fma, true);
1341 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), 1346 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"),
1342 Settings::values.cpuopt_unsafe_reduce_fp_error, true); 1347 Settings::values.cpuopt_unsafe_reduce_fp_error, true);
1348 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_ignore_standard_fpcr"),
1349 Settings::values.cpuopt_unsafe_ignore_standard_fpcr, true);
1343 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), 1350 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"),
1344 Settings::values.cpuopt_unsafe_inaccurate_nan, true); 1351 Settings::values.cpuopt_unsafe_inaccurate_nan, true);
1345 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_fastmem_check"), 1352 WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_fastmem_check"),
@@ -1396,6 +1403,8 @@ void Config::SaveRendererValues() {
1396 true); 1403 true);
1397 WriteSettingGlobal(QStringLiteral("accelerate_astc"), Settings::values.accelerate_astc, true); 1404 WriteSettingGlobal(QStringLiteral("accelerate_astc"), Settings::values.accelerate_astc, true);
1398 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); 1405 WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true);
1406 WriteSettingGlobal(QStringLiteral("disable_fps_limit"), Settings::values.disable_fps_limit,
1407 false);
1399 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), 1408 WriteSettingGlobal(QStringLiteral("use_assembly_shaders"),
1400 Settings::values.use_assembly_shaders, false); 1409 Settings::values.use_assembly_shaders, false);
1401 WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"), 1410 WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"),
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index ce3355588..3c1de0ac9 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -42,7 +42,7 @@ public:
42 default_mouse_buttons; 42 default_mouse_buttons;
43 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; 43 static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
44 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; 44 static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
45 static const std::array<UISettings::Shortcut, 17> default_hotkeys; 45 static const std::array<UISettings::Shortcut, 18> default_hotkeys;
46 46
47private: 47private:
48 void Initialize(const std::string& config_name); 48 void Initialize(const std::string& config_name);
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index 22219cbad..13db2ba98 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -34,12 +34,15 @@ void ConfigureCpu::SetConfiguration() {
34 ui->accuracy->setEnabled(runtime_lock); 34 ui->accuracy->setEnabled(runtime_lock);
35 ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); 35 ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock);
36 ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); 36 ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock);
37 ui->cpuopt_unsafe_ignore_standard_fpcr->setEnabled(runtime_lock);
37 ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); 38 ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock);
38 ui->cpuopt_unsafe_fastmem_check->setEnabled(runtime_lock); 39 ui->cpuopt_unsafe_fastmem_check->setEnabled(runtime_lock);
39 40
40 ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()); 41 ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue());
41 ui->cpuopt_unsafe_reduce_fp_error->setChecked( 42 ui->cpuopt_unsafe_reduce_fp_error->setChecked(
42 Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()); 43 Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue());
44 ui->cpuopt_unsafe_ignore_standard_fpcr->setChecked(
45 Settings::values.cpuopt_unsafe_ignore_standard_fpcr.GetValue());
43 ui->cpuopt_unsafe_inaccurate_nan->setChecked( 46 ui->cpuopt_unsafe_inaccurate_nan->setChecked(
44 Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()); 47 Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue());
45 ui->cpuopt_unsafe_fastmem_check->setChecked( 48 ui->cpuopt_unsafe_fastmem_check->setChecked(
@@ -84,6 +87,9 @@ void ConfigureCpu::ApplyConfiguration() {
84 ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error, 87 ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error,
85 ui->cpuopt_unsafe_reduce_fp_error, 88 ui->cpuopt_unsafe_reduce_fp_error,
86 cpuopt_unsafe_reduce_fp_error); 89 cpuopt_unsafe_reduce_fp_error);
90 ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_ignore_standard_fpcr,
91 ui->cpuopt_unsafe_ignore_standard_fpcr,
92 cpuopt_unsafe_ignore_standard_fpcr);
87 ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan, 93 ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan,
88 ui->cpuopt_unsafe_inaccurate_nan, 94 ui->cpuopt_unsafe_inaccurate_nan,
89 cpuopt_unsafe_inaccurate_nan); 95 cpuopt_unsafe_inaccurate_nan);
@@ -137,6 +143,9 @@ void ConfigureCpu::SetupPerGameUI() {
137 ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error, 143 ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error,
138 Settings::values.cpuopt_unsafe_reduce_fp_error, 144 Settings::values.cpuopt_unsafe_reduce_fp_error,
139 cpuopt_unsafe_reduce_fp_error); 145 cpuopt_unsafe_reduce_fp_error);
146 ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_ignore_standard_fpcr,
147 Settings::values.cpuopt_unsafe_ignore_standard_fpcr,
148 cpuopt_unsafe_ignore_standard_fpcr);
140 ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan, 149 ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan,
141 Settings::values.cpuopt_unsafe_inaccurate_nan, 150 Settings::values.cpuopt_unsafe_inaccurate_nan,
142 cpuopt_unsafe_inaccurate_nan); 151 cpuopt_unsafe_inaccurate_nan);
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index 57ff2772a..b2b5f1671 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -40,6 +40,7 @@ private:
40 40
41 ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma; 41 ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma;
42 ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error; 42 ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error;
43 ConfigurationShared::CheckState cpuopt_unsafe_ignore_standard_fpcr;
43 ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan; 44 ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan;
44 ConfigurationShared::CheckState cpuopt_unsafe_fastmem_check; 45 ConfigurationShared::CheckState cpuopt_unsafe_fastmem_check;
45}; 46};
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui
index 31ef9e3f5..0e296d4e5 100644
--- a/src/yuzu/configuration/configure_cpu.ui
+++ b/src/yuzu/configuration/configure_cpu.ui
@@ -112,6 +112,18 @@
112 </widget> 112 </widget>
113 </item> 113 </item>
114 <item> 114 <item>
115 <widget class="QCheckBox" name="cpuopt_unsafe_ignore_standard_fpcr">
116 <property name="toolTip">
117 <string>
118 &lt;div&gt;This option improves the speed of 32 bits ASIMD floating-point functions by running with incorrect rounding modes.&lt;/div&gt;
119 </string>
120 </property>
121 <property name="text">
122 <string>Faster ASIMD instructions (32 bits only)</string>
123 </property>
124 </widget>
125 </item>
126 <item>
115 <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> 127 <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan">
116 <property name="toolTip"> 128 <property name="toolTip">
117 <string> 129 <string>
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index a9e611125..8d13c9857 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -28,6 +28,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
28 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 28 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
29 29
30 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); 30 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
31 ui->disable_fps_limit->setChecked(Settings::values.disable_fps_limit.GetValue());
31 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); 32 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
32 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); 33 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
33 ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue()); 34 ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue());
@@ -58,6 +59,8 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
58 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 59 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
59 ui->anisotropic_filtering_combobox); 60 ui->anisotropic_filtering_combobox);
60 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); 61 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync);
62 ConfigurationShared::ApplyPerGameSetting(&Settings::values.disable_fps_limit,
63 ui->disable_fps_limit, disable_fps_limit);
61 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, 64 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
62 ui->use_assembly_shaders, use_assembly_shaders); 65 ui->use_assembly_shaders, use_assembly_shaders);
63 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, 66 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
@@ -100,6 +103,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
100 if (Settings::IsConfiguringGlobal()) { 103 if (Settings::IsConfiguringGlobal()) {
101 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); 104 ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
102 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); 105 ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
106 ui->disable_fps_limit->setEnabled(Settings::values.disable_fps_limit.UsingGlobal());
103 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); 107 ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal());
104 ui->use_asynchronous_shaders->setEnabled( 108 ui->use_asynchronous_shaders->setEnabled(
105 Settings::values.use_asynchronous_shaders.UsingGlobal()); 109 Settings::values.use_asynchronous_shaders.UsingGlobal());
@@ -112,6 +116,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
112 } 116 }
113 117
114 ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); 118 ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync);
119 ConfigurationShared::SetColoredTristate(ui->disable_fps_limit,
120 Settings::values.disable_fps_limit, disable_fps_limit);
115 ConfigurationShared::SetColoredTristate( 121 ConfigurationShared::SetColoredTristate(
116 ui->use_assembly_shaders, Settings::values.use_assembly_shaders, use_assembly_shaders); 122 ui->use_assembly_shaders, Settings::values.use_assembly_shaders, use_assembly_shaders);
117 ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, 123 ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders,
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 9148aacf2..6ac5f20ec 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -35,6 +35,7 @@ private:
35 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; 35 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui;
36 36
37 ConfigurationShared::CheckState use_vsync; 37 ConfigurationShared::CheckState use_vsync;
38 ConfigurationShared::CheckState disable_fps_limit;
38 ConfigurationShared::CheckState use_assembly_shaders; 39 ConfigurationShared::CheckState use_assembly_shaders;
39 ConfigurationShared::CheckState use_asynchronous_shaders; 40 ConfigurationShared::CheckState use_asynchronous_shaders;
40 ConfigurationShared::CheckState use_fast_gpu_time; 41 ConfigurationShared::CheckState use_fast_gpu_time;
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index ad0840355..18c43629e 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -77,6 +77,24 @@
77 </widget> 77 </widget>
78 </item> 78 </item>
79 <item> 79 <item>
80 <widget class="QCheckBox" name="disable_fps_limit">
81 <property name="enabled">
82 <bool>true</bool>
83 </property>
84 <property name="toolTip">
85 <string>
86 &lt;html&gt;&lt;head/&gt;&lt;body&gt;
87 &lt;p&gt;Presents guest frames as they become available, disabling the FPS limit in most titles.&lt;/p&gt;
88 &lt;p&gt;NOTE: Will cause instabilities.&lt;/p&gt;
89 &lt;/body&gt;&lt;/html&gt;
90 </string>
91 </property>
92 <property name="text">
93 <string>Disable framerate limit (experimental)</string>
94 </property>
95 </widget>
96 </item>
97 <item>
80 <widget class="QCheckBox" name="use_assembly_shaders"> 98 <widget class="QCheckBox" name="use_assembly_shaders">
81 <property name="toolTip"> 99 <property name="toolTip">
82 <string>Enabling this reduces shader stutter. Enables OpenGL assembly shaders on supported Nvidia devices (NV_gpu_program5 is required). This feature is experimental.</string> 100 <string>Enabling this reduces shader stutter. Enables OpenGL assembly shaders on supported Nvidia devices (NV_gpu_program5 is required). This feature is experimental.</string>
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index a1d434aca..8c00eec59 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -47,6 +47,8 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, const std::str
47 ui->setupUi(this); 47 ui->setupUi(this);
48 setFocusPolicy(Qt::ClickFocus); 48 setFocusPolicy(Qt::ClickFocus);
49 setWindowTitle(tr("Properties")); 49 setWindowTitle(tr("Properties"));
50 // remove Help question mark button from the title bar
51 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
50 52
51 ui->addonsTab->SetTitleId(title_id); 53 ui->addonsTab->SetTitleId(title_id);
52 54
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui
index adf6d0b39..7da14146b 100644
--- a/src/yuzu/configuration/configure_per_game.ui
+++ b/src/yuzu/configuration/configure_per_game.ui
@@ -6,10 +6,15 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>800</width> 9 <width>900</width>
10 <height>600</height> 10 <height>600</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="minimumSize">
14 <size>
15 <width>900</width>
16 </size>
17 </property>
13 <property name="windowTitle"> 18 <property name="windowTitle">
14 <string>Dialog</string> 19 <string>Dialog</string>
15 </property> 20 </property>
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 9b709d405..ebb0f411c 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -79,8 +79,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() {
79 std::sort(disabled_addons.begin(), disabled_addons.end()); 79 std::sort(disabled_addons.begin(), disabled_addons.end());
80 std::sort(current.begin(), current.end()); 80 std::sort(current.begin(), current.end());
81 if (disabled_addons != current) { 81 if (disabled_addons != current) {
82 void(Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / 82 Common::FS::RemoveFile(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
83 "game_list" / fmt::format("{:016X}.pv.txt", title_id))); 83 "game_list" / fmt::format("{:016X}.pv.txt", title_id));
84 } 84 }
85 85
86 Settings::values.disabled_addons[title_id] = disabled_addons; 86 Settings::values.disabled_addons[title_id] = disabled_addons;
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index be8933c5c..75ab5ef44 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -194,10 +194,10 @@ static void RemoveCachedContents() {
194 const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; 194 const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information";
195 const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; 195 const auto offline_system_data = cache_dir / "offline_web_applet_system_data";
196 196
197 void(Common::FS::RemoveDirRecursively(offline_fonts)); 197 Common::FS::RemoveDirRecursively(offline_fonts);
198 void(Common::FS::RemoveDirRecursively(offline_manual)); 198 Common::FS::RemoveDirRecursively(offline_manual);
199 void(Common::FS::RemoveDirRecursively(offline_legal_information)); 199 Common::FS::RemoveDirRecursively(offline_legal_information);
200 void(Common::FS::RemoveDirRecursively(offline_system_data)); 200 Common::FS::RemoveDirRecursively(offline_system_data);
201} 201}
202 202
203GMainWindow::GMainWindow() 203GMainWindow::GMainWindow()
@@ -1025,7 +1025,11 @@ void GMainWindow::InitializeHotkeys() {
1025 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), 1025 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
1026 &QShortcut::activated, this, 1026 &QShortcut::activated, this,
1027 [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); 1027 [] { Settings::values.audio_muted = !Settings::values.audio_muted; });
1028 1028 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Framerate Limit"), this),
1029 &QShortcut::activated, this, [] {
1030 Settings::values.disable_fps_limit.SetValue(
1031 !Settings::values.disable_fps_limit.GetValue());
1032 });
1029 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this), 1033 connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this),
1030 &QShortcut::activated, this, [&] { 1034 &QShortcut::activated, this, [&] {
1031 Settings::values.mouse_panning = !Settings::values.mouse_panning; 1035 Settings::values.mouse_panning = !Settings::values.mouse_panning;
@@ -1739,8 +1743,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
1739 RemoveAddOnContent(program_id, entry_type); 1743 RemoveAddOnContent(program_id, entry_type);
1740 break; 1744 break;
1741 } 1745 }
1742 void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / 1746 Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
1743 "game_list")); 1747 "game_list");
1744 game_list->PopulateAsync(UISettings::values.game_dirs); 1748 game_list->PopulateAsync(UISettings::values.game_dirs);
1745} 1749}
1746 1750
@@ -2209,8 +2213,8 @@ void GMainWindow::OnMenuInstallToNAND() {
2209 : tr("%n file(s) failed to install\n", "", failed_files.size())); 2213 : tr("%n file(s) failed to install\n", "", failed_files.size()));
2210 2214
2211 QMessageBox::information(this, tr("Install Results"), install_results); 2215 QMessageBox::information(this, tr("Install Results"), install_results);
2212 void(Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / 2216 Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
2213 "game_list")); 2217 "game_list");
2214 game_list->PopulateAsync(UISettings::values.game_dirs); 2218 game_list->PopulateAsync(UISettings::values.game_dirs);
2215 ui.action_Install_File_NAND->setEnabled(true); 2219 ui.action_Install_File_NAND->setEnabled(true);
2216} 2220}
@@ -2842,7 +2846,7 @@ void GMainWindow::MigrateConfigFiles() {
2842 LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination); 2846 LOG_INFO(Frontend, "Migrating config file from {} to {}", origin, destination);
2843 if (!Common::FS::RenameFile(origin, destination)) { 2847 if (!Common::FS::RenameFile(origin, destination)) {
2844 // Delete the old config file if one already exists in the new location. 2848 // Delete the old config file if one already exists in the new location.
2845 void(Common::FS::RemoveFile(origin)); 2849 Common::FS::RemoveFile(origin);
2846 } 2850 }
2847 } 2851 }
2848} 2852}
@@ -3036,9 +3040,9 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
3036 3040
3037 const auto keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir); 3041 const auto keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
3038 3042
3039 void(Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated")); 3043 Common::FS::RemoveFile(keys_dir / "prod.keys_autogenerated");
3040 void(Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated")); 3044 Common::FS::RemoveFile(keys_dir / "console.keys_autogenerated");
3041 void(Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated")); 3045 Common::FS::RemoveFile(keys_dir / "title.keys_autogenerated");
3042 } 3046 }
3043 3047
3044 Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); 3048 Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance();
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 621b31571..60bf66ec0 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -443,6 +443,8 @@ void Config::ReadValues() {
443 sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true)); 443 sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true));
444 Settings::values.use_vsync.SetValue( 444 Settings::values.use_vsync.SetValue(
445 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); 445 static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1)));
446 Settings::values.disable_fps_limit.SetValue(
447 sdl2_config->GetBoolean("Renderer", "disable_fps_limit", false));
446 Settings::values.use_assembly_shaders.SetValue( 448 Settings::values.use_assembly_shaders.SetValue(
447 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", true)); 449 sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", true));
448 Settings::values.use_asynchronous_shaders.SetValue( 450 Settings::values.use_asynchronous_shaders.SetValue(
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index f0a0ec398..cc9850aad 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -264,7 +264,10 @@ swap_screen =
264 264
265[Audio] 265[Audio]
266# Which audio output engine to use. 266# Which audio output engine to use.
267# auto (default): Auto-select, null: No audio output, cubeb: Cubeb audio engine (if available) 267# auto (default): Auto-select
268# cubeb: Cubeb audio engine (if available)
269# sdl2: SDL2 audio engine (if available)
270# null: No audio output
268output_engine = 271output_engine =
269 272
270# Whether or not to enable the audio-stretching post-processing effect. 273# Whether or not to enable the audio-stretching post-processing effect.
@@ -363,6 +366,9 @@ use_debug_asserts =
363use_auto_stub = 366use_auto_stub =
364# Enables/Disables the macro JIT compiler 367# Enables/Disables the macro JIT compiler
365disable_macro_jit=false 368disable_macro_jit=false
369# Presents guest frames as they become available. Experimental.
370# false: Disabled (default), true: Enabled
371disable_fps_limit=false
366 372
367[WebService] 373[WebService]
368# Whether or not to enable telemetry 374# Whether or not to enable telemetry
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 584967f5c..50e388312 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -219,7 +219,7 @@ int main(int argc, char** argv) {
219 system.GPU().Start(); 219 system.GPU().Start();
220 220
221 system.Renderer().ReadRasterizer()->LoadDiskResources( 221 system.Renderer().ReadRasterizer()->LoadDiskResources(
222 system.CurrentProcess()->GetTitleID(), false, 222 system.CurrentProcess()->GetTitleID(), std::stop_token{},
223 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); 223 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
224 224
225 void(system.Run()); 225 void(system.Run());