summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--externals/CMakeLists.txt5
m---------externals/dynarmic0
-rw-r--r--src/common/logging/backend.cpp351
-rw-r--r--src/common/logging/backend.h113
-rw-r--r--src/common/settings.h2
-rw-r--r--src/common/x64/xbyak_abi.h2
-rw-r--r--src/common/x64/xbyak_util.h2
-rw-r--r--src/core/core.cpp17
-rw-r--r--src/core/core.h8
-rw-r--r--src/core/hle/kernel/kernel.cpp23
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp31
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp8
-rw-r--r--src/tests/common/param_package.cpp2
-rw-r--r--src/video_core/macro/macro_jit_x64.h2
-rw-r--r--src/video_core/textures/texture.h2
-rw-r--r--src/yuzu/CMakeLists.txt9
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp34
-rw-r--r--src/yuzu/debugger/console.cpp11
-rw-r--r--src/yuzu/main.cpp19
-rw-r--r--src/yuzu_cmd/yuzu.cpp22
20 files changed, 324 insertions, 339 deletions
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index 4b8d35548..0c2c059a9 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -7,7 +7,9 @@ include(DownloadExternals)
7# xbyak 7# xbyak
8if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) 8if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
9 add_library(xbyak INTERFACE) 9 add_library(xbyak INTERFACE)
10 target_include_directories(xbyak SYSTEM INTERFACE ./xbyak/xbyak) 10 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
11 file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/xbyak/xbyak DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
12 target_include_directories(xbyak SYSTEM INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/xbyak/include)
11 target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES) 13 target_compile_definitions(xbyak INTERFACE XBYAK_NO_OP_NAMES)
12endif() 14endif()
13 15
@@ -19,6 +21,7 @@ target_include_directories(catch-single-include INTERFACE catch/single_include)
19if (ARCHITECTURE_x86_64) 21if (ARCHITECTURE_x86_64)
20 set(DYNARMIC_TESTS OFF) 22 set(DYNARMIC_TESTS OFF)
21 set(DYNARMIC_NO_BUNDLED_FMT ON) 23 set(DYNARMIC_NO_BUNDLED_FMT ON)
24 set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
22 add_subdirectory(dynarmic) 25 add_subdirectory(dynarmic)
23endif() 26endif()
24 27
diff --git a/externals/dynarmic b/externals/dynarmic
Subproject 7946868af49d403fe54c92d2d60ef986513d1fe Subproject 517e35f845e010788b6febe42fd6ddb187b8c23
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 61dddab3f..949384fd3 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -2,13 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6#include <atomic> 5#include <atomic>
7#include <chrono> 6#include <chrono>
8#include <climits> 7#include <climits>
9#include <condition_variable> 8#include <exception>
10#include <memory>
11#include <mutex>
12#include <thread> 9#include <thread>
13#include <vector> 10#include <vector>
14 11
@@ -16,104 +13,229 @@
16#include <windows.h> // For OutputDebugStringW 13#include <windows.h> // For OutputDebugStringW
17#endif 14#endif
18 15
19#include "common/assert.h"
20#include "common/fs/file.h" 16#include "common/fs/file.h"
21#include "common/fs/fs.h" 17#include "common/fs/fs.h"
18#include "common/fs/fs_paths.h"
19#include "common/fs/path_util.h"
22#include "common/literals.h" 20#include "common/literals.h"
23 21
24#include "common/logging/backend.h" 22#include "common/logging/backend.h"
25#include "common/logging/log.h" 23#include "common/logging/log.h"
26#include "common/logging/text_formatter.h" 24#include "common/logging/text_formatter.h"
27#include "common/settings.h" 25#include "common/settings.h"
26#ifdef _WIN32
28#include "common/string_util.h" 27#include "common/string_util.h"
28#endif
29#include "common/threadsafe_queue.h" 29#include "common/threadsafe_queue.h"
30 30
31namespace Common::Log { 31namespace Common::Log {
32 32
33namespace {
34
33/** 35/**
34 * Static state as a singleton. 36 * Interface for logging backends.
35 */ 37 */
36class Impl { 38class Backend {
37public: 39public:
38 static Impl& Instance() { 40 virtual ~Backend() = default;
39 static Impl backend; 41
40 return backend; 42 virtual void Write(const Entry& entry) = 0;
43
44 virtual void EnableForStacktrace() = 0;
45
46 virtual void Flush() = 0;
47};
48
49/**
50 * Backend that writes to stderr and with color
51 */
52class ColorConsoleBackend final : public Backend {
53public:
54 explicit ColorConsoleBackend() = default;
55
56 ~ColorConsoleBackend() override = default;
57
58 void Write(const Entry& entry) override {
59 if (enabled.load(std::memory_order_relaxed)) {
60 PrintColoredMessage(entry);
61 }
41 } 62 }
42 63
43 Impl(const Impl&) = delete; 64 void Flush() override {
44 Impl& operator=(const Impl&) = delete; 65 // stderr shouldn't be buffered
66 }
45 67
46 Impl(Impl&&) = delete; 68 void EnableForStacktrace() override {
47 Impl& operator=(Impl&&) = delete; 69 enabled = true;
70 }
48 71
49 void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, 72 void SetEnabled(bool enabled_) {
50 const char* function, std::string message) { 73 enabled = enabled_;
51 message_queue.Push( 74 }
52 CreateEntry(log_class, log_level, filename, line_num, function, std::move(message))); 75
76private:
77 std::atomic_bool enabled{false};
78};
79
80/**
81 * Backend that writes to a file passed into the constructor
82 */
83class FileBackend final : public Backend {
84public:
85 explicit FileBackend(const std::filesystem::path& filename) {
86 auto old_filename = filename;
87 old_filename += ".old.txt";
88
89 // Existence checks are done within the functions themselves.
90 // We don't particularly care if these succeed or not.
91 static_cast<void>(FS::RemoveFile(old_filename));
92 static_cast<void>(FS::RenameFile(filename, old_filename));
93
94 file = std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write,
95 FS::FileType::TextFile);
96 }
97
98 ~FileBackend() override = default;
99
100 void Write(const Entry& entry) override {
101 if (!enabled) {
102 return;
103 }
104
105 bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
106
107 using namespace Common::Literals;
108 // Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
109 const auto write_limit = Settings::values.extended_logging ? 1_GiB : 100_MiB;
110 const bool write_limit_exceeded = bytes_written > write_limit;
111 if (entry.log_level >= Level::Error || write_limit_exceeded) {
112 if (write_limit_exceeded) {
113 // Stop writing after the write limit is exceeded.
114 // Don't close the file so we can print a stacktrace if necessary
115 enabled = false;
116 }
117 file->Flush();
118 }
119 }
120
121 void Flush() override {
122 file->Flush();
123 }
124
125 void EnableForStacktrace() override {
126 enabled = true;
127 bytes_written = 0;
53 } 128 }
54 129
55 void AddBackend(std::unique_ptr<Backend> backend) { 130private:
56 std::lock_guard lock{writing_mutex}; 131 std::unique_ptr<FS::IOFile> file;
57 backends.push_back(std::move(backend)); 132 bool enabled = true;
133 std::size_t bytes_written = 0;
134};
135
136/**
137 * Backend that writes to Visual Studio's output window
138 */
139class DebuggerBackend final : public Backend {
140public:
141 explicit DebuggerBackend() = default;
142
143 ~DebuggerBackend() override = default;
144
145 void Write(const Entry& entry) override {
146#ifdef _WIN32
147 ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
148#endif
58 } 149 }
59 150
60 void RemoveBackend(std::string_view backend_name) { 151 void Flush() override {}
61 std::lock_guard lock{writing_mutex}; 152
153 void EnableForStacktrace() override {}
154};
155
156bool initialization_in_progress_suppress_logging = true;
62 157
63 std::erase_if(backends, [&backend_name](const auto& backend) { 158/**
64 return backend_name == backend->GetName(); 159 * Static state as a singleton.
65 }); 160 */
161class Impl {
162public:
163 static Impl& Instance() {
164 if (!instance) {
165 throw std::runtime_error("Using Logging instance before its initialization");
166 }
167 return *instance;
66 } 168 }
67 169
68 const Filter& GetGlobalFilter() const { 170 static void Initialize() {
69 return filter; 171 if (instance) {
172 LOG_WARNING(Log, "Reinitializing logging backend");
173 return;
174 }
175 using namespace Common::FS;
176 const auto& log_dir = GetYuzuPath(YuzuPath::LogDir);
177 void(CreateDir(log_dir));
178 Filter filter;
179 filter.ParseFilterString(Settings::values.log_filter.GetValue());
180 instance = std::unique_ptr<Impl, decltype(&Deleter)>(new Impl(log_dir / LOG_FILE, filter),
181 Deleter);
182 initialization_in_progress_suppress_logging = false;
70 } 183 }
71 184
185 Impl(const Impl&) = delete;
186 Impl& operator=(const Impl&) = delete;
187
188 Impl(Impl&&) = delete;
189 Impl& operator=(Impl&&) = delete;
190
72 void SetGlobalFilter(const Filter& f) { 191 void SetGlobalFilter(const Filter& f) {
73 filter = f; 192 filter = f;
74 } 193 }
75 194
76 Backend* GetBackend(std::string_view backend_name) { 195 void SetColorConsoleBackendEnabled(bool enabled) {
77 const auto it = 196 color_console_backend.SetEnabled(enabled);
78 std::find_if(backends.begin(), backends.end(), 197 }
79 [&backend_name](const auto& i) { return backend_name == i->GetName(); }); 198
80 if (it == backends.end()) 199 void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
81 return nullptr; 200 const char* function, std::string message) {
82 return it->get(); 201 if (!filter.CheckMessage(log_class, log_level))
202 return;
203 const Entry& entry =
204 CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
205 message_queue.Push(entry);
83 } 206 }
84 207
85private: 208private:
86 Impl() { 209 Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
87 backend_thread = std::thread([&] { 210 : filter{filter_}, file_backend{file_backend_filename}, backend_thread{std::thread([this] {
88 Entry entry; 211 Common::SetCurrentThreadName("yuzu:Log");
89 auto write_logs = [&](Entry& e) { 212 Entry entry;
90 std::lock_guard lock{writing_mutex}; 213 const auto write_logs = [this, &entry]() {
91 for (const auto& backend : backends) { 214 ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
92 backend->Write(e); 215 };
93 } 216 while (true) {
94 }; 217 entry = message_queue.PopWait();
95 while (true) { 218 if (entry.final_entry) {
96 entry = message_queue.PopWait(); 219 break;
97 if (entry.final_entry) { 220 }
98 break; 221 write_logs();
99 } 222 }
100 write_logs(entry); 223 // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
101 } 224 // case where a system is repeatedly spamming logs even on close.
225 int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
226 while (max_logs_to_write-- && message_queue.Pop(entry)) {
227 write_logs();
228 }
229 })} {}
102 230
103 // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a 231 ~Impl() {
104 // case where a system is repeatedly spamming logs even on close. 232 StopBackendThread();
105 const int MAX_LOGS_TO_WRITE = filter.IsDebug() ? INT_MAX : 100;
106 int logs_written = 0;
107 while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) {
108 write_logs(entry);
109 }
110 });
111 } 233 }
112 234
113 ~Impl() { 235 void StopBackendThread() {
114 Entry entry; 236 Entry stop_entry{};
115 entry.final_entry = true; 237 stop_entry.final_entry = true;
116 message_queue.Push(entry); 238 message_queue.Push(stop_entry);
117 backend_thread.join(); 239 backend_thread.join();
118 } 240 }
119 241
@@ -135,100 +257,51 @@ private:
135 }; 257 };
136 } 258 }
137 259
138 std::mutex writing_mutex; 260 void ForEachBackend(auto lambda) {
139 std::thread backend_thread; 261 lambda(static_cast<Backend&>(debugger_backend));
140 std::vector<std::unique_ptr<Backend>> backends; 262 lambda(static_cast<Backend&>(color_console_backend));
141 MPSCQueue<Entry> message_queue; 263 lambda(static_cast<Backend&>(file_backend));
142 Filter filter; 264 }
143 std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
144};
145
146ConsoleBackend::~ConsoleBackend() = default;
147
148void ConsoleBackend::Write(const Entry& entry) {
149 PrintMessage(entry);
150}
151
152ColorConsoleBackend::~ColorConsoleBackend() = default;
153
154void ColorConsoleBackend::Write(const Entry& entry) {
155 PrintColoredMessage(entry);
156}
157
158FileBackend::FileBackend(const std::filesystem::path& filename) {
159 auto old_filename = filename;
160 old_filename += ".old.txt";
161
162 // Existence checks are done within the functions themselves.
163 // We don't particularly care if these succeed or not.
164 FS::RemoveFile(old_filename);
165 void(FS::RenameFile(filename, old_filename));
166
167 file =
168 std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
169}
170
171FileBackend::~FileBackend() = default;
172 265
173void FileBackend::Write(const Entry& entry) { 266 static void Deleter(Impl* ptr) {
174 if (!file->IsOpen()) { 267 delete ptr;
175 return;
176 } 268 }
177 269
178 using namespace Common::Literals; 270 static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
179 // Prevent logs from exceeding a set maximum size in the event that log entries are spammed.
180 constexpr std::size_t MAX_BYTES_WRITTEN = 100_MiB;
181 constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1_GiB;
182 271
183 const bool write_limit_exceeded = 272 Filter filter;
184 bytes_written > MAX_BYTES_WRITTEN_EXTENDED || 273 DebuggerBackend debugger_backend{};
185 (bytes_written > MAX_BYTES_WRITTEN && !Settings::values.extended_logging); 274 ColorConsoleBackend color_console_backend{};
275 FileBackend file_backend;
186 276
187 // Close the file after the write limit is exceeded. 277 std::thread backend_thread;
188 if (write_limit_exceeded) { 278 MPSCQueue<Entry> message_queue{};
189 file->Close(); 279 std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
190 return; 280};
191 } 281} // namespace
192 282
193 bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); 283void Initialize() {
194 if (entry.log_level >= Level::Error) { 284 Impl::Initialize();
195 file->Flush();
196 }
197} 285}
198 286
199DebuggerBackend::~DebuggerBackend() = default; 287void DisableLoggingInTests() {
200 288 initialization_in_progress_suppress_logging = true;
201void DebuggerBackend::Write(const Entry& entry) {
202#ifdef _WIN32
203 ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
204#endif
205} 289}
206 290
207void SetGlobalFilter(const Filter& filter) { 291void SetGlobalFilter(const Filter& filter) {
208 Impl::Instance().SetGlobalFilter(filter); 292 Impl::Instance().SetGlobalFilter(filter);
209} 293}
210 294
211void AddBackend(std::unique_ptr<Backend> backend) { 295void SetColorConsoleBackendEnabled(bool enabled) {
212 Impl::Instance().AddBackend(std::move(backend)); 296 Impl::Instance().SetColorConsoleBackendEnabled(enabled);
213}
214
215void RemoveBackend(std::string_view backend_name) {
216 Impl::Instance().RemoveBackend(backend_name);
217}
218
219Backend* GetBackend(std::string_view backend_name) {
220 return Impl::Instance().GetBackend(backend_name);
221} 297}
222 298
223void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, 299void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
224 unsigned int line_num, const char* function, const char* format, 300 unsigned int line_num, const char* function, const char* format,
225 const fmt::format_args& args) { 301 const fmt::format_args& args) {
226 auto& instance = Impl::Instance(); 302 if (!initialization_in_progress_suppress_logging) {
227 const auto& filter = instance.GetGlobalFilter(); 303 Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
228 if (!filter.CheckMessage(log_class, log_level)) 304 fmt::vformat(format, args));
229 return; 305 }
230
231 instance.PushEntry(log_class, log_level, filename, line_num, function,
232 fmt::vformat(format, args));
233} 306}
234} // namespace Common::Log 307} // namespace Common::Log
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index 4b9a910c1..cb7839ee9 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -5,120 +5,21 @@
5#pragma once 5#pragma once
6 6
7#include <filesystem> 7#include <filesystem>
8#include <memory>
9#include <string>
10#include <string_view>
11#include "common/logging/filter.h" 8#include "common/logging/filter.h"
12#include "common/logging/log.h"
13
14namespace Common::FS {
15class IOFile;
16}
17 9
18namespace Common::Log { 10namespace Common::Log {
19 11
20class Filter; 12class Filter;
21 13
22/** 14/// Initializes the logging system. This should be the first thing called in main.
23 * Interface for logging backends. As loggers can be created and removed at runtime, this can be 15void Initialize();
24 * used by a frontend for adding a custom logging backend as needed
25 */
26class Backend {
27public:
28 virtual ~Backend() = default;
29
30 virtual void SetFilter(const Filter& new_filter) {
31 filter = new_filter;
32 }
33 virtual const char* GetName() const = 0;
34 virtual void Write(const Entry& entry) = 0;
35
36private:
37 Filter filter;
38};
39
40/**
41 * Backend that writes to stderr without any color commands
42 */
43class ConsoleBackend : public Backend {
44public:
45 ~ConsoleBackend() override;
46
47 static const char* Name() {
48 return "console";
49 }
50 const char* GetName() const override {
51 return Name();
52 }
53 void Write(const Entry& entry) override;
54};
55
56/**
57 * Backend that writes to stderr and with color
58 */
59class ColorConsoleBackend : public Backend {
60public:
61 ~ColorConsoleBackend() override;
62
63 static const char* Name() {
64 return "color_console";
65 }
66
67 const char* GetName() const override {
68 return Name();
69 }
70 void Write(const Entry& entry) override;
71};
72 16
73/** 17void DisableLoggingInTests();
74 * Backend that writes to a file passed into the constructor
75 */
76class FileBackend : public Backend {
77public:
78 explicit FileBackend(const std::filesystem::path& filename);
79 ~FileBackend() override;
80
81 static const char* Name() {
82 return "file";
83 }
84
85 const char* GetName() const override {
86 return Name();
87 }
88
89 void Write(const Entry& entry) override;
90
91private:
92 std::unique_ptr<FS::IOFile> file;
93 std::size_t bytes_written = 0;
94};
95
96/**
97 * Backend that writes to Visual Studio's output window
98 */
99class DebuggerBackend : public Backend {
100public:
101 ~DebuggerBackend() override;
102
103 static const char* Name() {
104 return "debugger";
105 }
106 const char* GetName() const override {
107 return Name();
108 }
109 void Write(const Entry& entry) override;
110};
111
112void AddBackend(std::unique_ptr<Backend> backend);
113
114void RemoveBackend(std::string_view backend_name);
115
116Backend* GetBackend(std::string_view backend_name);
117 18
118/** 19/**
119 * The global filter will prevent any messages from even being processed if they are filtered. Each 20 * The global filter will prevent any messages from even being processed if they are filtered.
120 * backend can have a filter, but if the level is lower than the global filter, the backend will
121 * never get the message
122 */ 21 */
123void SetGlobalFilter(const Filter& filter); 22void SetGlobalFilter(const Filter& filter);
124} // namespace Common::Log \ No newline at end of file 23
24void SetColorConsoleBackendEnabled(bool enabled);
25} // namespace Common::Log
diff --git a/src/common/settings.h b/src/common/settings.h
index c65746749..20769d310 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -489,7 +489,7 @@ struct Values {
489 std::chrono::seconds custom_rtc_differential; 489 std::chrono::seconds custom_rtc_differential;
490 490
491 BasicSetting<s32> current_user{0, "current_user"}; 491 BasicSetting<s32> current_user{0, "current_user"};
492 RangedSetting<s32> language_index{1, 0, 16, "language_index"}; 492 RangedSetting<s32> language_index{1, 0, 17, "language_index"};
493 RangedSetting<s32> region_index{1, 0, 6, "region_index"}; 493 RangedSetting<s32> region_index{1, 0, 6, "region_index"};
494 RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"}; 494 RangedSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"};
495 RangedSetting<s32> sound_index{1, 0, 2, "sound_index"}; 495 RangedSetting<s32> sound_index{1, 0, 2, "sound_index"};
diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h
index c2c9b6134..0ddf9b83e 100644
--- a/src/common/x64/xbyak_abi.h
+++ b/src/common/x64/xbyak_abi.h
@@ -6,7 +6,7 @@
6 6
7#include <bitset> 7#include <bitset>
8#include <initializer_list> 8#include <initializer_list>
9#include <xbyak.h> 9#include <xbyak/xbyak.h>
10#include "common/assert.h" 10#include "common/assert.h"
11 11
12namespace Common::X64 { 12namespace Common::X64 {
diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h
index df17f8cbe..44d2558f1 100644
--- a/src/common/x64/xbyak_util.h
+++ b/src/common/x64/xbyak_util.h
@@ -5,7 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <type_traits> 7#include <type_traits>
8#include <xbyak.h> 8#include <xbyak/xbyak.h>
9#include "common/x64/xbyak_abi.h" 9#include "common/x64/xbyak_abi.h"
10 10
11namespace Common::X64 { 11namespace Common::X64 {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 5d8a61b3a..5893a86bf 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -4,6 +4,7 @@
4 4
5#include <array> 5#include <array>
6#include <atomic> 6#include <atomic>
7#include <exception>
7#include <memory> 8#include <memory>
8#include <utility> 9#include <utility>
9 10
@@ -84,8 +85,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
84 85
85} // Anonymous namespace 86} // Anonymous namespace
86 87
87/*static*/ System System::s_instance;
88
89FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, 88FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
90 const std::string& path) { 89 const std::string& path) {
91 // To account for split 00+01+etc files. 90 // To account for split 00+01+etc files.
@@ -425,6 +424,20 @@ struct System::Impl {
425System::System() : impl{std::make_unique<Impl>(*this)} {} 424System::System() : impl{std::make_unique<Impl>(*this)} {}
426System::~System() = default; 425System::~System() = default;
427 426
427System& System::GetInstance() {
428 if (!s_instance) {
429 throw std::runtime_error("Using System instance before its initialization");
430 }
431 return *s_instance;
432}
433
434void System::InitializeGlobalInstance() {
435 if (s_instance) {
436 throw std::runtime_error("Reinitializing Global System instance.");
437 }
438 s_instance = std::unique_ptr<System>(new System);
439}
440
428CpuManager& System::GetCpuManager() { 441CpuManager& System::GetCpuManager() {
429 return impl->cpu_manager; 442 return impl->cpu_manager;
430} 443}
diff --git a/src/core/core.h b/src/core/core.h
index cd9af0c07..f9116ebb6 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -120,9 +120,9 @@ public:
120 * Gets the instance of the System singleton class. 120 * Gets the instance of the System singleton class.
121 * @returns Reference to the instance of the System singleton class. 121 * @returns Reference to the instance of the System singleton class.
122 */ 122 */
123 [[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance() { 123 [[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance();
124 return s_instance; 124
125 } 125 static void InitializeGlobalInstance();
126 126
127 /// Enumeration representing the return values of the System Initialize and Load process. 127 /// Enumeration representing the return values of the System Initialize and Load process.
128 enum class ResultStatus : u32 { 128 enum class ResultStatus : u32 {
@@ -393,7 +393,7 @@ private:
393 struct Impl; 393 struct Impl;
394 std::unique_ptr<Impl> impl; 394 std::unique_ptr<Impl> impl;
395 395
396 static System s_instance; 396 inline static std::unique_ptr<System> s_instance{};
397}; 397};
398 398
399} // namespace Core 399} // namespace Core
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8673384ee..8fdab44e4 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -261,20 +261,23 @@ struct KernelCore::Impl {
261 current_process = process; 261 current_process = process;
262 } 262 }
263 263
264 /// Creates a new host thread ID, should only be called by GetHostThreadId 264 static inline thread_local u32 host_thread_id = UINT32_MAX;
265 u32 AllocateHostThreadId(std::optional<std::size_t> core_id) { 265
266 if (core_id) { 266 /// Gets the host thread ID for the caller, allocating a new one if this is the first time
267 // The first for slots are reserved for CPU core threads 267 u32 GetHostThreadId(std::size_t core_id) {
268 ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES); 268 if (host_thread_id == UINT32_MAX) {
269 return static_cast<u32>(*core_id); 269 // The first four slots are reserved for CPU core threads
270 } else { 270 ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
271 return next_host_thread_id++; 271 host_thread_id = static_cast<u32>(core_id);
272 } 272 }
273 return host_thread_id;
273 } 274 }
274 275
275 /// Gets the host thread ID for the caller, allocating a new one if this is the first time 276 /// Gets the host thread ID for the caller, allocating a new one if this is the first time
276 u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) { 277 u32 GetHostThreadId() {
277 const thread_local auto host_thread_id{AllocateHostThreadId(core_id)}; 278 if (host_thread_id == UINT32_MAX) {
279 host_thread_id = next_host_thread_id++;
280 }
278 return host_thread_id; 281 return host_thread_id;
279 } 282 }
280 283
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index ef6854d62..36a4aa9cd 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -16,6 +16,30 @@
16 16
17namespace Service::AM::Applets { 17namespace Service::AM::Applets {
18 18
19struct ErrorCode {
20 u32 error_category{};
21 u32 error_number{};
22
23 static constexpr ErrorCode FromU64(u64 error_code) {
24 return {
25 .error_category{static_cast<u32>(error_code >> 32)},
26 .error_number{static_cast<u32>(error_code & 0xFFFFFFFF)},
27 };
28 }
29
30 static constexpr ErrorCode FromResultCode(ResultCode result) {
31 return {
32 .error_category{2000 + static_cast<u32>(result.module.Value())},
33 .error_number{result.description.Value()},
34 };
35 }
36
37 constexpr ResultCode ToResultCode() const {
38 return ResultCode{static_cast<ErrorModule>(error_category - 2000), error_number};
39 }
40};
41static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
42
19#pragma pack(push, 4) 43#pragma pack(push, 4)
20struct ShowError { 44struct ShowError {
21 u8 mode; 45 u8 mode;
@@ -76,12 +100,7 @@ void CopyArgumentData(const std::vector<u8>& data, T& variable) {
76} 100}
77 101
78ResultCode Decode64BitError(u64 error) { 102ResultCode Decode64BitError(u64 error) {
79 const auto description = (error >> 32) & 0x1FFF; 103 return ErrorCode::FromU64(error).ToResultCode();
80 auto module = error & 0x3FF;
81 if (module >= 2000)
82 module -= 2000;
83 module &= 0x1FF;
84 return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
85} 104}
86 105
87} // Anonymous namespace 106} // Anonymous namespace
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index fb8c02a77..14c77f162 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -298,14 +298,10 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
298 if (IR::IsGeneric(attr)) { 298 if (IR::IsGeneric(attr)) {
299 const u32 index{IR::GenericAttributeIndex(attr)}; 299 const u32 index{IR::GenericAttributeIndex(attr)};
300 const std::optional<AttrInfo> type{AttrTypes(ctx, index)}; 300 const std::optional<AttrInfo> type{AttrTypes(ctx, index)};
301 if (!type) { 301 if (!type || !ctx.runtime_info.previous_stage_stores.Generic(index, element)) {
302 // Attribute is disabled 302 // Attribute is disabled or varying component is not written
303 return ctx.Const(element == 3 ? 1.0f : 0.0f); 303 return ctx.Const(element == 3 ? 1.0f : 0.0f);
304 } 304 }
305 if (!ctx.runtime_info.previous_stage_stores.Generic(index, element)) {
306 // Varying component is not written
307 return ctx.Const(type && element == 3 ? 1.0f : 0.0f);
308 }
309 const Id generic_id{ctx.input_generics.at(index)}; 305 const Id generic_id{ctx.input_generics.at(index)};
310 const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))}; 306 const Id pointer{AttrPointer(ctx, type->pointer, vertex, generic_id, ctx.Const(element))};
311 const Id value{ctx.OpLoad(type->id, pointer)}; 307 const Id value{ctx.OpLoad(type->id, pointer)};
diff --git a/src/tests/common/param_package.cpp b/src/tests/common/param_package.cpp
index 4c0f9654f..e31ca3544 100644
--- a/src/tests/common/param_package.cpp
+++ b/src/tests/common/param_package.cpp
@@ -4,11 +4,13 @@
4 4
5#include <catch2/catch.hpp> 5#include <catch2/catch.hpp>
6#include <math.h> 6#include <math.h>
7#include "common/logging/backend.h"
7#include "common/param_package.h" 8#include "common/param_package.h"
8 9
9namespace Common { 10namespace Common {
10 11
11TEST_CASE("ParamPackage", "[common]") { 12TEST_CASE("ParamPackage", "[common]") {
13 Common::Log::DisableLoggingInTests();
12 ParamPackage original{ 14 ParamPackage original{
13 {"abc", "xyz"}, 15 {"abc", "xyz"},
14 {"def", "42"}, 16 {"def", "42"},
diff --git a/src/video_core/macro/macro_jit_x64.h b/src/video_core/macro/macro_jit_x64.h
index 7f50ac2f8..d03d480b4 100644
--- a/src/video_core/macro/macro_jit_x64.h
+++ b/src/video_core/macro/macro_jit_x64.h
@@ -6,7 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
9#include <xbyak.h> 9#include <xbyak/xbyak.h>
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/x64/xbyak_abi.h" 12#include "common/x64/xbyak_abi.h"
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 1a9399455..7994cb859 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -159,7 +159,7 @@ static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size");
159 return {raw, raw}; 159 return {raw, raw};
160 } else { 160 } else {
161 const Tegra::Texture::TextureHandle handle{raw}; 161 const Tegra::Texture::TextureHandle handle{raw};
162 return {handle.tic_id, via_header_index ? handle.tic_id : handle.tsc_id}; 162 return {handle.tic_id, handle.tsc_id};
163 } 163 }
164} 164}
165 165
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index cf68a95b5..19ba0dbba 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -182,7 +182,14 @@ if (ENABLE_QT_TRANSLATION)
182 # Update source TS file if enabled 182 # Update source TS file if enabled
183 if (GENERATE_QT_TRANSLATION) 183 if (GENERATE_QT_TRANSLATION)
184 get_target_property(SRCS yuzu SOURCES) 184 get_target_property(SRCS yuzu SOURCES)
185 qt5_create_translation(QM_FILES ${SRCS} ${UIS} ${YUZU_QT_LANGUAGES}/en.ts) 185 qt5_create_translation(QM_FILES
186 ${SRCS}
187 ${UIS}
188 ${YUZU_QT_LANGUAGES}/en.ts
189 OPTIONS
190 -source-language en_US
191 -target-language en_US
192 )
186 add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts) 193 add_custom_target(translation ALL DEPENDS ${YUZU_QT_LANGUAGES}/en.ts)
187 endif() 194 endif()
188 195
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index cd633e45f..9c890ed5d 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -647,18 +647,18 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
647 // Face buttons 647 // Face buttons
648 p.setPen(colors.outline); 648 p.setPen(colors.outline);
649 button_color = colors.button; 649 button_color = colors.button;
650 DrawCircleButton(p, face_center + QPoint(face_distance, 0), button_values[A], face_radius); 650 DrawCircleButton(p, face_center + QPointF(face_distance, 0), button_values[A], face_radius);
651 DrawCircleButton(p, face_center + QPoint(0, face_distance), button_values[B], face_radius); 651 DrawCircleButton(p, face_center + QPointF(0, face_distance), button_values[B], face_radius);
652 DrawCircleButton(p, face_center + QPoint(0, -face_distance), button_values[X], face_radius); 652 DrawCircleButton(p, face_center + QPointF(0, -face_distance), button_values[X], face_radius);
653 DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius); 653 DrawCircleButton(p, face_center + QPointF(-face_distance, 0), button_values[Y], face_radius);
654 654
655 // Face buttons text 655 // Face buttons text
656 p.setPen(colors.transparent); 656 p.setPen(colors.transparent);
657 p.setBrush(colors.font); 657 p.setBrush(colors.font);
658 DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size); 658 DrawSymbol(p, face_center + QPointF(face_distance, 0), Symbol::A, text_size);
659 DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size); 659 DrawSymbol(p, face_center + QPointF(0, face_distance), Symbol::B, text_size);
660 DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size); 660 DrawSymbol(p, face_center + QPointF(0, -face_distance), Symbol::X, text_size);
661 DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size); 661 DrawSymbol(p, face_center + QPointF(-face_distance, 1), Symbol::Y, text_size);
662 662
663 // D-pad constants 663 // D-pad constants
664 const QPointF dpad_center = center + QPoint(-171, 8); 664 const QPointF dpad_center = center + QPoint(-171, 8);
@@ -669,18 +669,20 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen
669 // D-pad buttons 669 // D-pad buttons
670 p.setPen(colors.outline); 670 p.setPen(colors.outline);
671 button_color = colors.button; 671 button_color = colors.button;
672 DrawCircleButton(p, dpad_center + QPoint(dpad_distance, 0), button_values[DRight], dpad_radius); 672 DrawCircleButton(p, dpad_center + QPointF(dpad_distance, 0), button_values[DRight],
673 DrawCircleButton(p, dpad_center + QPoint(0, dpad_distance), button_values[DDown], dpad_radius); 673 dpad_radius);
674 DrawCircleButton(p, dpad_center + QPoint(0, -dpad_distance), button_values[DUp], dpad_radius); 674 DrawCircleButton(p, dpad_center + QPointF(0, dpad_distance), button_values[DDown], dpad_radius);
675 DrawCircleButton(p, dpad_center + QPoint(-dpad_distance, 0), button_values[DLeft], dpad_radius); 675 DrawCircleButton(p, dpad_center + QPointF(0, -dpad_distance), button_values[DUp], dpad_radius);
676 DrawCircleButton(p, dpad_center + QPointF(-dpad_distance, 0), button_values[DLeft],
677 dpad_radius);
676 678
677 // D-pad arrows 679 // D-pad arrows
678 p.setPen(colors.font2); 680 p.setPen(colors.font2);
679 p.setBrush(colors.font2); 681 p.setBrush(colors.font2);
680 DrawArrow(p, dpad_center + QPoint(dpad_distance, 0), Direction::Right, dpad_arrow_size); 682 DrawArrow(p, dpad_center + QPointF(dpad_distance, 0), Direction::Right, dpad_arrow_size);
681 DrawArrow(p, dpad_center + QPoint(0, dpad_distance), Direction::Down, dpad_arrow_size); 683 DrawArrow(p, dpad_center + QPointF(0, dpad_distance), Direction::Down, dpad_arrow_size);
682 DrawArrow(p, dpad_center + QPoint(0, -dpad_distance), Direction::Up, dpad_arrow_size); 684 DrawArrow(p, dpad_center + QPointF(0, -dpad_distance), Direction::Up, dpad_arrow_size);
683 DrawArrow(p, dpad_center + QPoint(-dpad_distance, 0), Direction::Left, dpad_arrow_size); 685 DrawArrow(p, dpad_center + QPointF(-dpad_distance, 0), Direction::Left, dpad_arrow_size);
684 686
685 // ZL and ZR buttons 687 // ZL and ZR buttons
686 p.setPen(colors.outline); 688 p.setPen(colors.outline);
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp
index 22ca1285d..f89ea8ea7 100644
--- a/src/yuzu/debugger/console.cpp
+++ b/src/yuzu/debugger/console.cpp
@@ -21,6 +21,7 @@ void ToggleConsole() {
21 console_shown = UISettings::values.show_console.GetValue(); 21 console_shown = UISettings::values.show_console.GetValue();
22 } 22 }
23 23
24 using namespace Common::Log;
24#if defined(_WIN32) && !defined(_DEBUG) 25#if defined(_WIN32) && !defined(_DEBUG)
25 FILE* temp; 26 FILE* temp;
26 if (UISettings::values.show_console) { 27 if (UISettings::values.show_console) {
@@ -29,24 +30,20 @@ void ToggleConsole() {
29 freopen_s(&temp, "CONIN$", "r", stdin); 30 freopen_s(&temp, "CONIN$", "r", stdin);
30 freopen_s(&temp, "CONOUT$", "w", stdout); 31 freopen_s(&temp, "CONOUT$", "w", stdout);
31 freopen_s(&temp, "CONOUT$", "w", stderr); 32 freopen_s(&temp, "CONOUT$", "w", stderr);
32 Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>()); 33 SetColorConsoleBackendEnabled(true);
33 } 34 }
34 } else { 35 } else {
35 if (FreeConsole()) { 36 if (FreeConsole()) {
36 // In order to close the console, we have to also detach the streams on it. 37 // In order to close the console, we have to also detach the streams on it.
37 // Just redirect them to NUL if there is no console window 38 // Just redirect them to NUL if there is no console window
38 Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name()); 39 SetColorConsoleBackendEnabled(false);
39 freopen_s(&temp, "NUL", "r", stdin); 40 freopen_s(&temp, "NUL", "r", stdin);
40 freopen_s(&temp, "NUL", "w", stdout); 41 freopen_s(&temp, "NUL", "w", stdout);
41 freopen_s(&temp, "NUL", "w", stderr); 42 freopen_s(&temp, "NUL", "w", stderr);
42 } 43 }
43 } 44 }
44#else 45#else
45 if (UISettings::values.show_console) { 46 SetColorConsoleBackendEnabled(UISettings::values.show_console.GetValue());
46 Common::Log::AddBackend(std::make_unique<Common::Log::ColorConsoleBackend>());
47 } else {
48 Common::Log::RemoveBackend(Common::Log::ColorConsoleBackend::Name());
49 }
50#endif 47#endif
51} 48}
52} // namespace Debugger 49} // namespace Debugger
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 5940e0cfd..e36774cc6 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -175,21 +175,6 @@ void GMainWindow::ShowTelemetryCallout() {
175 175
176const int GMainWindow::max_recent_files_item; 176const int GMainWindow::max_recent_files_item;
177 177
178static void InitializeLogging() {
179 using namespace Common;
180
181 Log::Filter log_filter;
182 log_filter.ParseFilterString(Settings::values.log_filter.GetValue());
183 Log::SetGlobalFilter(log_filter);
184
185 const auto log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir);
186 void(FS::CreateDir(log_dir));
187 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir / LOG_FILE));
188#ifdef _WIN32
189 Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
190#endif
191}
192
193static void RemoveCachedContents() { 178static void RemoveCachedContents() {
194 const auto cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir); 179 const auto cache_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir);
195 const auto offline_fonts = cache_dir / "fonts"; 180 const auto offline_fonts = cache_dir / "fonts";
@@ -207,8 +192,7 @@ GMainWindow::GMainWindow()
207 : input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, 192 : input_subsystem{std::make_shared<InputCommon::InputSubsystem>()},
208 config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, 193 config{std::make_unique<Config>()}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()},
209 provider{std::make_unique<FileSys::ManualContentProvider>()} { 194 provider{std::make_unique<FileSys::ManualContentProvider>()} {
210 InitializeLogging(); 195 Common::Log::Initialize();
211
212 LoadTranslation(); 196 LoadTranslation();
213 197
214 setAcceptDrops(true); 198 setAcceptDrops(true);
@@ -3437,6 +3421,7 @@ int main(int argc, char* argv[]) {
3437 // generating shaders 3421 // generating shaders
3438 setlocale(LC_ALL, "C"); 3422 setlocale(LC_ALL, "C");
3439 3423
3424 Core::System::InitializeGlobalInstance();
3440 GMainWindow main_window; 3425 GMainWindow main_window;
3441 // After settings have been loaded by GMainWindow, apply the filter 3426 // After settings have been loaded by GMainWindow, apply the filter
3442 main_window.show(); 3427 main_window.show();
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index c10093820..ba2c993ba 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -74,31 +74,14 @@ static void PrintVersion() {
74 std::cout << "yuzu " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl; 74 std::cout << "yuzu " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
75} 75}
76 76
77static void InitializeLogging() {
78 using namespace Common;
79
80 Log::Filter log_filter(Log::Level::Debug);
81 log_filter.ParseFilterString(static_cast<std::string>(Settings::values.log_filter));
82 Log::SetGlobalFilter(log_filter);
83
84 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
85
86 const auto& log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir);
87 void(FS::CreateDir(log_dir));
88 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir / LOG_FILE));
89#ifdef _WIN32
90 Log::AddBackend(std::make_unique<Log::DebuggerBackend>());
91#endif
92}
93
94/// Application entry point 77/// Application entry point
95int main(int argc, char** argv) { 78int main(int argc, char** argv) {
79 Common::Log::Initialize();
80 Common::Log::SetColorConsoleBackendEnabled(true);
96 Common::DetachedTasks detached_tasks; 81 Common::DetachedTasks detached_tasks;
97 Config config; 82 Config config;
98 83
99 int option_index = 0; 84 int option_index = 0;
100
101 InitializeLogging();
102#ifdef _WIN32 85#ifdef _WIN32
103 int argc_w; 86 int argc_w;
104 auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w); 87 auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
@@ -163,6 +146,7 @@ int main(int argc, char** argv) {
163 return -1; 146 return -1;
164 } 147 }
165 148
149 Core::System::InitializeGlobalInstance();
166 auto& system{Core::System::GetInstance()}; 150 auto& system{Core::System::GetInstance()};
167 InputCommon::InputSubsystem input_subsystem; 151 InputCommon::InputSubsystem input_subsystem;
168 152