diff options
| -rw-r--r-- | externals/CMakeLists.txt | 5 | ||||
| m--------- | externals/dynarmic | 0 | ||||
| -rw-r--r-- | src/common/logging/backend.cpp | 351 | ||||
| -rw-r--r-- | src/common/logging/backend.h | 113 | ||||
| -rw-r--r-- | src/common/settings.h | 2 | ||||
| -rw-r--r-- | src/common/x64/xbyak_abi.h | 2 | ||||
| -rw-r--r-- | src/common/x64/xbyak_util.h | 2 | ||||
| -rw-r--r-- | src/core/core.cpp | 17 | ||||
| -rw-r--r-- | src/core/core.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/applet_error.cpp | 31 | ||||
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | 8 | ||||
| -rw-r--r-- | src/tests/common/param_package.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/macro/macro_jit_x64.h | 2 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 2 | ||||
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player_widget.cpp | 34 | ||||
| -rw-r--r-- | src/yuzu/debugger/console.cpp | 11 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 19 | ||||
| -rw-r--r-- | src/yuzu_cmd/yuzu.cpp | 22 |
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 |
| 8 | if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) | 8 | if (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) |
| 12 | endif() | 14 | endif() |
| 13 | 15 | ||
| @@ -19,6 +21,7 @@ target_include_directories(catch-single-include INTERFACE catch/single_include) | |||
| 19 | if (ARCHITECTURE_x86_64) | 21 | if (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) |
| 23 | endif() | 26 | endif() |
| 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 | ||
| 31 | namespace Common::Log { | 31 | namespace Common::Log { |
| 32 | 32 | ||
| 33 | namespace { | ||
| 34 | |||
| 33 | /** | 35 | /** |
| 34 | * Static state as a singleton. | 36 | * Interface for logging backends. |
| 35 | */ | 37 | */ |
| 36 | class Impl { | 38 | class Backend { |
| 37 | public: | 39 | public: |
| 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 | */ | ||
| 52 | class ColorConsoleBackend final : public Backend { | ||
| 53 | public: | ||
| 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 | |
| 76 | private: | ||
| 77 | std::atomic_bool enabled{false}; | ||
| 78 | }; | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Backend that writes to a file passed into the constructor | ||
| 82 | */ | ||
| 83 | class FileBackend final : public Backend { | ||
| 84 | public: | ||
| 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) { | 130 | private: |
| 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 | */ | ||
| 139 | class DebuggerBackend final : public Backend { | ||
| 140 | public: | ||
| 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 | |||
| 156 | bool 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 | */ |
| 161 | class Impl { | ||
| 162 | public: | ||
| 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 | ||
| 85 | private: | 208 | private: |
| 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 | |||
| 146 | ConsoleBackend::~ConsoleBackend() = default; | ||
| 147 | |||
| 148 | void ConsoleBackend::Write(const Entry& entry) { | ||
| 149 | PrintMessage(entry); | ||
| 150 | } | ||
| 151 | |||
| 152 | ColorConsoleBackend::~ColorConsoleBackend() = default; | ||
| 153 | |||
| 154 | void ColorConsoleBackend::Write(const Entry& entry) { | ||
| 155 | PrintColoredMessage(entry); | ||
| 156 | } | ||
| 157 | |||
| 158 | FileBackend::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 | |||
| 171 | FileBackend::~FileBackend() = default; | ||
| 172 | 265 | ||
| 173 | void 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')); | 283 | void Initialize() { |
| 194 | if (entry.log_level >= Level::Error) { | 284 | Impl::Initialize(); |
| 195 | file->Flush(); | ||
| 196 | } | ||
| 197 | } | 285 | } |
| 198 | 286 | ||
| 199 | DebuggerBackend::~DebuggerBackend() = default; | 287 | void DisableLoggingInTests() { |
| 200 | 288 | initialization_in_progress_suppress_logging = true; | |
| 201 | void DebuggerBackend::Write(const Entry& entry) { | ||
| 202 | #ifdef _WIN32 | ||
| 203 | ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); | ||
| 204 | #endif | ||
| 205 | } | 289 | } |
| 206 | 290 | ||
| 207 | void SetGlobalFilter(const Filter& filter) { | 291 | void SetGlobalFilter(const Filter& filter) { |
| 208 | Impl::Instance().SetGlobalFilter(filter); | 292 | Impl::Instance().SetGlobalFilter(filter); |
| 209 | } | 293 | } |
| 210 | 294 | ||
| 211 | void AddBackend(std::unique_ptr<Backend> backend) { | 295 | void SetColorConsoleBackendEnabled(bool enabled) { |
| 212 | Impl::Instance().AddBackend(std::move(backend)); | 296 | Impl::Instance().SetColorConsoleBackendEnabled(enabled); |
| 213 | } | ||
| 214 | |||
| 215 | void RemoveBackend(std::string_view backend_name) { | ||
| 216 | Impl::Instance().RemoveBackend(backend_name); | ||
| 217 | } | ||
| 218 | |||
| 219 | Backend* GetBackend(std::string_view backend_name) { | ||
| 220 | return Impl::Instance().GetBackend(backend_name); | ||
| 221 | } | 297 | } |
| 222 | 298 | ||
| 223 | void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | 299 | void 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 | |||
| 14 | namespace Common::FS { | ||
| 15 | class IOFile; | ||
| 16 | } | ||
| 17 | 9 | ||
| 18 | namespace Common::Log { | 10 | namespace Common::Log { |
| 19 | 11 | ||
| 20 | class Filter; | 12 | class 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 | 15 | void Initialize(); |
| 24 | * used by a frontend for adding a custom logging backend as needed | ||
| 25 | */ | ||
| 26 | class Backend { | ||
| 27 | public: | ||
| 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 | |||
| 36 | private: | ||
| 37 | Filter filter; | ||
| 38 | }; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Backend that writes to stderr without any color commands | ||
| 42 | */ | ||
| 43 | class ConsoleBackend : public Backend { | ||
| 44 | public: | ||
| 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 | */ | ||
| 59 | class ColorConsoleBackend : public Backend { | ||
| 60 | public: | ||
| 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 | /** | 17 | void DisableLoggingInTests(); |
| 74 | * Backend that writes to a file passed into the constructor | ||
| 75 | */ | ||
| 76 | class FileBackend : public Backend { | ||
| 77 | public: | ||
| 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 | |||
| 91 | private: | ||
| 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 | */ | ||
| 99 | class DebuggerBackend : public Backend { | ||
| 100 | public: | ||
| 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 | |||
| 112 | void AddBackend(std::unique_ptr<Backend> backend); | ||
| 113 | |||
| 114 | void RemoveBackend(std::string_view backend_name); | ||
| 115 | |||
| 116 | Backend* 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 | */ |
| 123 | void SetGlobalFilter(const Filter& filter); | 22 | void SetGlobalFilter(const Filter& filter); |
| 124 | } // namespace Common::Log \ No newline at end of file | 23 | |
| 24 | void 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 | ||
| 12 | namespace Common::X64 { | 12 | namespace 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 | ||
| 11 | namespace Common::X64 { | 11 | namespace 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 | |||
| 89 | FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | 88 | FileSys::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 { | |||
| 425 | System::System() : impl{std::make_unique<Impl>(*this)} {} | 424 | System::System() : impl{std::make_unique<Impl>(*this)} {} |
| 426 | System::~System() = default; | 425 | System::~System() = default; |
| 427 | 426 | ||
| 427 | System& System::GetInstance() { | ||
| 428 | if (!s_instance) { | ||
| 429 | throw std::runtime_error("Using System instance before its initialization"); | ||
| 430 | } | ||
| 431 | return *s_instance; | ||
| 432 | } | ||
| 433 | |||
| 434 | void 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 | |||
| 428 | CpuManager& System::GetCpuManager() { | 441 | CpuManager& 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 | ||
| 17 | namespace Service::AM::Applets { | 17 | namespace Service::AM::Applets { |
| 18 | 18 | ||
| 19 | struct 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 | }; | ||
| 41 | static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size."); | ||
| 42 | |||
| 19 | #pragma pack(push, 4) | 43 | #pragma pack(push, 4) |
| 20 | struct ShowError { | 44 | struct ShowError { |
| 21 | u8 mode; | 45 | u8 mode; |
| @@ -76,12 +100,7 @@ void CopyArgumentData(const std::vector<u8>& data, T& variable) { | |||
| 76 | } | 100 | } |
| 77 | 101 | ||
| 78 | ResultCode Decode64BitError(u64 error) { | 102 | ResultCode 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 | ||
| 9 | namespace Common { | 10 | namespace Common { |
| 10 | 11 | ||
| 11 | TEST_CASE("ParamPackage", "[common]") { | 12 | TEST_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 | ||
| 176 | const int GMainWindow::max_recent_files_item; | 176 | const int GMainWindow::max_recent_files_item; |
| 177 | 177 | ||
| 178 | static 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 | |||
| 193 | static void RemoveCachedContents() { | 178 | static 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 | ||
| 77 | static 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 |
| 95 | int main(int argc, char** argv) { | 78 | int 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 | ||