From 79d6c8a377f0c721e689d86e4f23e2208317493f Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:10:34 +0200 Subject: [PATCH] common: Rewrite logging based on cut down citra logger (#86) * common: Rewrite logging based on cut down Citra logger * code: Misc fixes * core: Bring back tls handler * linker: Cleanup * config: Remove log level * logging: Enable console output by default * core: Fix windows build --- .github/workflows/windows.yml | 2 +- .gitmodules | 4 - CMakeLists.txt | 34 +- src/Util/config.cpp | 14 +- src/Util/config.h | 2 +- src/common/assert.cpp | 18 + src/common/assert.h | 84 +++ src/common/bounded_threadsafe_queue.h | 248 +++++++++ src/common/concepts.h | 31 ++ src/common/error.cpp | 57 ++ src/common/error.h | 21 + src/common/fs_file.cpp | 96 ---- src/common/fs_file.h | 86 --- src/common/io_file.cpp | 426 +++++++++++---- src/common/io_file.h | 236 ++++++-- src/common/log.cpp | 159 ------ src/common/log.h | 42 -- src/common/logging/backend.cpp | 277 ++++++++++ src/common/logging/backend.h | 27 + src/common/logging/filter.cpp | 173 ++++++ src/common/logging/filter.h | 66 +++ src/common/logging/formatter.h | 21 + src/common/logging/log.h | 70 +++ src/common/logging/log_entry.h | 26 + src/common/logging/text_formatter.cpp | 109 ++++ src/common/logging/text_formatter.h | 21 + src/common/logging/types.h | 63 +++ src/common/path_util.cpp | 87 +++ src/common/path_util.h | 79 +++ src/common/string_util.cpp | 47 ++ src/common/string_util.h | 5 + src/common/thread.cpp | 123 +++++ src/common/thread.h | 23 + src/core/PS4/GPU/video_out_buffer.cpp | 25 +- src/core/PS4/HLE/Graphics/video_out.cpp | 100 ++-- src/core/aerolib/stubs.cpp | 11 +- src/core/file_sys/fs.cpp | 31 +- src/core/file_sys/fs.h | 30 +- src/core/hle/kernel/cpu_management.cpp | 5 +- src/core/hle/kernel/event_queues.cpp | 37 +- src/core/hle/kernel/memory_management.cpp | 74 +-- src/core/hle/libraries/libc/libc.cpp | 15 +- src/core/hle/libraries/libc/libc_cxa.cpp | 21 +- src/core/hle/libraries/libc/libc_stdio.cpp | 14 +- src/core/hle/libraries/libc/libc_stdio.h | 1 + src/core/hle/libraries/libc/libc_stdlib.cpp | 10 +- src/core/hle/libraries/libc/printf.h | 1 + .../hle/libraries/libkernel/file_system.cpp | 34 +- .../hle/libraries/libkernel/file_system.h | 2 +- .../hle/libraries/libkernel/libkernel.cpp | 27 +- .../libraries/libkernel/thread_management.cpp | 74 +-- src/core/hle/libraries/libpad/pad.cpp | 9 +- src/core/hle/libraries/libs.h | 9 - .../libscegnmdriver/libscegnmdriver.cpp | 6 +- .../libsystemservice/system_service.cpp | 4 +- .../libuserservice/libuserservice.cpp | 6 +- src/core/libraries/libscegnmdriver.cpp | 506 +++++++++--------- src/core/linker.cpp | 390 ++++++-------- src/core/linker.h | 11 +- src/core/loader/elf.cpp | 199 ++++--- src/core/loader/elf.h | 17 +- src/core/loader/symbols_resolver.cpp | 4 +- src/core/tls.cpp | 177 ++++++ src/core/tls.h | 16 + src/core/virtual_memory.cpp | 27 +- src/emulator.cpp | 1 - src/main.cpp | 13 +- src/vulkan_util.cpp | 60 +-- third-party/CMakeLists.txt | 8 - third-party/spdlog | 1 - 70 files changed, 3212 insertions(+), 1541 deletions(-) create mode 100644 src/common/assert.cpp create mode 100644 src/common/assert.h create mode 100644 src/common/bounded_threadsafe_queue.h create mode 100644 src/common/concepts.h create mode 100644 src/common/error.cpp create mode 100644 src/common/error.h delete mode 100644 src/common/fs_file.cpp delete mode 100644 src/common/fs_file.h delete mode 100644 src/common/log.cpp delete mode 100644 src/common/log.h create mode 100644 src/common/logging/backend.cpp create mode 100644 src/common/logging/backend.h create mode 100644 src/common/logging/filter.cpp create mode 100644 src/common/logging/filter.h create mode 100644 src/common/logging/formatter.h create mode 100644 src/common/logging/log.h create mode 100644 src/common/logging/log_entry.h create mode 100644 src/common/logging/text_formatter.cpp create mode 100644 src/common/logging/text_formatter.h create mode 100644 src/common/logging/types.h create mode 100644 src/common/path_util.cpp create mode 100644 src/common/path_util.h create mode 100644 src/common/thread.cpp create mode 100644 src/common/thread.h create mode 100644 src/core/tls.cpp create mode 100644 src/core/tls.h delete mode 160000 third-party/spdlog diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 48e2d246..88fb8970 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -29,7 +29,7 @@ jobs: run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -T ClangCL - name: Build # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel - name: Upload a Build Artifact uses: actions/upload-artifact@v3.1.2 with: diff --git a/.gitmodules b/.gitmodules index 9267baa7..16f4946a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,10 +6,6 @@ path = third-party/fmt url = https://github.com/fmtlib/fmt.git shallow = true -[submodule "third-party/spdlog"] - path = third-party/spdlog - url = https://github.com/gabime/spdlog - shallow = true [submodule "third-party/magic_enum"] path = third-party/magic_enum url = https://github.com/Neargye/magic_enum.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb5613b..9810ff92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,15 +128,31 @@ set(HOST_SOURCES src/Emulator/Host/controller.cpp ) add_executable(shadps4 + src/common/assert.cpp + src/common/assert.h + src/common/bounded_threadsafe_queue.h + src/common/concepts.h src/common/debug.h src/common/disassembler.cpp src/common/disassembler.h src/common/discord.cpp src/common/discord.h - src/common/fs_file.cpp - src/common/fs_file.h - src/common/log.cpp - src/common/log.h + src/common/error.cpp + src/common/error.h + src/common/io_file.cpp + src/common/io_file.h + src/common/path_util.cpp + src/common/path_util.h + src/common/logging/backend.cpp + src/common/logging/backend.h + src/common/logging/filter.cpp + src/common/logging/filter.h + src/common/logging/formatter.h + src/common/logging/log_entry.h + src/common/logging/log.h + src/common/logging/text_formatter.cpp + src/common/logging/text_formatter.h + src/common/logging/types.h src/common/native_clock.cpp src/common/native_clock.h src/common/rdtsc.cpp @@ -144,6 +160,8 @@ add_executable(shadps4 src/common/singleton.h src/common/string_util.cpp src/common/string_util.h + src/common/thread.cpp + src/common/thread.h src/common/types.h src/common/uint128.h src/common/version.h @@ -207,14 +225,18 @@ add_executable(shadps4 src/core/PS4/GPU/tile_manager.h src/core/hle/libraries/libkernel/time_management.cpp src/core/hle/libraries/libkernel/time_management.h - "src/common/io_file.cpp" "src/common/io_file.h") + src/core/tls.cpp + src/core/tls.h +) create_target_directory_groups(shadps4) -target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt spdlog::spdlog toml11::toml11) +target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11) target_link_libraries(shadps4 PRIVATE discord-rpc SDL3-shared vulkan-1 xxhash Zydis) if (WIN32) target_link_libraries(shadps4 PRIVATE mincore winpthread clang_rt.builtins-x86_64.lib) + add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS) + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN) endif() add_custom_command(TARGET shadps4 POST_BUILD diff --git a/src/Util/config.cpp b/src/Util/config.cpp index 5c0d2803..3d202742 100644 --- a/src/Util/config.cpp +++ b/src/Util/config.cpp @@ -12,19 +12,22 @@ namespace Config { bool isNeo = false; u32 screenWidth = 1280; u32 screenHeight = 720; -u32 logLevel = 0; // TRACE = 0 , DEBUG = 1 , INFO = 2 , WARN = 3 , ERROR = 4 , CRITICAL = 5, OFF = 6 +std::string logFilter; bool isNeoMode() { return isNeo; } + u32 getScreenWidth() { return screenWidth; } + u32 getScreenHeight() { return screenHeight; } -u32 getLogLevel() { - return logLevel; + +std::string getLogFilter() { + return logFilter; } void load(const std::filesystem::path& path) { @@ -50,7 +53,7 @@ void load(const std::filesystem::path& path) { auto general = generalResult.unwrap(); isNeo = toml::find_or(general, "isPS4Pro", false); - logLevel = toml::find_or(general, "logLevel", false); + logFilter = toml::find_or(general, "logFilter", ""); } } if (data.contains("GPU")) { @@ -62,7 +65,6 @@ void load(const std::filesystem::path& path) { screenHeight = toml::find_or(general, "screenHeight", false); } } - int k = 0; } void save(const std::filesystem::path& path) { toml::basic_value data; @@ -84,7 +86,7 @@ void save(const std::filesystem::path& path) { } data["General"]["isPS4Pro"] = isNeo; - data["General"]["logLevel"] = logLevel; + data["General"]["logFilter"] = logFilter; data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenHeight"] = screenHeight; diff --git a/src/Util/config.h b/src/Util/config.h index 9cd2e0c0..c2869049 100644 --- a/src/Util/config.h +++ b/src/Util/config.h @@ -11,7 +11,7 @@ void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); bool isNeoMode(); -u32 getLogLevel(); +std::string getLogFilter(); u32 getScreenWidth(); u32 getScreenHeight(); diff --git a/src/common/assert.cpp b/src/common/assert.cpp new file mode 100644 index 00000000..43b094c8 --- /dev/null +++ b/src/common/assert.cpp @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/logging/backend.h" + +#define Crash() __asm__ __volatile__("int $3") + +void assert_fail_impl() { + Common::Log::Stop(); + Crash(); +} + +[[noreturn]] void unreachable_impl() { + Common::Log::Stop(); + Crash(); + throw std::runtime_error("Unreachable code"); +} diff --git a/src/common/assert.h b/src/common/assert.h new file mode 100644 index 00000000..dabeb111 --- /dev/null +++ b/src/common/assert.h @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/logging/log.h" + +// Sometimes we want to try to continue even after hitting an assert. +// However touching this file yields a global recompilation as this header is included almost +// everywhere. So let's just move the handling of the failed assert to a single cpp file. + +void assert_fail_impl(); +[[noreturn]] void unreachable_impl(); + +#ifdef _MSC_VER +#define SHAD_NO_INLINE __declspec(noinline) +#else +#define SHAD_NO_INLINE __attribute__((noinline)) +#endif + +#define ASSERT(_a_) \ + ([&]() SHAD_NO_INLINE { \ + if (!(_a_)) [[unlikely]] { \ + LOG_CRITICAL(Debug, "Assertion Failed!"); \ + assert_fail_impl(); \ + } \ + }()) + +#define ASSERT_MSG(_a_, ...) \ + ([&]() SHAD_NO_INLINE { \ + if (!(_a_)) [[unlikely]] { \ + LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \ + assert_fail_impl(); \ + } \ + }()) + +#define UNREACHABLE() \ + do { \ + LOG_CRITICAL(Debug, "Unreachable code!"); \ + unreachable_impl(); \ + } while (0) + +#define UNREACHABLE_MSG(...) \ + do { \ + LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \ + unreachable_impl(); \ + } while (0) + +#ifdef _DEBUG +#define DEBUG_ASSERT(_a_) ASSERT(_a_) +#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__) +#else // not debug +#define DEBUG_ASSERT(_a_) \ + do { \ + } while (0) +#define DEBUG_ASSERT_MSG(_a_, _desc_, ...) \ + do { \ + } while (0) +#endif + +#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!") +#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__) + +#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!") +#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__) + +// If the assert is ignored, execute _b_ +#define ASSERT_OR_EXECUTE(_a_, _b_) \ + do { \ + ASSERT(_a_); \ + if (!(_a_)) [[unlikely]] { \ + _b_ \ + } \ + } while (0) + +// If the assert is ignored, execute _b_ +#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \ + do { \ + ASSERT_MSG(_a_, __VA_ARGS__); \ + if (!(_a_)) [[unlikely]] { \ + _b_ \ + } \ + } while (0) diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h new file mode 100644 index 00000000..46e382f0 --- /dev/null +++ b/src/common/bounded_threadsafe_queue.h @@ -0,0 +1,248 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Common { + +namespace detail { +constexpr std::size_t DefaultCapacity = 0x1000; +} // namespace detail + +template +class SPSCQueue { + static_assert((Capacity & (Capacity - 1)) == 0, "Capacity must be a power of two."); + +public: + template + bool TryEmplace(Args&&... args) { + return Emplace(std::forward(args)...); + } + + template + void EmplaceWait(Args&&... args) { + Emplace(std::forward(args)...); + } + + bool TryPop(T& t) { + return Pop(t); + } + + void PopWait(T& t) { + Pop(t); + } + + void PopWait(T& t, std::stop_token stop_token) { + Pop(t, stop_token); + } + + T PopWait() { + T t; + Pop(t); + return t; + } + + T PopWait(std::stop_token stop_token) { + T t; + Pop(t, stop_token); + return t; + } + +private: + enum class PushMode { + Try, + Wait, + Count, + }; + + enum class PopMode { + Try, + Wait, + WaitWithStopToken, + Count, + }; + + template + bool Emplace(Args&&... args) { + const std::size_t write_index = m_write_index.load(std::memory_order::relaxed); + + if constexpr (Mode == PushMode::Try) { + // Check if we have free slots to write to. + if ((write_index - m_read_index.load(std::memory_order::acquire)) == Capacity) { + return false; + } + } else if constexpr (Mode == PushMode::Wait) { + // Wait until we have free slots to write to. + std::unique_lock lock{producer_cv_mutex}; + producer_cv.wait(lock, [this, write_index] { + return (write_index - m_read_index.load(std::memory_order::acquire)) < Capacity; + }); + } else { + static_assert(Mode < PushMode::Count, "Invalid PushMode."); + } + + // Determine the position to write to. + const std::size_t pos = write_index % Capacity; + + // Emplace into the queue. + new (std::addressof(m_data[pos])) T(std::forward(args)...); + + // Increment the write index. + ++m_write_index; + + // Notify the consumer that we have pushed into the queue. + std::scoped_lock lock{consumer_cv_mutex}; + consumer_cv.notify_one(); + + return true; + } + + template + bool Pop(T& t, [[maybe_unused]] std::stop_token stop_token = {}) { + const std::size_t read_index = m_read_index.load(std::memory_order::relaxed); + + if constexpr (Mode == PopMode::Try) { + // Check if the queue is empty. + if (read_index == m_write_index.load(std::memory_order::acquire)) { + return false; + } + } else if constexpr (Mode == PopMode::Wait) { + // Wait until the queue is not empty. + std::unique_lock lock{consumer_cv_mutex}; + consumer_cv.wait(lock, [this, read_index] { + return read_index != m_write_index.load(std::memory_order::acquire); + }); + } else if constexpr (Mode == PopMode::WaitWithStopToken) { + // Wait until the queue is not empty. + std::unique_lock lock{consumer_cv_mutex}; + consumer_cv.wait(lock, stop_token, [this, read_index] { + return read_index != m_write_index.load(std::memory_order::acquire); + }); + if (stop_token.stop_requested()) { + return false; + } + } else { + static_assert(Mode < PopMode::Count, "Invalid PopMode."); + } + + // Determine the position to read from. + const std::size_t pos = read_index % Capacity; + + // Pop the data off the queue, moving it. + t = std::move(m_data[pos]); + + // Increment the read index. + ++m_read_index; + + // Notify the producer that we have popped off the queue. + std::scoped_lock lock{producer_cv_mutex}; + producer_cv.notify_one(); + + return true; + } + + alignas(128) std::atomic_size_t m_read_index{0}; + alignas(128) std::atomic_size_t m_write_index{0}; + + std::array m_data; + + std::condition_variable_any producer_cv; + std::mutex producer_cv_mutex; + std::condition_variable_any consumer_cv; + std::mutex consumer_cv_mutex; +}; + +template +class MPSCQueue { +public: + template + bool TryEmplace(Args&&... args) { + std::scoped_lock lock{write_mutex}; + return spsc_queue.TryEmplace(std::forward(args)...); + } + + template + void EmplaceWait(Args&&... args) { + std::scoped_lock lock{write_mutex}; + spsc_queue.EmplaceWait(std::forward(args)...); + } + + bool TryPop(T& t) { + return spsc_queue.TryPop(t); + } + + void PopWait(T& t) { + spsc_queue.PopWait(t); + } + + void PopWait(T& t, std::stop_token stop_token) { + spsc_queue.PopWait(t, stop_token); + } + + T PopWait() { + return spsc_queue.PopWait(); + } + + T PopWait(std::stop_token stop_token) { + return spsc_queue.PopWait(stop_token); + } + +private: + SPSCQueue spsc_queue; + std::mutex write_mutex; +}; + +template +class MPMCQueue { +public: + template + bool TryEmplace(Args&&... args) { + std::scoped_lock lock{write_mutex}; + return spsc_queue.TryEmplace(std::forward(args)...); + } + + template + void EmplaceWait(Args&&... args) { + std::scoped_lock lock{write_mutex}; + spsc_queue.EmplaceWait(std::forward(args)...); + } + + bool TryPop(T& t) { + std::scoped_lock lock{read_mutex}; + return spsc_queue.TryPop(t); + } + + void PopWait(T& t) { + std::scoped_lock lock{read_mutex}; + spsc_queue.PopWait(t); + } + + void PopWait(T& t, std::stop_token stop_token) { + std::scoped_lock lock{read_mutex}; + spsc_queue.PopWait(t, stop_token); + } + + T PopWait() { + std::scoped_lock lock{read_mutex}; + return spsc_queue.PopWait(); + } + + T PopWait(std::stop_token stop_token) { + std::scoped_lock lock{read_mutex}; + return spsc_queue.PopWait(stop_token); + } + +private: + SPSCQueue spsc_queue; + std::mutex write_mutex; + std::mutex read_mutex; +}; + +} // namespace Common diff --git a/src/common/concepts.h b/src/common/concepts.h new file mode 100644 index 00000000..a61add7a --- /dev/null +++ b/src/common/concepts.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +namespace Common { + +// Check if type satisfies the ContiguousContainer named requirement. +template +concept IsContiguousContainer = std::contiguous_iterator; + +template +concept DerivedFrom = std::derived_from; + +// TODO: Replace with std::convertible_to when libc++ implements it. +template +concept ConvertibleTo = std::is_convertible_v; + +// No equivalents in the stdlib + +template +concept IsArithmetic = std::is_arithmetic_v; + +template +concept IsIntegral = std::is_integral_v; + +} // namespace Common diff --git a/src/common/error.cpp b/src/common/error.cpp new file mode 100644 index 00000000..a1125b6e --- /dev/null +++ b/src/common/error.cpp @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +#include "common/error.h" + +namespace Common { + +std::string NativeErrorToString(int e) { +#ifdef _WIN32 + LPSTR err_str; + + DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&err_str), 1, nullptr); + if (!res) { + return "(FormatMessageA failed to format error)"; + } + std::string ret(err_str); + LocalFree(err_str); + return ret; +#else + char err_str[255]; +#if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) || \ + defined(ANDROID) + // Thread safe (GNU-specific) + const char* str = strerror_r(e, err_str, sizeof(err_str)); + return std::string(str); +#else + // Thread safe (XSI-compliant) + int second_err = strerror_r(e, err_str, sizeof(err_str)); + if (second_err != 0) { + return "(strerror_r failed to format error)"; + } + return std::string(err_str); +#endif // GLIBC etc. +#endif // _WIN32 +} + +std::string GetLastErrorMsg() { +#ifdef _WIN32 + return NativeErrorToString(GetLastError()); +#else + return NativeErrorToString(errno); +#endif +} + +} // namespace Common diff --git a/src/common/error.h b/src/common/error.h new file mode 100644 index 00000000..62a3bd83 --- /dev/null +++ b/src/common/error.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +namespace Common { + +// Generic function to get last error message. +// Call directly after the command or use the error num. +// This function might change the error code. +// Defined in error.cpp. +[[nodiscard]] std::string GetLastErrorMsg(); + +// Like GetLastErrorMsg(), but passing an explicit error code. +// Defined in error.cpp. +[[nodiscard]] std::string NativeErrorToString(int e); + +} // namespace Common diff --git a/src/common/fs_file.cpp b/src/common/fs_file.cpp deleted file mode 100644 index 3875b9ac..00000000 --- a/src/common/fs_file.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/fs_file.h" - -namespace Common::FS { - -File::File() = default; - -File::File(const std::string& path, OpenMode mode) { - open(path, mode); -} - -File::~File() { - close(); -} - -bool File::open(const std::string& path, OpenMode mode) { - close(); -#ifdef _WIN64 - fopen_s(&m_file, path.c_str(), getOpenMode(mode)); -#else - m_file = std::fopen(path.c_str(), getOpenMode(mode)); -#endif - return isOpen(); -} - -bool File::close() { - if (!isOpen() || std::fclose(m_file) != 0) [[unlikely]] { - m_file = nullptr; - return false; - } - - m_file = nullptr; - return true; -} - -bool File::write(std::span data) { - return isOpen() && std::fwrite(data.data(), 1, data.size(), m_file) == data.size(); -} - -bool File::read(void* data, u64 size) const { - return isOpen() && std::fread(data, 1, size, m_file) == size; -} - -bool File::seek(s64 offset, SeekMode mode) { -#ifdef _WIN64 - if (!isOpen() || _fseeki64(m_file, offset, getSeekMode(mode)) != 0) { - return false; - } -#else - if (!isOpen() || fseeko64(m_file, offset, getSeekMode(mode)) != 0) { - return false; - } -#endif - return true; -} - -u64 File::tell() const { - if (isOpen()) [[likely]] { -#ifdef _WIN64 - return _ftelli64(m_file); -#else - return ftello64(m_file); -#endif - } - - return -1; -} - -u64 File::getFileSize() { -#ifdef _WIN64 - const u64 pos = _ftelli64(m_file); - if (_fseeki64(m_file, 0, SEEK_END) != 0) { - return 0; - } - - const u64 size = _ftelli64(m_file); - if (_fseeki64(m_file, pos, SEEK_SET) != 0) { - return 0; - } -#else - const u64 pos = ftello64(m_file); - if (fseeko64(m_file, 0, SEEK_END) != 0) { - return 0; - } - - const u64 size = ftello64(m_file); - if (fseeko64(m_file, pos, SEEK_SET) != 0) { - return 0; - } -#endif - return size; -} - -} // namespace Common::FS diff --git a/src/common/fs_file.h b/src/common/fs_file.h deleted file mode 100644 index d6a63db9..00000000 --- a/src/common/fs_file.h +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include - -#include "common/types.h" - -namespace Common::FS { - -enum class OpenMode : u32 { Read = 0x1, Write = 0x2, ReadWrite = Read | Write }; - -enum class SeekMode : u32 { - Set, - Cur, - End, -}; - -class File { -public: - File(); - explicit File(const std::string& path, OpenMode mode = OpenMode::Read); - ~File(); - - bool open(const std::string& path, OpenMode mode = OpenMode::Read); - bool close(); - bool read(void* data, u64 size) const; - bool write(std::span data); - bool seek(s64 offset, SeekMode mode); - u64 getFileSize(); - u64 tell() const; - - template - bool read(T& data) const { - return read(&data, sizeof(T)); - } - - template - bool read(std::vector& data) const { - return read(data.data(), data.size() * sizeof(T)); - } - - bool isOpen() const { - return m_file != nullptr; - } - - const char* getOpenMode(OpenMode mode) const { - switch (mode) { - case OpenMode::Read: - return "rb"; - case OpenMode::Write: - return "wb"; - case OpenMode::ReadWrite: - return "r+b"; - default: - return "r"; - } - } - - int getSeekMode(SeekMode mode) const { - switch (mode) { - case SeekMode::Set: - return SEEK_SET; - case SeekMode::Cur: - return SEEK_CUR; - case SeekMode::End: - return SEEK_END; - default: - return SEEK_SET; - } - } - - [[nodiscard]] std::FILE* fileDescr() const { - return m_file; - } - -private: - std::FILE* m_file{}; -}; - -} // namespace Common::FS diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp index 3df32178..fda3353e 100644 --- a/src/common/io_file.cpp +++ b/src/common/io_file.cpp @@ -1,141 +1,335 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/io_file.h" +#include -// #include "helpers.hpp" +#include "common/io_file.h" +#include "common/logging/log.h" +#include "common/path_util.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#endif #ifdef _MSC_VER -// 64 bit offsets for MSVC +#define fileno _fileno #define fseeko _fseeki64 #define ftello _ftelli64 -#define fileno _fileno - -#pragma warning(disable : 4996) #endif -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif +namespace Common::FS { + +namespace fs = std::filesystem; + +namespace { + +#ifdef _WIN32 + +[[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) { + switch (type) { + case FileType::BinaryFile: + switch (mode) { + case FileAccessMode::Read: + return L"rb"; + case FileAccessMode::Write: + return L"wb"; + case FileAccessMode::Append: + return L"ab"; + case FileAccessMode::ReadWrite: + return L"r+b"; + case FileAccessMode::ReadAppend: + return L"a+b"; + } + break; + case FileType::TextFile: + switch (mode) { + case FileAccessMode::Read: + return L"r"; + case FileAccessMode::Write: + return L"w"; + case FileAccessMode::Append: + return L"a"; + case FileAccessMode::ReadWrite: + return L"r+"; + case FileAccessMode::ReadAppend: + return L"a+"; + } + break; + } + + return L""; +} + +[[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) { + switch (flag) { + case FileShareFlag::ShareNone: + default: + return _SH_DENYRW; + case FileShareFlag::ShareReadOnly: + return _SH_DENYWR; + case FileShareFlag::ShareWriteOnly: + return _SH_DENYRD; + case FileShareFlag::ShareReadWrite: + return _SH_DENYNO; + } +} -#ifdef WIN32 -#include // For _chsize_s #else -#include // For ftruncate + +[[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) { + switch (type) { + case FileType::BinaryFile: + switch (mode) { + case FileAccessMode::Read: + return "rb"; + case FileAccessMode::Write: + return "wb"; + case FileAccessMode::Append: + return "ab"; + case FileAccessMode::ReadWrite: + return "r+b"; + case FileAccessMode::ReadAppend: + return "a+b"; + } + break; + case FileType::TextFile: + switch (mode) { + case FileAccessMode::Read: + return "r"; + case FileAccessMode::Write: + return "w"; + case FileAccessMode::Append: + return "a"; + case FileAccessMode::ReadWrite: + return "r+"; + case FileAccessMode::ReadAppend: + return "a+"; + } + break; + } + + return ""; +} + #endif -IOFile::IOFile(const std::filesystem::path& path, const char* permissions) : handle(nullptr) { - open(path, permissions); -} - -bool IOFile::open(const std::filesystem::path& path, const char* permissions) { - const auto str = - path.string(); // For some reason converting paths directly with c_str() doesn't work - return open(str.c_str(), permissions); -} - -bool IOFile::open(const char* filename, const char* permissions) { - // If this IOFile is already bound to an open file descriptor, release the file descriptor - // To avoid leaking it and/or erroneously locking the file - if (isOpen()) { - close(); - } - - handle = std::fopen(filename, permissions); - return isOpen(); -} - -void IOFile::close() { - if (isOpen()) { - fclose(handle); - handle = nullptr; +[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) { + switch (origin) { + case SeekOrigin::SetOrigin: + default: + return SEEK_SET; + case SeekOrigin::CurrentPosition: + return SEEK_CUR; + case SeekOrigin::End: + return SEEK_END; } } -std::pair IOFile::read(void* data, std::size_t length, std::size_t dataSize) { - if (!isOpen()) { - return {false, std::numeric_limits::max()}; - } +} // Anonymous namespace - if (length == 0) - return {true, 0}; - return {true, std::fread(data, dataSize, length, handle)}; +IOFile::IOFile() = default; + +IOFile::IOFile(const std::string& path, FileAccessMode mode, FileType type, FileShareFlag flag) { + Open(path, mode, type, flag); } -std::pair IOFile::write(const void* data, std::size_t length, - std::size_t dataSize) { - if (!isOpen()) { - return {false, std::numeric_limits::max()}; - } +IOFile::IOFile(std::string_view path, FileAccessMode mode, FileType type, FileShareFlag flag) { + Open(path, mode, type, flag); +} - if (length == 0) { - return {true, 0}; +IOFile::IOFile(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) { + Open(path, mode, type, flag); +} + +IOFile::~IOFile() { + Close(); +} + +IOFile::IOFile(IOFile&& other) noexcept { + std::swap(file_path, other.file_path); + std::swap(file_access_mode, other.file_access_mode); + std::swap(file_type, other.file_type); + std::swap(file, other.file); +} + +IOFile& IOFile::operator=(IOFile&& other) noexcept { + std::swap(file_path, other.file_path); + std::swap(file_access_mode, other.file_access_mode); + std::swap(file_type, other.file_type); + std::swap(file, other.file); + return *this; +} + +void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) { + Close(); + + file_path = path; + file_access_mode = mode; + file_type = type; + + errno = 0; + +#ifdef _WIN32 + if (flag != FileShareFlag::ShareNone) { + file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag)); } else { - return {true, std::fwrite(data, dataSize, length, handle)}; + _wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type)); } -} - -std::pair IOFile::readBytes(void* data, std::size_t count) { - return read(data, count, sizeof(std::uint8_t)); -} -std::pair IOFile::writeBytes(const void* data, std::size_t count) { - return write(data, count, sizeof(std::uint8_t)); -} - -std::optional IOFile::size() { - if (!isOpen()) - return {}; - - std::uint64_t pos = ftello(handle); - if (fseeko(handle, 0, SEEK_END) != 0) { - return {}; - } - - std::uint64_t size = ftello(handle); - if ((size != pos) && (fseeko(handle, pos, SEEK_SET) != 0)) { - return {}; - } - - return size; -} - -bool IOFile::seek(std::int64_t offset, int origin) { - if (!isOpen() || fseeko(handle, offset, origin) != 0) - return false; - - return true; -} - -bool IOFile::flush() { - if (!isOpen() || fflush(handle)) - return false; - - return true; -} - -bool IOFile::rewind() { - return seek(0, SEEK_SET); -} -FILE* IOFile::getHandle() { - return handle; -} - -void IOFile::setAppDataDir(const std::filesystem::path& dir) { - // if (dir == "") - // Helpers::panic("Failed to set app data directory"); - appData = dir; -} - -bool IOFile::setSize(std::uint64_t size) { - if (!isOpen()) - return false; - bool success; - -#ifdef WIN32 - success = _chsize_s(_fileno(handle), size) == 0; #else - success = ftruncate(fileno(handle), size) == 0; + file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); #endif - fflush(handle); - return success; + + if (!IsOpen()) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + } } + +void IOFile::Close() { + if (!IsOpen()) { + return; + } + + errno = 0; + + const auto close_result = std::fclose(file) == 0; + + if (!close_result) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + } + + file = nullptr; +} + +std::string IOFile::ReadString(size_t length) const { + std::vector string_buffer(length); + + const auto chars_read = ReadSpan(string_buffer); + const auto string_size = chars_read != length ? chars_read : length; + + return std::string{string_buffer.data(), string_size}; +} + +bool IOFile::Flush() const { + if (!IsOpen()) { + return false; + } + + errno = 0; + +#ifdef _WIN32 + const auto flush_result = std::fflush(file) == 0; +#else + const auto flush_result = std::fflush(file) == 0; +#endif + + if (!flush_result) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + } + + return flush_result; +} + +bool IOFile::Commit() const { + if (!IsOpen()) { + return false; + } + + errno = 0; + +#ifdef _WIN32 + const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0; +#else + const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0; +#endif + + if (!commit_result) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + } + + return commit_result; +} + +bool IOFile::SetSize(u64 size) const { + if (!IsOpen()) { + return false; + } + + errno = 0; + +#ifdef _WIN32 + const auto set_size_result = _chsize_s(fileno(file), static_cast(size)) == 0; +#else + const auto set_size_result = ftruncate(fileno(file), static_cast(size)) == 0; +#endif + + if (!set_size_result) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}", + PathToUTF8String(file_path), size, ec.message()); + } + + return set_size_result; +} + +u64 IOFile::GetSize() const { + if (!IsOpen()) { + return 0; + } + + // Flush any unwritten buffered data into the file prior to retrieving the file size. + std::fflush(file); + + std::error_code ec; + + const auto file_size = fs::file_size(file_path, ec); + + if (ec) { + LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}", + PathToUTF8String(file_path), ec.message()); + return 0; + } + + return file_size; +} + +bool IOFile::Seek(s64 offset, SeekOrigin origin) const { + if (!IsOpen()) { + return false; + } + + errno = 0; + + const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0; + + if (!seek_result) { + const auto ec = std::error_code{errno, std::generic_category()}; + LOG_ERROR(Common_Filesystem, + "Failed to seek the file at path={}, offset={}, origin={}, ec_message={}", + PathToUTF8String(file_path), offset, static_cast(origin), ec.message()); + } + + return seek_result; +} + +s64 IOFile::Tell() const { + if (!IsOpen()) { + return 0; + } + + errno = 0; + + return ftello(file); +} + +} // namespace Common::FS diff --git a/src/common/io_file.h b/src/common/io_file.h index 04e75600..11fafbec 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -1,45 +1,207 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once -#include + +#include #include -#include +#include +#include -class IOFile { - FILE* handle = nullptr; - static inline std::filesystem::path appData = - ""; // Directory for holding app data. AppData on Windows +#include "common/concepts.h" +#include "common/types.h" -public: - IOFile() : handle(nullptr) {} - IOFile(FILE* handle) : handle(handle) {} - IOFile(const std::filesystem::path& path, const char* permissions = "rb"); +namespace Common::FS { - bool isOpen() { - return handle != nullptr; - } - bool open(const std::filesystem::path& path, const char* permissions = "rb"); - bool open(const char* filename, const char* permissions = "rb"); - void close(); - - std::pair read(void* data, std::size_t length, std::size_t dataSize); - std::pair readBytes(void* data, std::size_t count); - - std::pair write(const void* data, std::size_t length, std::size_t dataSize); - std::pair writeBytes(const void* data, std::size_t count); - - std::optional size(); - - bool seek(std::int64_t offset, int origin = SEEK_SET); - bool rewind(); - bool flush(); - FILE* getHandle(); - static void setAppDataDir(const std::filesystem::path& dir); - static std::filesystem::path getAppData() { - return appData; - } - - // Sets the size of the file to "size" and returns whether it succeeded or not - bool setSize(std::uint64_t size); +enum class FileAccessMode { + /** + * If the file at path exists, it opens the file for reading. + * If the file at path does not exist, it fails to open the file. + */ + Read = 1 << 0, + /** + * If the file at path exists, the existing contents of the file are erased. + * The empty file is then opened for writing. + * If the file at path does not exist, it creates and opens a new empty file for writing. + */ + Write = 1 << 1, + /** + * If the file at path exists, it opens the file for reading and writing. + * If the file at path does not exist, it fails to open the file. + */ + ReadWrite = Read | Write, + /** + * If the file at path exists, it opens the file for appending. + * If the file at path does not exist, it creates and opens a new empty file for appending. + */ + Append = 1 << 2, + /** + * If the file at path exists, it opens the file for both reading and appending. + * If the file at path does not exist, it creates and opens a new empty file for both + * reading and appending. + */ + ReadAppend = Read | Append, }; + +enum class FileType { + BinaryFile, + TextFile, +}; + +enum class FileShareFlag { + ShareNone, // Provides exclusive access to the file. + ShareReadOnly, // Provides read only shared access to the file. + ShareWriteOnly, // Provides write only shared access to the file. + ShareReadWrite, // Provides read and write shared access to the file. +}; + +enum class SeekOrigin : u32 { + SetOrigin, // Seeks from the start of the file. + CurrentPosition, // Seeks from the current file pointer position. + End, // Seeks from the end of the file. +}; + +class IOFile final { +public: + IOFile(); + + explicit IOFile(const std::string& path, FileAccessMode mode, + FileType type = FileType::BinaryFile, + FileShareFlag flag = FileShareFlag::ShareReadOnly); + + explicit IOFile(std::string_view path, FileAccessMode mode, + FileType type = FileType::BinaryFile, + FileShareFlag flag = FileShareFlag::ShareReadOnly); + explicit IOFile(const std::filesystem::path& path, FileAccessMode mode, + FileType type = FileType::BinaryFile, + FileShareFlag flag = FileShareFlag::ShareReadOnly); + + ~IOFile(); + + IOFile(const IOFile&) = delete; + IOFile& operator=(const IOFile&) = delete; + + IOFile(IOFile&& other) noexcept; + IOFile& operator=(IOFile&& other) noexcept; + + std::filesystem::path GetPath() const { + return file_path; + } + + FileAccessMode GetAccessMode() const { + return file_access_mode; + } + + FileType GetType() const { + return file_type; + } + + bool IsOpen() const { + return file != nullptr; + } + + void Open(const std::filesystem::path& path, FileAccessMode mode, + FileType type = FileType::BinaryFile, + FileShareFlag flag = FileShareFlag::ShareReadOnly); + void Close(); + + bool Flush() const; + bool Commit() const; + + bool SetSize(u64 size) const; + u64 GetSize() const; + + bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const; + s64 Tell() const; + + template + size_t Read(T& data) const { + if constexpr (IsContiguousContainer) { + using ContiguousType = typename T::value_type; + static_assert(std::is_trivially_copyable_v, + "Data type must be trivially copyable."); + return ReadSpan(data); + } else { + return ReadObject(data) ? 1 : 0; + } + } + + template + size_t Write(const T& data) const { + if constexpr (IsContiguousContainer) { + using ContiguousType = typename T::value_type; + static_assert(std::is_trivially_copyable_v, + "Data type must be trivially copyable."); + return WriteSpan(data); + } else { + static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); + return WriteObject(data) ? 1 : 0; + } + } + + template + size_t ReadSpan(std::span data) const { + static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); + + if (!IsOpen()) { + return 0; + } + + return ReadRaw(data.data(), data.size()); + } + + template + size_t ReadRaw(void* data, size_t size) const { + return std::fread(data, sizeof(T), size, file); + } + + template + size_t WriteSpan(std::span data) const { + static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); + + if (!IsOpen()) { + return 0; + } + + return std::fwrite(data.data(), sizeof(T), data.size(), file); + } + + template + bool ReadObject(T& object) const { + static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); + static_assert(!std::is_pointer_v, "T must not be a pointer to an object."); + + if (!IsOpen()) { + return false; + } + + return std::fread(&object, sizeof(T), 1, file) == 1; + } + + template + bool WriteObject(const T& object) const { + static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); + static_assert(!std::is_pointer_v, "T must not be a pointer to an object."); + + if (!IsOpen()) { + return false; + } + + return std::fwrite(&object, sizeof(T), 1, file) == 1; + } + + std::string ReadString(size_t length) const; + + size_t WriteString(std::span string) const { + return WriteSpan(string); + } + +private: + std::filesystem::path file_path; + FileAccessMode file_access_mode{}; + FileType file_type{}; + + std::FILE* file = nullptr; +}; + +} // namespace Common::FS diff --git a/src/common/log.cpp b/src/common/log.cpp deleted file mode 100644 index 3ad797ba..00000000 --- a/src/common/log.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include -#include -#include -#include "common/log.h" -#ifdef _WIN64 -#include -#endif - -namespace Common::Log { - -std::vector sinks; -constexpr bool log_file_exceptions = true; - -void Flush() { - spdlog::details::registry::instance().flush_all(); -} - -thread_local uint8_t TLS[1024]; - -uint64_t tls_access(int64_t tls_offset) { - if (tls_offset == 0) { - return (uint64_t)TLS; - } -} - -#ifdef _WIN64 -static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { - auto orig_rip = pExp->ContextRecord->Rip; - while (*(uint8_t*)pExp->ContextRecord->Rip == 0x66) - pExp->ContextRecord->Rip++; - - if (*(uint8_t*)pExp->ContextRecord->Rip == 0xcd) { - int reg = *(uint8_t*)(pExp->ContextRecord->Rip + 1) - 0x80; - int sizes = *(uint8_t*)(pExp->ContextRecord->Rip + 2); - int pattern_size = sizes & 0xF; - int imm_size = sizes >> 4; - - int64_t tls_offset; - if (imm_size == 4) - tls_offset = *(int32_t*)(pExp->ContextRecord->Rip + pattern_size); - else - tls_offset = *(int64_t*)(pExp->ContextRecord->Rip + pattern_size); - - (&pExp->ContextRecord->Rax)[reg] = tls_access(tls_offset); /* TLS_ACCESS */ - pExp->ContextRecord->Rip += pattern_size + imm_size; - - return EXCEPTION_CONTINUE_EXECUTION; - } - - pExp->ContextRecord->Rip = orig_rip; - const u32 ec = pExp->ExceptionRecord->ExceptionCode; - switch (ec) { - case EXCEPTION_ACCESS_VIOLATION: { - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ACCESS_VIOLATION ({:#x}). ", ec); - const auto info = pExp->ExceptionRecord->ExceptionInformation; - switch (info[0]) { - case 0: - LOG_CRITICAL_IF(log_file_exceptions, "Read violation at address {:#x}.", info[1]); - break; - case 1: - LOG_CRITICAL_IF(log_file_exceptions, "Write violation at address {:#x}.", info[1]); - break; - case 8: - LOG_CRITICAL_IF(log_file_exceptions, "DEP violation at address {:#x}.", info[1]); - break; - default: - break; - } - break; - } - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED ({:#x}). ", - ec); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_DATATYPE_MISALIGNMENT ({:#x}). ", - ec); - break; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO ({:#x}). ", - ec); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_ILLEGAL_INSTRUCTION ({:#x}). ", - ec); - break; - case EXCEPTION_IN_PAGE_ERROR: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_IN_PAGE_ERROR ({:#x}). ", ec); - break; - case EXCEPTION_INT_DIVIDE_BY_ZERO: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO ({:#x}). ", - ec); - break; - case EXCEPTION_PRIV_INSTRUCTION: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_PRIV_INSTRUCTION ({:#x}). ", ec); - break; - case EXCEPTION_STACK_OVERFLOW: - LOG_CRITICAL_IF(log_file_exceptions, "Exception EXCEPTION_STACK_OVERFLOW ({:#x}). ", ec); - break; - default: - return EXCEPTION_CONTINUE_SEARCH; - } - Flush(); - return EXCEPTION_CONTINUE_SEARCH; -} -#endif - -int Init(bool use_stdout) { - sinks.clear(); - if (use_stdout) { - sinks.push_back(std::make_shared()); - } -#ifdef _WIN64 - sinks.push_back(std::make_shared(L"shadps4.txt", true)); -#else - sinks.push_back(std::make_shared("shadps4.txt", true)); -#endif - spdlog::set_default_logger( - std::make_shared("shadps4 logger", begin(sinks), end(sinks))); - auto f = std::make_unique( - "%^|%L|: %v%$", spdlog::pattern_time_type::local, std::string("")); // disable eol - spdlog::set_formatter(std::move(f)); - spdlog::set_level(static_cast(Config::getLogLevel())); - -#ifdef _WIN64 - if (!AddVectoredExceptionHandler(0, ExceptionHandler)) { - LOG_CRITICAL_IF(log_file_exceptions, "Failed to register an exception handler"); - } -#endif - - static std::terminate_handler old_terminate = nullptr; - old_terminate = std::set_terminate([]() { - try { - std::rethrow_exception(std::current_exception()); - } catch (const std::exception& e) { - LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. {}", e.what()); - } catch (...) { - LOG_CRITICAL_IF(log_file_exceptions, "Unhandled C++ exception. UNKNOWN"); - } - Flush(); - if (old_terminate) - old_terminate(); - }); - - return 0; -} - -void SetLevel(spdlog::level::level_enum log_level) { - spdlog::set_level(log_level); -} - -} // namespace Common::Log diff --git a/src/common/log.h b/src/common/log.h deleted file mode 100644 index 089cdcbd..00000000 --- a/src/common/log.h +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE - -#include - -namespace Common::Log { - -#define LOG_TRACE SPDLOG_TRACE -#define LOG_DEBUG SPDLOG_DEBUG -#define LOG_INFO SPDLOG_INFO -#define LOG_WARN SPDLOG_WARN -#define LOG_ERROR SPDLOG_ERROR -#define LOG_CRITICAL SPDLOG_CRITICAL - -#define LOG_TRACE_IF(flag, ...) \ - if (flag) \ - LOG_TRACE(__VA_ARGS__) -#define LOG_DEBUG_IF(flag, ...) \ - if (flag) \ - LOG_DEBUG(__VA_ARGS__) -#define LOG_INFO_IF(flag, ...) \ - if (flag) \ - LOG_INFO(__VA_ARGS__) -#define LOG_WARN_IF(flag, ...) \ - if (flag) \ - LOG_WARN(__VA_ARGS__) -#define LOG_ERROR_IF(flag, ...) \ - if (flag) \ - LOG_ERROR(__VA_ARGS__) -#define LOG_CRITICAL_IF(flag, ...) \ - if (flag) \ - LOG_CRITICAL(__VA_ARGS__) - -int Init(bool use_stdout); - -void SetLevel(spdlog::level::level_enum log_level); - -} // namespace Common::Log diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp new file mode 100644 index 00000000..50d18c98 --- /dev/null +++ b/src/common/logging/backend.cpp @@ -0,0 +1,277 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +#include +#include "Util/config.h" + +#ifdef _WIN32 +#include // For OutputDebugStringW +#endif + +#include "common/bounded_threadsafe_queue.h" +#include "common/io_file.h" +#include "common/logging/backend.h" +#include "common/logging/log.h" +#include "common/logging/log_entry.h" +#include "common/logging/text_formatter.h" +#include "common/path_util.h" +#include "common/string_util.h" +#include "common/thread.h" + +namespace Common::Log { + +using namespace Common::FS; + +namespace { + +/** + * Backend that writes to stderr and with color + */ +class ColorConsoleBackend { +public: + explicit ColorConsoleBackend() = default; + + ~ColorConsoleBackend() = default; + + void Write(const Entry& entry) { + if (enabled.load(std::memory_order_relaxed)) { + PrintColoredMessage(entry); + } + } + + void Flush() { + // stderr shouldn't be buffered + } + + void SetEnabled(bool enabled_) { + enabled = enabled_; + } + +private: + std::atomic_bool enabled{true}; +}; + +/** + * Backend that writes to a file passed into the constructor + */ +class FileBackend { +public: + explicit FileBackend(const std::filesystem::path& filename) + : file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {} + + ~FileBackend() = default; + + void Write(const Entry& entry) { + if (!enabled) { + return; + } + + bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n')); + + // Prevent logs from exceeding a set maximum size in the event that log entries are spammed. + const auto write_limit = 100_MB; + const bool write_limit_exceeded = bytes_written > write_limit; + if (entry.log_level >= Level::Error || write_limit_exceeded) { + if (write_limit_exceeded) { + // Stop writing after the write limit is exceeded. + // Don't close the file so we can print a stacktrace if necessary + enabled = false; + } + file.Flush(); + } + } + + void Flush() { + file.Flush(); + } + +private: + Common::FS::IOFile file; + bool enabled = true; + std::size_t bytes_written = 0; +}; + +/** + * Backend that writes to Visual Studio's output window + */ +class DebuggerBackend { +public: + explicit DebuggerBackend() = default; + + ~DebuggerBackend() = default; + + void Write(const Entry& entry) { +#ifdef _WIN32 + ::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str()); +#endif + } + + void Flush() {} + + void EnableForStacktrace() {} +}; + +bool initialization_in_progress_suppress_logging = true; + +/** + * Static state as a singleton. + */ +class Impl { +public: + static Impl& Instance() { + if (!instance) { + throw std::runtime_error("Using Logging instance before its initialization"); + } + return *instance; + } + + static void Initialize(std::string_view log_file) { + if (instance) { + LOG_WARNING(Log, "Reinitializing logging backend"); + return; + } + const auto& log_dir = GetUserPath(PathType::LogDir); + std::filesystem::create_directory(log_dir); + Filter filter; + filter.ParseFilterString(Config::getLogFilter()); + instance = std::unique_ptr(new Impl(log_dir / LOG_FILE, filter), + Deleter); + initialization_in_progress_suppress_logging = false; + } + + static void Start() { + instance->StartBackendThread(); + } + + static void Stop() { + instance->StopBackendThread(); + } + + Impl(const Impl&) = delete; + Impl& operator=(const Impl&) = delete; + + Impl(Impl&&) = delete; + Impl& operator=(Impl&&) = delete; + + void SetGlobalFilter(const Filter& f) { + filter = f; + } + + void SetColorConsoleBackendEnabled(bool enabled) { + color_console_backend.SetEnabled(enabled); + } + + void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, + const char* function, std::string message) { + if (!filter.CheckMessage(log_class, log_level)) { + return; + } + + using std::chrono::duration_cast; + using std::chrono::microseconds; + using std::chrono::steady_clock; + + message_queue.EmplaceWait(Entry{ + .timestamp = duration_cast(steady_clock::now() - time_origin), + .log_class = log_class, + .log_level = log_level, + .filename = filename, + .line_num = line_num, + .function = function, + .message = std::move(message), + }); + } + +private: + Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_) + : filter{filter_}, file_backend{file_backend_filename} {} + + ~Impl() = default; + + void StartBackendThread() { + backend_thread = std::jthread([this](std::stop_token stop_token) { + Common::SetCurrentThreadName("shadPS4:Log"); + Entry entry; + const auto write_logs = [this, &entry]() { + ForEachBackend([&entry](auto& backend) { backend.Write(entry); }); + }; + while (!stop_token.stop_requested()) { + message_queue.PopWait(entry, stop_token); + if (entry.filename != nullptr) { + write_logs(); + } + } + // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a + // case where a system is repeatedly spamming logs even on close. + int max_logs_to_write = filter.IsDebug() ? std::numeric_limits::max() : 100; + while (max_logs_to_write-- && message_queue.TryPop(entry)) { + write_logs(); + } + }); + } + + void StopBackendThread() { + backend_thread.request_stop(); + if (backend_thread.joinable()) { + backend_thread.join(); + } + + ForEachBackend([](auto& backend) { backend.Flush(); }); + } + + void ForEachBackend(auto lambda) { + lambda(debugger_backend); + lambda(color_console_backend); + lambda(file_backend); + } + + static void Deleter(Impl* ptr) { + delete ptr; + } + + static inline std::unique_ptr instance{nullptr, Deleter}; + + Filter filter; + DebuggerBackend debugger_backend{}; + ColorConsoleBackend color_console_backend{}; + FileBackend file_backend; + + MPSCQueue message_queue{}; + std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; + std::jthread backend_thread; +}; +} // namespace + +void Initialize(std::string_view log_file) { + Impl::Initialize(log_file.empty() ? LOG_FILE : log_file); +} + +void Start() { + Impl::Start(); +} + +void Stop() { + Impl::Stop(); +} + +void SetGlobalFilter(const Filter& filter) { + Impl::Instance().SetGlobalFilter(filter); +} + +void SetColorConsoleBackendEnabled(bool enabled) { + Impl::Instance().SetColorConsoleBackendEnabled(enabled); +} + +void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, + unsigned int line_num, const char* function, const char* format, + const fmt::format_args& args) { + if (!initialization_in_progress_suppress_logging) [[likely]] { + Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, + fmt::vformat(format, args)); + } +} +} // namespace Common::Log diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h new file mode 100644 index 00000000..91c9da83 --- /dev/null +++ b/src/common/logging/backend.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/logging/filter.h" + +namespace Common::Log { + +class Filter; + +/// Initializes the logging system. This should be the first thing called in main. +void Initialize(std::string_view log_file = ""); + +/// Starts the logging threads. +void Start(); + +/// Explictily stops the logger thread and flushes the buffers +void Stop(); + +/// The global filter will prevent any messages from even being processed if they are filtered. +void SetGlobalFilter(const Filter& filter); + +void SetColorConsoleBackendEnabled(bool enabled); + +} // namespace Common::Log diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp new file mode 100644 index 00000000..04c5d7ef --- /dev/null +++ b/src/common/logging/filter.cpp @@ -0,0 +1,173 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "common/assert.h" +#include "common/logging/filter.h" + +namespace Common::Log { +namespace { +template +Level GetLevelByName(const It begin, const It end) { + for (u8 i = 0; i < static_cast(Level::Count); ++i) { + const char* level_name = GetLevelName(static_cast(i)); + if (std::string_view(begin, end).compare(level_name) == 0) { + return static_cast(i); + } + } + return Level::Count; +} + +template +Class GetClassByName(const It begin, const It end) { + for (u8 i = 0; i < static_cast(Class::Count); ++i) { + const char* level_name = GetLogClassName(static_cast(i)); + if (std::string_view(begin, end).compare(level_name) == 0) { + return static_cast(i); + } + } + return Class::Count; +} + +template +bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { + auto level_separator = std::find(begin, end, ':'); + if (level_separator == end) { + LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}", + std::string_view(begin, end)); + return false; + } + + const Level level = GetLevelByName(level_separator + 1, end); + if (level == Level::Count) { + LOG_ERROR(Log, "Unknown log level in filter: {}", std::string_view(begin, end)); + return false; + } + + if (std::string_view(begin, level_separator).compare("*") == 0) { + instance.ResetAll(level); + return true; + } + + const Class log_class = GetClassByName(begin, level_separator); + if (log_class == Class::Count) { + LOG_ERROR(Log, "Unknown log class in filter: {}", std::string(begin, end)); + return false; + } + + instance.SetClassLevel(log_class, level); + return true; +} +} // Anonymous namespace + +/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this. +#define ALL_LOG_CLASSES() \ + CLS(Log) \ + CLS(Common) \ + SUB(Common, Filesystem) \ + SUB(Common, Memory) \ + CLS(Core) \ + SUB(Core, Linker) \ + CLS(Config) \ + CLS(Debug) \ + CLS(Kernel) \ + SUB(Kernel, Pthread) \ + SUB(Kernel, Vmm) \ + SUB(Kernel, Fs) \ + SUB(Kernel, Event) \ + SUB(Kernel, Sce) \ + CLS(Lib) \ + SUB(Lib, LibC) \ + SUB(Lib, Kernel) \ + SUB(Lib, Pad) \ + SUB(Lib, GnmDriver) \ + SUB(Lib, SystemService) \ + SUB(Lib, UserService) \ + SUB(Lib, VideoOut) \ + CLS(Frontend) \ + CLS(Render) \ + SUB(Render, Vulkan) \ + CLS(Input) \ + CLS(Loader) + +// GetClassName is a macro defined by Windows.h, grrr... +const char* GetLogClassName(Class log_class) { + switch (log_class) { +#define CLS(x) \ + case Class::x: \ + return #x; +#define SUB(x, y) \ + case Class::x##_##y: \ + return #x "." #y; + ALL_LOG_CLASSES() +#undef CLS +#undef SUB + case Class::Count: + default: + break; + } + UNREACHABLE(); +} + +const char* GetLevelName(Level log_level) { +#define LVL(x) \ + case Level::x: \ + return #x + switch (log_level) { + LVL(Trace); + LVL(Debug); + LVL(Info); + LVL(Warning); + LVL(Error); + LVL(Critical); + case Level::Count: + default: + break; + } +#undef LVL + UNREACHABLE(); +} + +Filter::Filter(Level default_level) { + ResetAll(default_level); +} + +void Filter::ResetAll(Level level) { + class_levels.fill(level); +} + +void Filter::SetClassLevel(Class log_class, Level level) { + class_levels[static_cast(log_class)] = level; +} + +void Filter::ParseFilterString(std::string_view filter_view) { + auto clause_begin = filter_view.cbegin(); + while (clause_begin != filter_view.cend()) { + auto clause_end = std::find(clause_begin, filter_view.cend(), ' '); + + // If clause isn't empty + if (clause_end != clause_begin) { + ParseFilterRule(*this, clause_begin, clause_end); + } + + if (clause_end != filter_view.cend()) { + // Skip over the whitespace + ++clause_end; + } + clause_begin = clause_end; + } +} + +bool Filter::CheckMessage(Class log_class, Level level) const { + return static_cast(level) >= + static_cast(class_levels[static_cast(log_class)]); +} + +bool Filter::IsDebug() const { + return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) { + return static_cast(l) <= static_cast(Level::Debug); + }); +} + +} // namespace Common::Log diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h new file mode 100644 index 00000000..7c46fd82 --- /dev/null +++ b/src/common/logging/filter.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include "common/logging/types.h" + +namespace Common::Log { + +/** + * Returns the name of the passed log class as a C-string. Subclasses are separated by periods + * instead of underscores as in the enumeration. + */ +const char* GetLogClassName(Class log_class); + +/** + * Returns the name of the passed log level as a C-string. + */ +const char* GetLevelName(Level log_level); + +/** + * Implements a log message filter which allows different log classes to have different minimum + * severity levels. The filter can be changed at runtime and can be parsed from a string to allow + * editing via the interface or loading from a configuration file. + */ +class Filter { +public: + /// Initializes the filter with all classes having `default_level` as the minimum level. + explicit Filter(Level default_level = Level::Info); + + /// Resets the filter so that all classes have `level` as the minimum displayed level. + void ResetAll(Level level); + + /// Sets the minimum level of `log_class` (and not of its subclasses) to `level`. + void SetClassLevel(Class log_class, Level level); + + /** + * Parses a filter string and applies it to this filter. + * + * A filter string consists of a space-separated list of filter rules, each of the format + * `:`. `` is a log class name, with subclasses separated using periods. + * `*` is allowed as a class name and will reset all filters to the specified level. `` + * a severity level name which will be set as the minimum logging level of the matched classes. + * Rules are applied left to right, with each rule overriding previous ones in the sequence. + * + * A few examples of filter rules: + * - `*:Info` -- Resets the level of all classes to Info. + * - `Service:Info` -- Sets the level of Service to Info. + * - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. + */ + void ParseFilterString(std::string_view filter_view); + + /// Matches class/level combination against the filter, returning true if it passed. + bool CheckMessage(Class log_class, Level level) const; + + /// Returns true if any logging classes are set to debug + bool IsDebug() const; + +private: + std::array(Class::Count)> class_levels; +}; + +} // namespace Common::Log diff --git a/src/common/logging/formatter.h b/src/common/logging/formatter.h new file mode 100644 index 00000000..f80905cc --- /dev/null +++ b/src/common/logging/formatter.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +// Adapted from https://github.com/fmtlib/fmt/issues/2704 +// a generic formatter for enum classes +#if FMT_VERSION >= 80100 +template +struct fmt::formatter, char>> + : formatter> { + template + auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) { + return fmt::formatter>::format( + static_cast>(value), ctx); + } +}; +#endif diff --git a/src/common/logging/log.h b/src/common/logging/log.h new file mode 100644 index 00000000..5fa43034 --- /dev/null +++ b/src/common/logging/log.h @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include + +#include "common/logging/formatter.h" +#include "common/logging/types.h" + +namespace Common::Log { + +constexpr const char* TrimSourcePath(std::string_view source) { + const auto rfind = [source](const std::string_view match) { + return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); + }; + auto idx = std::max({rfind("/"), rfind("\\")}); + return source.data() + idx; +} + +/// Logs a message to the global logger, using fmt +void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, + unsigned int line_num, const char* function, const char* format, + const fmt::format_args& args); + +template +void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num, + const char* function, const char* format, const Args&... args) { + FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format, + fmt::make_format_args(args...)); +} + +} // namespace Common::Log + +// Define the fmt lib macros +#define LOG_GENERIC(log_class, log_level, ...) \ + Common::Log::FmtLogMessage(log_class, log_level, Common::Log::TrimSourcePath(__FILE__), \ + __LINE__, __func__, __VA_ARGS__) + +#ifdef _DEBUG +#define LOG_TRACE(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Trace, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) +#else +#define LOG_TRACE(log_class, fmt, ...) (void(0)) +#endif + +#define LOG_DEBUG(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Debug, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) +#define LOG_INFO(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Info, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) +#define LOG_WARNING(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Warning, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) +#define LOG_ERROR(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Error, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) +#define LOG_CRITICAL(log_class, ...) \ + Common::Log::FmtLogMessage(Common::Log::Class::log_class, Common::Log::Level::Critical, \ + Common::Log::TrimSourcePath(__FILE__), __LINE__, __func__, \ + __VA_ARGS__) diff --git a/src/common/logging/log_entry.h b/src/common/logging/log_entry.h new file mode 100644 index 00000000..cd4ae935 --- /dev/null +++ b/src/common/logging/log_entry.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/logging/types.h" + +namespace Common::Log { + +/** + * A log entry. Log entries are store in a structured format to permit more varied output + * formatting on different frontends, as well as facilitating filtering and aggregation. + */ +struct Entry { + std::chrono::microseconds timestamp; + Class log_class{}; + Level log_level{}; + const char* filename = nullptr; + u32 line_num = 0; + std::string function; + std::string message; +}; + +} // namespace Common::Log diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp new file mode 100644 index 00000000..5f6c2172 --- /dev/null +++ b/src/common/logging/text_formatter.cpp @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include "common/assert.h" +#include "common/logging/filter.h" +#include "common/logging/log.h" +#include "common/logging/log_entry.h" +#include "common/logging/text_formatter.h" + +namespace Common::Log { + +std::string FormatLogMessage(const Entry& entry) { + const u32 time_seconds = static_cast(entry.timestamp.count() / 1000000); + const u32 time_fractional = static_cast(entry.timestamp.count() % 1000000); + + const char* class_name = GetLogClassName(entry.log_class); + const char* level_name = GetLevelName(entry.log_level); + + return fmt::format("[{}] <{}> {}:{}:{}: {}", class_name, level_name, entry.filename, + entry.function, entry.line_num, entry.message); +} + +void PrintMessage(const Entry& entry) { + const auto str = FormatLogMessage(entry).append(1, '\n'); + fputs(str.c_str(), stdout); +} + +void PrintColoredMessage(const Entry& entry) { +#ifdef _WIN32 + HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE); + if (console_handle == INVALID_HANDLE_VALUE) { + return; + } + + CONSOLE_SCREEN_BUFFER_INFO original_info{}; + GetConsoleScreenBufferInfo(console_handle, &original_info); + + WORD color = 0; + switch (entry.log_level) { + case Level::Trace: // Grey + color = FOREGROUND_INTENSITY; + break; + case Level::Debug: // Cyan + color = FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + case Level::Info: // Bright gray + color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + case Level::Warning: // Bright yellow + color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case Level::Error: // Bright red + color = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + case Level::Critical: // Bright magenta + color = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY; + break; + case Level::Count: + UNREACHABLE(); + } + + SetConsoleTextAttribute(console_handle, color); +#else +#define ESC "\x1b" + const char* color = ""; + switch (entry.log_level) { + case Level::Trace: // Grey + color = ESC "[1;30m"; + break; + case Level::Debug: // Cyan + color = ESC "[0;36m"; + break; + case Level::Info: // Bright gray + color = ESC "[0;37m"; + break; + case Level::Warning: // Bright yellow + color = ESC "[1;33m"; + break; + case Level::Error: // Bright red + color = ESC "[1;31m"; + break; + case Level::Critical: // Bright magenta + color = ESC "[1;35m"; + break; + case Level::Count: + UNREACHABLE(); + } + + fputs(color, stdout); +#endif + + PrintMessage(entry); + +#ifdef _WIN32 + SetConsoleTextAttribute(console_handle, original_info.wAttributes); +#else + fputs(ESC "[0m", stdout); +#undef ESC +#endif +} + +} // namespace Common::Log diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h new file mode 100644 index 00000000..504d8639 --- /dev/null +++ b/src/common/logging/text_formatter.h @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +namespace Common::Log { + +struct Entry; + +/// Formats a log entry into the provided text buffer. +std::string FormatLogMessage(const Entry& entry); + +/// Formats and prints a log entry to stderr. +void PrintMessage(const Entry& entry); + +/// Prints the same message as `PrintMessage`, but colored according to the severity level. +void PrintColoredMessage(const Entry& entry); + +} // namespace Common::Log diff --git a/src/common/logging/types.h b/src/common/logging/types.h new file mode 100644 index 00000000..f9ee22fb --- /dev/null +++ b/src/common/logging/types.h @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: Copyright 2023 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Common::Log { + +/// Specifies the severity or level of detail of the log message. +enum class Level : u8 { + Trace, ///< Extremely detailed and repetitive debugging information that is likely to + ///< pollute logs. + Debug, ///< Less detailed debugging information. + Info, ///< Status information from important points during execution. + Warning, ///< Minor or potential problems found during execution of a task. + Error, ///< Major problems found during execution of a task that prevent it from being + ///< completed. + Critical, ///< Major problems during execution that threaten the stability of the entire + ///< application. + + Count, ///< Total number of logging levels +}; + +/** + * Specifies the sub-system that generated the log message. + * + * @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in + * backend.cpp. + */ +enum class Class : u8 { + Log, ///< Messages about the log system itself + Common, ///< Library routines + Common_Filesystem, ///< Filesystem interface library + Common_Memory, ///< Memory mapping and management functions + Core, ///< LLE emulation core + Core_Linker, ///< The module linker + Config, ///< Emulator configuration (including commandline) + Debug, ///< Debugging tools + Kernel, ///< The HLE implementation of the PS4 kernel. + Kernel_Pthread, ///< The pthread implementation of the kernel. + Kernel_Fs, ///< The filesystem implementation of the kernel. + Kernel_Vmm, ///< The virtual memory implementation of the kernel. + Kernel_Event, ///< The event management implementation of the kernel. + Kernel_Sce, ///< The sony specific interfaces provided by the kernel. + Lib, ///< HLE implementation of system library. Each major library + ///< should have its own subclass. + Lib_LibC, ///< The LibC implementation. + Lib_Kernel, ///< The LibKernel implementation. + Lib_Pad, ///< The LibScePad implementation. + Lib_GnmDriver, ///< The LibSceGnmDriver implementation. + Lib_SystemService, ///< The LibSceSystemService implementation. + Lib_UserService, ///< The LibSceUserService implementation. + Lib_VideoOut, ///< The LibSceVideoOut implementation. + Frontend, ///< Emulator UI + Render, ///< Video Core + Render_Vulkan, ///< Vulkan backend + Loader, ///< ROM loader + Input, ///< Input emulation + Count ///< Total number of logging classes +}; + +} // namespace Common::Log diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp new file mode 100644 index 00000000..16ece313 --- /dev/null +++ b/src/common/path_util.cpp @@ -0,0 +1,87 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include + +#include "common/logging/log.h" +#include "common/path_util.h" + +#ifndef MAX_PATH +#ifdef _WIN32 +// This is the maximum number of UTF-16 code units permissible in Windows file paths +#define MAX_PATH 260 +#else +// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths +#define MAX_PATH 1024 +#endif +#endif + +namespace Common::FS { + +namespace fs = std::filesystem; + +static auto UserPaths = [] { + std::unordered_map paths; + const auto user_dir = std::filesystem::current_path() / PORTABLE_DIR; + + const auto create_path = [&](PathType shad_path, const fs::path& new_path) { + std::filesystem::create_directory(new_path); + paths.insert_or_assign(shad_path, new_path); + }; + + create_path(PathType::UserDir, user_dir); + create_path(PathType::LogDir, user_dir / LOG_DIR); + create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR); + create_path(PathType::ShaderDir, user_dir / SHADER_DIR); + create_path(PathType::App0, user_dir / APP0_DIR); + + return paths; +}(); + +bool ValidatePath(const fs::path& path) { + if (path.empty()) { + LOG_ERROR(Common_Filesystem, "Input path is empty, path={}", PathToUTF8String(path)); + return false; + } + +#ifdef _WIN32 + if (path.u16string().size() >= MAX_PATH) { + LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path)); + return false; + } +#else + if (path.u8string().size() >= MAX_PATH) { + LOG_ERROR(Common_Filesystem, "Input path is too long, path={}", PathToUTF8String(path)); + return false; + } +#endif + + return true; +} + +std::string PathToUTF8String(const std::filesystem::path& path) { + const auto u8_string = path.u8string(); + return std::string{u8_string.begin(), u8_string.end()}; +} + +const fs::path& GetUserPath(PathType shad_path) { + return UserPaths.at(shad_path); +} + +std::string GetUserPathString(PathType shad_path) { + return PathToUTF8String(GetUserPath(shad_path)); +} + +void SetUserPath(PathType shad_path, const fs::path& new_path) { + if (!std::filesystem::is_directory(new_path)) { + LOG_ERROR(Common_Filesystem, "Filesystem object at new_path={} is not a directory", + PathToUTF8String(new_path)); + return; + } + + UserPaths.insert_or_assign(shad_path, new_path); +} + +} // namespace Common::FS diff --git a/src/common/path_util.h b/src/common/path_util.h new file mode 100644 index 00000000..1836a3ac --- /dev/null +++ b/src/common/path_util.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +namespace Common::FS { + +enum class PathType { + UserDir, // Where shadPS4 stores its data. + LogDir, // Where log files are stored. + ScreenshotsDir, // Where screenshots are stored. + ShaderDir, // Where shaders are stored. + App0, // Where guest application data is stored. +}; + +constexpr auto PORTABLE_DIR = "user"; + +// Sub-directories contained within a user data directory +constexpr auto LOG_DIR = "log"; +constexpr auto SCREENSHOTS_DIR = "screenshots"; +constexpr auto SHADER_DIR = "shader"; +constexpr auto APP0_DIR = "app0"; + +// Filenames +constexpr auto LOG_FILE = "shad_log.txt"; + +/** + * Validates a given path. + * + * A given path is valid if it meets these conditions: + * - The path is not empty + * - The path is not too long + * + * @param path Filesystem path + * + * @returns True if the path is valid, false otherwise. + */ +[[nodiscard]] bool ValidatePath(const std::filesystem::path& path); + +/** + * Converts a filesystem path to a UTF-8 encoded std::string. + * + * @param path Filesystem path + * + * @returns UTF-8 encoded std::string. + */ +[[nodiscard]] std::string PathToUTF8String(const std::filesystem::path& path); + +/** + * Gets the filesystem path associated with the PathType enum. + * + * @param user_path PathType enum + * + * @returns The filesystem path associated with the PathType enum. + */ +[[nodiscard]] const std::filesystem::path& GetUserPath(PathType user_path); + +/** + * Gets the filesystem path associated with the PathType enum as a UTF-8 encoded std::string. + * + * @param user_path PathType enum + * + * @returns The filesystem path associated with the PathType enum as a UTF-8 encoded std::string. + */ +[[nodiscard]] std::string GetUserPathString(PathType user_path); + +/** + * Sets a new filesystem path associated with the PathType enum. + * If the filesystem object at new_path is not a directory, this function will not do anything. + * + * @param user_path PathType enum + * @param new_path New filesystem path + */ +void SetUserPath(PathType user_path, const std::filesystem::path& new_path); + +} // namespace Common::FS diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index a3973ef6..e38fd2af 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -6,6 +6,11 @@ #include #include #include "common/string_util.h" +#include "common/types.h" + +#ifdef _WIN32 +#include +#endif namespace Common { @@ -21,4 +26,46 @@ std::vector SplitString(const std::string& str, char delimiter) { return output; } +#ifdef _WIN32 +static std::wstring CPToUTF16(u32 code_page, std::string_view input) { + const auto size = + MultiByteToWideChar(code_page, 0, input.data(), static_cast(input.size()), nullptr, 0); + + if (size == 0) { + return {}; + } + + std::wstring output(size, L'\0'); + + if (size != MultiByteToWideChar(code_page, 0, input.data(), static_cast(input.size()), + &output[0], static_cast(output.size()))) { + output.clear(); + } + + return output; +} + +std::string UTF16ToUTF8(std::wstring_view input) { + const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast(input.size()), + nullptr, 0, nullptr, nullptr); + if (size == 0) { + return {}; + } + + std::string output(size, '\0'); + + if (size != WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast(input.size()), + &output[0], static_cast(output.size()), nullptr, + nullptr)) { + output.clear(); + } + + return output; +} + +std::wstring UTF8ToUTF16W(std::string_view input) { + return CPToUTF16(CP_UTF8, input); +} +#endif + } // namespace Common diff --git a/src/common/string_util.h b/src/common/string_util.h index 923579c9..ec3f1dca 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -11,4 +11,9 @@ namespace Common { std::vector SplitString(const std::string& str, char delimiter); +#ifdef _WIN32 +[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); +[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str); +#endif + } // namespace Common diff --git a/src/common/thread.cpp b/src/common/thread.cpp new file mode 100644 index 00000000..13db7eb5 --- /dev/null +++ b/src/common/thread.cpp @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "common/error.h" +#include "common/logging/log.h" +#include "common/thread.h" +#ifdef __APPLE__ +#include +#elif defined(_WIN32) +#include +#include "common/string_util.h" +#else +#if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#include +#else +#include +#endif +#include +#endif +#ifndef _WIN32 +#include +#endif + +#ifdef __FreeBSD__ +#define cpu_set_t cpuset_t +#endif + +namespace Common { + +#ifdef _WIN32 + +void SetCurrentThreadPriority(ThreadPriority new_priority) { + auto handle = GetCurrentThread(); + int windows_priority = 0; + switch (new_priority) { + case ThreadPriority::Low: + windows_priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case ThreadPriority::Normal: + windows_priority = THREAD_PRIORITY_NORMAL; + break; + case ThreadPriority::High: + windows_priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case ThreadPriority::VeryHigh: + windows_priority = THREAD_PRIORITY_HIGHEST; + break; + case ThreadPriority::Critical: + windows_priority = THREAD_PRIORITY_TIME_CRITICAL; + break; + default: + windows_priority = THREAD_PRIORITY_NORMAL; + break; + } + SetThreadPriority(handle, windows_priority); +} + +#else + +void SetCurrentThreadPriority(ThreadPriority new_priority) { + pthread_t this_thread = pthread_self(); + + const auto scheduling_type = SCHED_OTHER; + s32 max_prio = sched_get_priority_max(scheduling_type); + s32 min_prio = sched_get_priority_min(scheduling_type); + u32 level = std::max(static_cast(new_priority) + 1, 4U); + + struct sched_param params; + if (max_prio > min_prio) { + params.sched_priority = min_prio + ((max_prio - min_prio) * level) / 4; + } else { + params.sched_priority = min_prio - ((min_prio - max_prio) * level) / 4; + } + + pthread_setschedparam(this_thread, scheduling_type, ¶ms); +} + +#endif + +#ifdef _MSC_VER + +// Sets the debugger-visible name of the current thread. +void SetCurrentThreadName(const char* name) { + SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data()); +} + +#else // !MSVC_VER, so must be POSIX threads + +// MinGW with the POSIX threading model does not support pthread_setname_np +#if !defined(_WIN32) || defined(_MSC_VER) +void SetCurrentThreadName(const char* name) { +#ifdef __APPLE__ + pthread_setname_np(name); +#elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) + pthread_set_name_np(pthread_self(), name); +#elif defined(__NetBSD__) + pthread_setname_np(pthread_self(), "%s", (void*)name); +#elif defined(__linux__) + // Linux limits thread names to 15 characters and will outright reject any + // attempt to set a longer name with ERANGE. + std::string truncated(name, std::min(strlen(name), static_cast(15))); + if (int e = pthread_setname_np(pthread_self(), truncated.c_str())) { + errno = e; + LOG_ERROR(Common, "Failed to set thread name to '{}': {}", truncated, GetLastErrorMsg()); + } +#else + pthread_setname_np(pthread_self(), name); +#endif +} +#endif + +#if defined(_WIN32) +void SetCurrentThreadName(const char*) { + // Do Nothing on MingW +} +#endif + +#endif + +} // namespace Common diff --git a/src/common/thread.h b/src/common/thread.h new file mode 100644 index 00000000..39acc1db --- /dev/null +++ b/src/common/thread.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Common { + +enum class ThreadPriority : u32 { + Low = 0, + Normal = 1, + High = 2, + VeryHigh = 3, + Critical = 4, +}; + +void SetCurrentThreadPriority(ThreadPriority new_priority); + +void SetCurrentThreadName(const char* name); + +} // namespace Common diff --git a/src/core/PS4/GPU/video_out_buffer.cpp b/src/core/PS4/GPU/video_out_buffer.cpp index b0a5493f..87283997 100644 --- a/src/core/PS4/GPU/video_out_buffer.cpp +++ b/src/core/PS4/GPU/video_out_buffer.cpp @@ -1,14 +1,12 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "core/PS4/GPU/tile_manager.h" #include "core/PS4/GPU/video_out_buffer.h" #include "vulkan_util.h" -constexpr bool log_file_videoOutBuffer = true; // disable it to disable logging - static void update_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params, void* obj, const u64* virtual_addr, const u64* size, int virtual_addr_num) { @@ -55,8 +53,7 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params vk_format = VK_FORMAT_B8G8R8A8_SRGB; break; default: - LOG_CRITICAL_IF(log_file_videoOutBuffer, "unknown pixelFormat = {}\n", pixel_format); - std::exit(0); + UNREACHABLE_MSG("Unknown pixelFormat = {}", pixel_format); } vk_obj->extent.width = width; @@ -91,8 +88,7 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params vkCreateImage(ctx->m_device, &image_info, nullptr, &vk_obj->image); if (vk_obj->image == nullptr) { - LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image is null\n"); - std::exit(0); + UNREACHABLE_MSG("vk_obj->image is null"); } vkGetImageMemoryRequirements(ctx->m_device, vk_obj->image, &mem->requirements); @@ -102,19 +98,15 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params bool allocated = GPU::vulkanAllocateMemory(ctx, mem); if (!allocated) { - LOG_CRITICAL_IF(log_file_videoOutBuffer, "can't allocate vulkan memory\n"); - std::exit(0); + UNREACHABLE_MSG("Can't allocate vulkan memory"); } vkBindImageMemory(ctx->m_device, vk_obj->image, mem->memory, mem->offset); vk_obj->memory = *mem; - LOG_INFO_IF(log_file_videoOutBuffer, "videoOutBuffer create object\n"); - LOG_INFO_IF(log_file_videoOutBuffer, "mem requirements.size = {}\n", mem->requirements.size); - LOG_INFO_IF(log_file_videoOutBuffer, "width = {}\n", width); - LOG_INFO_IF(log_file_videoOutBuffer, "height = {}\n", height); - LOG_INFO_IF(log_file_videoOutBuffer, "size = {}\n", *size); + LOG_INFO(Lib_VideoOut, "videoOutBuffer create object width = {}, height = {}, size = {}", width, + height, *size); update_func(ctx, params, vk_obj, virtual_addr, size, virtual_addr_num); @@ -139,8 +131,7 @@ static void* create_func(HLE::Libs::Graphics::GraphicCtx* ctx, const u64* params &vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT]); if (vk_obj->image_view[HLE::Libs::Graphics::VulkanImage::VIEW_DEFAULT] == nullptr) { - LOG_CRITICAL_IF(log_file_videoOutBuffer, "vk_obj->image_view is null\n"); - std::exit(0); + UNREACHABLE_MSG("vk_obj->image_view is null"); } return vk_obj; diff --git a/src/core/PS4/HLE/Graphics/video_out.cpp b/src/core/PS4/HLE/Graphics/video_out.cpp index 05a18db3..259d0568 100644 --- a/src/core/PS4/HLE/Graphics/video_out.cpp +++ b/src/core/PS4/HLE/Graphics/video_out.cpp @@ -3,11 +3,10 @@ #include #include -#include #include "Objects/video_out_ctx.h" #include "Util/config.h" #include "common/debug.h" -#include "common/log.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/PS4/GPU/gpu_memory.h" #include "core/PS4/GPU/video_out_buffer.h" @@ -58,17 +57,11 @@ std::string getPixelFormatString(s32 format) { void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(SceVideoOutBufferAttribute* attribute, u32 pixelFormat, u32 tilingMode, u32 aspectRatio, u32 width, u32 height, u32 pitchInPixel) { - PRINT_FUNCTION_NAME(); - - auto tileMode = magic_enum::enum_cast(tilingMode); - auto aspectR = magic_enum::enum_cast(aspectRatio); - - LOG_INFO_IF(log_file_videoout, "pixelFormat = {}\n", getPixelFormatString(pixelFormat)); - LOG_INFO_IF(log_file_videoout, "tilingMode = {}\n", magic_enum::enum_name(tileMode.value())); - LOG_INFO_IF(log_file_videoout, "aspectRatio = {}\n", magic_enum::enum_name(aspectR.value())); - LOG_INFO_IF(log_file_videoout, "width = {}\n", width); - LOG_INFO_IF(log_file_videoout, "height = {}\n", height); - LOG_INFO_IF(log_file_videoout, "pitchInPixel = {}\n", pitchInPixel); + LOG_INFO(Lib_VideoOut, + "pixelFormat = {}, tilingMode = {}, aspectRatio = {}, width = {}, height = {}, " + "pitchInPixel = {}", + getPixelFormatString(pixelFormat), tilingMode, aspectRatio, width, height, + pitchInPixel); std::memset(attribute, 0, sizeof(SceVideoOutBufferAttribute)); @@ -100,7 +93,8 @@ static void flip_delete_event_func(Core::Kernel::SceKernelEqueue eq, s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 handle, void* udata) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Lib_VideoOut, "handle = {}", handle); + auto* videoOut = Common::Singleton::Instance(); auto* ctx = videoOut->getCtx(handle); @@ -136,46 +130,43 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Core::Kernel::SceKernelEqueue eq, s32 h s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses, s32 bufferNum, const SceVideoOutBufferAttribute* attribute) { - PRINT_FUNCTION_NAME(); auto* videoOut = Common::Singleton::Instance(); auto* ctx = videoOut->getCtx(handle); if (handle == 1) { // main port if (startIndex < 0 || startIndex > 15) { - LOG_TRACE_IF(log_file_videoout, "invalid startIndex = {}\n", startIndex); + LOG_ERROR(Lib_VideoOut, "Invalid startIndex = {}", startIndex); return SCE_VIDEO_OUT_ERROR_INVALID_VALUE; } if (bufferNum < 1 || bufferNum > 16) { - LOG_TRACE_IF(log_file_videoout, "invalid bufferNum = {}\n", bufferNum); + LOG_ERROR(Lib_VideoOut, "Invalid bufferNum = {}", bufferNum); return SCE_VIDEO_OUT_ERROR_INVALID_VALUE; } } if (addresses == nullptr) { - LOG_TRACE_IF(log_file_videoout, "addresses are null\n"); + LOG_ERROR(Lib_VideoOut, "Addresses are null"); return SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS; } if (attribute == nullptr) { - LOG_TRACE_IF(log_file_videoout, "attribute is null\n"); + LOG_ERROR(Lib_VideoOut, "Attribute is null"); return SCE_VIDEO_OUT_ERROR_INVALID_OPTION; } if (attribute->aspectRatio != 0) { - LOG_TRACE_IF(log_file_videoout, "invalid aspect ratio = {}\n", attribute->aspectRatio); + LOG_ERROR(Lib_VideoOut, "Invalid aspect ratio = {}", attribute->aspectRatio); return SCE_VIDEO_OUT_ERROR_INVALID_ASPECT_RATIO; } if (attribute->tilingMode < 0 || attribute->tilingMode > 1) { - LOG_TRACE_IF(log_file_videoout, "invalid tilingMode = {}\n", attribute->tilingMode); + LOG_ERROR(Lib_VideoOut, "Invalid tilingMode = {}", attribute->tilingMode); return SCE_VIDEO_OUT_ERROR_INVALID_TILING_MODE; } - LOG_INFO_IF(log_file_videoout, "startIndex = {}\n", startIndex); - LOG_INFO_IF(log_file_videoout, "bufferNum = {}\n", bufferNum); - LOG_INFO_IF(log_file_videoout, "pixelFormat = {:#x}\n", attribute->pixelFormat); - LOG_INFO_IF(log_file_videoout, "tilingMode = {}\n", attribute->tilingMode); - LOG_INFO_IF(log_file_videoout, "aspectRatio = {}\n", attribute->aspectRatio); - LOG_INFO_IF(log_file_videoout, "width = {}\n", attribute->width); - LOG_INFO_IF(log_file_videoout, "height = {}\n", attribute->height); - LOG_INFO_IF(log_file_videoout, "pitchInPixel = {}\n", attribute->pitchInPixel); - LOG_INFO_IF(log_file_videoout, "option = {}\n", attribute->option); + + LOG_INFO(Lib_VideoOut, + "handle = {}, startIndex = {}, bufferNum = {}, pixelFormat = {:#x}, aspectRatio = {}, " + "tilingMode = {}, width = {}, height = {}, pitchInPixel = {}, option = {:#x}", + handle, startIndex, bufferNum, attribute->pixelFormat, attribute->aspectRatio, + attribute->tilingMode, attribute->width, attribute->height, attribute->pitchInPixel, + attribute->option); int registration_index = ctx->buffers_registration_index++; @@ -214,7 +205,7 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co for (int i = 0; i < bufferNum; i++) { if (ctx->buffers[i + startIndex].buffer != nullptr) { - LOG_TRACE_IF(log_file_videoout, "buffer slot {} is occupied!\n", i + startIndex); + LOG_ERROR(Lib_VideoOut, "Buffer slot {} is occupied!", i + startIndex); return SCE_VIDEO_OUT_ERROR_SLOT_OCCUPIED; } @@ -227,51 +218,49 @@ s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* co 0, videoOut->getGraphicCtx(), nullptr, reinterpret_cast(addresses[i]), buffer_size, buffer_info)); - LOG_INFO_IF(log_file_videoout, "buffers[{}] = {:#x}\n", i + startIndex, - reinterpret_cast(addresses[i])); + LOG_INFO(Lib_VideoOut, "buffers[{}] = {:#x}", i + startIndex, + reinterpret_cast(addresses[i])); } return registration_index; } s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Lib_VideoOut, "called"); auto* videoOut = Common::Singleton::Instance(); videoOut->getCtx(handle)->m_flip_rate = rate; return SCE_OK; } s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Lib_VideoOut, "called"); auto* videoOut = Common::Singleton::Instance(); s32 pending = videoOut->getCtx(handle)->m_flip_status.flipPendingNum; return pending; } s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg) { - PRINT_FUNCTION_NAME(); auto* videoOut = Common::Singleton::Instance(); auto* ctx = videoOut->getCtx(handle); if (flipMode != 1) { // BREAKPOINT(); // only flipmode==1 is supported - LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flipmode {}\n", - bufferIndex); // openBOR needs 2 but seems to work + LOG_WARNING(Lib_VideoOut, "flipmode = {}", + flipMode); // openBOR needs 2 but seems to work } if (bufferIndex == -1) { BREAKPOINT(); // blank output not supported } if (bufferIndex < -1 || bufferIndex > 15) { - LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip invalid bufferIndex {}\n", - bufferIndex); + LOG_ERROR(Lib_VideoOut, "Invalid bufferIndex = {}", bufferIndex); return SCE_VIDEO_OUT_ERROR_INVALID_INDEX; } - LOG_INFO_IF(log_file_videoout, "bufferIndex = {}\n", bufferIndex); - LOG_INFO_IF(log_file_videoout, "flipMode = {}\n", flipMode); - LOG_INFO_IF(log_file_videoout, "flipArg = {}\n", flipArg); + + LOG_INFO(Lib_VideoOut, "bufferIndex = {}, flipMode = {}, flipArg = {}", bufferIndex, flipMode, + flipArg); if (!videoOut->getFlipQueue().submitFlip(ctx, bufferIndex, flipArg)) { - LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flip queue is full\n"); + LOG_ERROR(Lib_VideoOut, "Flip queue is full"); return SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL; } Core::Libraries::LibSceGnmDriver::sceGnmFlushGarlic(); // hackish should be done that neccesary @@ -280,24 +269,20 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode } s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, SceVideoOutFlipStatus* status) { - PRINT_FUNCTION_NAME(); auto* videoOut = Common::Singleton::Instance(); auto* ctx = videoOut->getCtx(handle); videoOut->getFlipQueue().getFlipStatus(ctx, status); - LOG_INFO_IF(log_file_videoout, "count = {}\n", status->count); - LOG_INFO_IF(log_file_videoout, "processTime = {}\n", status->processTime); - LOG_INFO_IF(log_file_videoout, "tsc = {}\n", status->tsc); - LOG_INFO_IF(log_file_videoout, "submitTsc = {}\n", status->submitTsc); - LOG_INFO_IF(log_file_videoout, "flipArg = {}\n", status->flipArg); - LOG_INFO_IF(log_file_videoout, "gcQueueNum = {}\n", status->gcQueueNum); - LOG_INFO_IF(log_file_videoout, "flipPendingNum = {}\n", status->flipPendingNum); - LOG_INFO_IF(log_file_videoout, "currentBuffer = {}\n", status->currentBuffer); + LOG_INFO(Lib_VideoOut, + "count = {}, processTime = {}, tsc = {}, submitTsc = {}, flipArg = {}, gcQueueNum = " + "{}, flipPendingNum = {}, currentBuffer = {}", + status->count, status->processTime, status->tsc, status->submitTsc, status->flipArg, + status->gcQueueNum, status->flipPendingNum, status->currentBuffer); return 0; } s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Lib_VideoOut, "called"); auto* videoOut = Common::Singleton::Instance(); *status = videoOut->getCtx(handle)->m_resolution; return SCE_OK; @@ -305,7 +290,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutio s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index, const void* param) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Lib_VideoOut, "called"); if (userId != SCE_USER_SERVICE_USER_ID_SYSTEM && userId != 0) { BREAKPOINT(); } @@ -313,7 +298,7 @@ s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 i BREAKPOINT(); } if (index != 0) { - LOG_TRACE_IF(log_file_videoout, "sceVideoOutOpen index!=0\n"); + LOG_ERROR(Lib_VideoOut, "Index != 0"); return SCE_VIDEO_OUT_ERROR_INVALID_VALUE; } if (param != nullptr) { @@ -323,7 +308,7 @@ s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 i int handle = videoOut->Open(); if (handle < 0) { - LOG_TRACE_IF(log_file_videoout, "sceVideoOutOpen all available handles are open\n"); + LOG_ERROR(Lib_VideoOut, "All available handles are open"); return SCE_VIDEO_OUT_ERROR_RESOURCE_BUSY; // it is alreadyOpened } @@ -342,7 +327,6 @@ s32 PS4_SYSV_ABI sceVideoOutUnregisterBuffers(s32 handle, s32 attributeIndex) { } void videoOutRegisterLib(Core::Loader::SymbolsResolver* sym) { - using namespace Core; LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutGetFlipStatus); LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutSubmitFlip); diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp index 34db7a94..5a797548 100644 --- a/src/core/aerolib/stubs.cpp +++ b/src/core/aerolib/stubs.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/log.h" +#include "common/logging/log.h" #include "core/aerolib/aerolib.h" #include "core/aerolib/stubs.h" @@ -22,13 +22,12 @@ namespace Core::AeroLib { constexpr u32 MAX_STUBS = 128; u64 UnresolvedStub() { - LOG_ERROR("Unresolved Stub: called, returning zero to {}\n", __builtin_return_address(0)); + LOG_ERROR(Core, "Returning zero to {}", __builtin_return_address(0)); return 0; } static u64 UnknownStub() { - LOG_ERROR("Stub: Unknown (nid: Unknown) called, returning zero to {}\n", - __builtin_return_address(0)); + LOG_ERROR(Core, "Returning zero to {}", __builtin_return_address(0)); return 0; } @@ -39,10 +38,10 @@ template static u64 CommonStub() { auto entry = stub_nids[stub_index]; if (entry) { - LOG_ERROR("Stub: {} (nid: {}) called, returning zero to {}\n", entry->name, entry->nid, + LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}", entry->name, entry->nid, __builtin_return_address(0)); } else { - LOG_ERROR("Stub: Unknown (nid: {}) called, returning zero to {}\n", + LOG_ERROR(Core, "Stub: Unknown (nid: {}) called, returning zero to {}", stub_nids_unknown[stub_index], __builtin_return_address(0)); } return 0; diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 5e8f8312..6a99a808 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -8,21 +8,24 @@ namespace Core::FileSys { constexpr int RESERVED_HANDLES = 3; // First 3 handles are stdin,stdout,stderr -void MntPoints::mount(const std::string& host_folder, const std::string& guest_folder) { +void MntPoints::Mount(const std::filesystem::path& host_folder, const std::string& guest_folder) { std::scoped_lock lock{m_mutex}; MntPair pair; - pair.host_path = host_folder; + pair.host_path = host_folder.string(); pair.guest_path = guest_folder; m_mnt_pairs.push_back(pair); } -void MntPoints::unmount(const std::string& path) {} // TODO! -void MntPoints::unmountAll() { + +void MntPoints::Unmount(const std::string& path) {} // TODO! + +void MntPoints::UnmountAll() { std::scoped_lock lock{m_mutex}; m_mnt_pairs.clear(); } -std::string MntPoints::getHostDirectory(const std::string& guest_directory) { + +std::string MntPoints::GetHostDirectory(const std::string& guest_directory) { std::scoped_lock lock{m_mutex}; for (auto& pair : m_mnt_pairs) { if (pair.guest_path.starts_with(guest_directory)) { @@ -38,7 +41,8 @@ std::string MntPoints::getHostDirectory(const std::string& guest_directory) { } return ""; } -std::string MntPoints::getHostFile(const std::string& guest_file) { + +std::string MntPoints::GetHostFile(const std::string& guest_file) { std::scoped_lock lock{m_mutex}; for (auto& pair : m_mnt_pairs) { @@ -52,11 +56,13 @@ std::string MntPoints::getHostFile(const std::string& guest_file) { } return ""; } -int HandleTable::createHandle() { + +int HandleTable::CreateHandle() { std::scoped_lock lock{m_mutex}; + auto* file = new File{}; - file->isDirectory = false; - file->isOpened = false; + file->is_directory = false; + file->is_opened = false; int existingFilesNum = m_files.size(); @@ -68,19 +74,20 @@ int HandleTable::createHandle() { } m_files.push_back(file); - return m_files.size() + RESERVED_HANDLES - 1; } -void HandleTable::deleteHandle(int d) { + +void HandleTable::DeleteHandle(int d) { std::scoped_lock lock{m_mutex}; delete m_files.at(d - RESERVED_HANDLES); m_files[d - RESERVED_HANDLES] = nullptr; } -File* HandleTable::getFile(int d) { +File* HandleTable::GetFile(int d) { std::scoped_lock lock{m_mutex}; return m_files.at(d - RESERVED_HANDLES); } + File* HandleTable::getFile(const std::string& host_name) { std::scoped_lock lock{m_mutex}; for (auto* file : m_files) { diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 79910525..7d7b9985 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -7,7 +7,6 @@ #include #include #include -#include "common/fs_file.h" #include "common/io_file.h" namespace Core::FileSys { @@ -21,11 +20,12 @@ public: MntPoints() = default; virtual ~MntPoints() = default; - void mount(const std::string& host_folder, const std::string& guest_folder); - void unmount(const std::string& path); - void unmountAll(); - std::string getHostDirectory(const std::string& guest_directory); - std::string getHostFile(const std::string& guest_file); + + void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder); + void Unmount(const std::string& path); + void UnmountAll(); + std::string GetHostDirectory(const std::string& guest_directory); + std::string GetHostFile(const std::string& guest_file); private: std::vector m_mnt_pairs; @@ -33,22 +33,24 @@ private: }; struct File { - std::atomic_bool isOpened; - std::atomic_bool isDirectory; + std::atomic_bool is_opened{}; + std::atomic_bool is_directory{}; std::string m_host_name; std::string m_guest_name; - IOFile f; + Common::FS::IOFile f; // std::vector dirents; u32 dirents_index; std::mutex m_mutex; }; + class HandleTable { public: - HandleTable() {} - virtual ~HandleTable() {} - int createHandle(); - void deleteHandle(int d); - File* getFile(int d); + HandleTable() = default; + virtual ~HandleTable() = default; + + int CreateHandle(); + void DeleteHandle(int d); + File* GetFile(int d); File* getFile(const std::string& host_name); private: diff --git a/src/core/hle/kernel/cpu_management.cpp b/src/core/hle/kernel/cpu_management.cpp index bd483e84..81c3b3fe 100644 --- a/src/core/hle/kernel/cpu_management.cpp +++ b/src/core/hle/kernel/cpu_management.cpp @@ -2,14 +2,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "Util/config.h" -#include "common/log.h" +#include "common/logging/log.h" #include "core/hle/kernel/cpu_management.h" -#include "core/hle/libraries/libs.h" namespace Core::Kernel { int PS4_SYSV_ABI sceKernelIsNeoMode() { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Sce, "called"); return Config::isNeoMode(); } diff --git a/src/core/hle/kernel/event_queues.cpp b/src/core/hle/kernel/event_queues.cpp index ca3264d4..9c198fc3 100644 --- a/src/core/hle/kernel/event_queues.cpp +++ b/src/core/hle/kernel/event_queues.cpp @@ -1,51 +1,44 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "core/hle/error_codes.h" #include "core/hle/kernel/event_queues.h" -#include "core/hle/libraries/libs.h" namespace Core::Kernel { -constexpr bool log_file_equeues = true; // disable it to disable logging - int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name) { - PRINT_FUNCTION_NAME(); - if (eq == nullptr) { - LOG_TRACE_IF(log_file_equeues, - "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL eq invalid\n"); + LOG_ERROR(Kernel_Event, "Event queue is null!"); return SCE_KERNEL_ERROR_EINVAL; } if (name == nullptr) { - LOG_TRACE_IF(log_file_equeues, - "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EFAULT name invalid\n"); + LOG_ERROR(Kernel_Event, "Event queue name is invalid!"); return SCE_KERNEL_ERROR_EFAULT; } if (name == NULL) { - LOG_TRACE_IF(log_file_equeues, - "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_EINVAL name is null\n"); + LOG_ERROR(Kernel_Event, "Event queue name is null!"); return SCE_KERNEL_ERROR_EINVAL; } - if (strlen(name) > 31) { // max is 32 including null terminator - LOG_TRACE_IF(log_file_equeues, - "sceKernelCreateEqueue returned SCE_KERNEL_ERROR_ENAMETOOLONG name size " - "exceeds 32 bytes\n"); + // Maximum is 32 including null terminator + static constexpr size_t MaxEventQueueNameSize = 32; + if (std::strlen(name) > MaxEventQueueNameSize) { + LOG_ERROR(Kernel_Event, "Event queue name exceeds 32 bytes!"); return SCE_KERNEL_ERROR_ENAMETOOLONG; } + + LOG_INFO(Kernel_Event, "name = {}", name); + *eq = new EqueueInternal; (*eq)->setName(std::string(name)); - - LOG_INFO_IF(log_file_equeues, "sceKernelCreateEqueue created with name \"{}\"\n", name); return SCE_OK; } int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int num, int* out, SceKernelUseconds* timo) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Event, "num = {}", num); if (eq == nullptr) { return SCE_KERNEL_ERROR_EBADF; @@ -66,10 +59,10 @@ int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int if (timo != nullptr) { // Only events that have already arrived at the time of this function call can be received if (*timo == 0) { - BREAKPOINT(); + UNREACHABLE(); } else { // Wait until an event arrives with timing out - BREAKPOINT(); + UNREACHABLE(); } } diff --git a/src/core/hle/kernel/memory_management.cpp b/src/core/hle/kernel/memory_management.cpp index 7cb23e8f..9491b4a3 100644 --- a/src/core/hle/kernel/memory_management.cpp +++ b/src/core/hle/kernel/memory_management.cpp @@ -2,106 +2,85 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/PS4/GPU/gpu_memory.h" #include "core/hle/error_codes.h" #include "core/hle/kernel/Objects/physical_memory.h" #include "core/hle/kernel/memory_management.h" -#include "core/hle/libraries/libs.h" #include "core/virtual_memory.h" namespace Core::Kernel { -constexpr bool log_file_memory = true; // disable it to disable logging - bool is16KBAligned(u64 n) { return ((n % (16ull * 1024) == 0)); } u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() { - PRINT_FUNCTION_NAME(); + LOG_WARNING(Kernel_Vmm, "(STUBBED) called"); return SCE_KERNEL_MAIN_DMEM_SIZE; } int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Vmm, + "searchStart = {:#x}, searchEnd = {:#x}, len = {:#x}, alignment = {:#x}, memoryType = " + "{:#x}", + searchStart, searchEnd, len, alignment, memoryType); if (searchStart < 0 || searchEnd <= searchStart) { - LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned " - "SCE_KERNEL_ERROR_EINVAL searchStart,searchEnd invalid\n"); + LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); return SCE_KERNEL_ERROR_EINVAL; } - bool isInRange = (searchStart < len && searchEnd > len); - if (len <= 0 || !is16KBAligned(len) || !isInRange) { - LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned " - "SCE_KERNEL_ERROR_EINVAL memory range invalid\n"); + const bool is_in_range = (searchStart < len && searchEnd > len); + if (len <= 0 || !is16KBAligned(len) || !is_in_range) { + LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); return SCE_KERNEL_ERROR_EINVAL; } if ((alignment != 0 || is16KBAligned(alignment)) && !std::has_single_bit(alignment)) { - LOG_TRACE_IF( - log_file_memory, - "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n"); + LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); return SCE_KERNEL_ERROR_EINVAL; } if (physAddrOut == nullptr) { - LOG_TRACE_IF( - log_file_memory, - "sceKernelAllocateDirectMemory returned SCE_KERNEL_ERROR_EINVAL physAddrOut is null\n"); + LOG_ERROR(Kernel_Vmm, "Result physical address pointer is null!"); return SCE_KERNEL_ERROR_EINVAL; } - auto memtype = magic_enum::enum_cast(memoryType); - - LOG_INFO_IF(log_file_memory, "search_start = {:#x}\n", searchStart); - LOG_INFO_IF(log_file_memory, "search_end = {:#x}\n", searchEnd); - LOG_INFO_IF(log_file_memory, "len = {:#x}\n", len); - LOG_INFO_IF(log_file_memory, "alignment = {:#x}\n", alignment); - LOG_INFO_IF(log_file_memory, "memory_type = {}\n", magic_enum::enum_name(memtype.value())); u64 physical_addr = 0; auto* physical_memory = Common::Singleton::Instance(); if (!physical_memory->Alloc(searchStart, searchEnd, len, alignment, &physical_addr, memoryType)) { - LOG_TRACE_IF(log_file_memory, "sceKernelAllocateDirectMemory returned " - "SCE_KERNEL_ERROR_EAGAIN can't allocate physical memory\n"); + LOG_CRITICAL(Kernel_Vmm, "Unable to allocate physical memory"); return SCE_KERNEL_ERROR_EAGAIN; } *physAddrOut = static_cast(physical_addr); - LOG_INFO_IF(true, "physAddrOut = {:#x}\n", physical_addr); + LOG_INFO(Kernel_Vmm, "physAddrOut = {:#x}", physical_addr); return SCE_OK; } int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) { - PRINT_FUNCTION_NAME(); + LOG_INFO( + Kernel_Vmm, + "len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = {:#x}", + len, prot, flags, directMemoryStart, alignment); + if (len == 0 || !is16KBAligned(len)) { - LOG_TRACE_IF(log_file_memory, - "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL len invalid\n"); + LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!"); return SCE_KERNEL_ERROR_EINVAL; } if (!is16KBAligned(directMemoryStart)) { - LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL " - "directMemoryStart invalid\n"); + LOG_ERROR(Kernel_Vmm, "Start address is not 16KB aligned!"); return SCE_KERNEL_ERROR_EINVAL; } if (alignment != 0) { if ((!std::has_single_bit(alignment) && !is16KBAligned(alignment))) { - LOG_TRACE_IF( - log_file_memory, - "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n"); + LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); return SCE_KERNEL_ERROR_EINVAL; } } - LOG_INFO_IF(log_file_memory, "len = {:#x}\n", len); - LOG_INFO_IF(log_file_memory, "prot = {:#x}\n", prot); - LOG_INFO_IF(log_file_memory, "flags = {:#x}\n", flags); - LOG_INFO_IF(log_file_memory, "directMemoryStart = {:#x}\n", directMemoryStart); - LOG_INFO_IF(log_file_memory, "alignment = {:#x}\n", alignment); - VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess; GPU::MemoryMode gpu_mode = GPU::MemoryMode::NoAccess; @@ -112,7 +91,7 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl gpu_mode = GPU::MemoryMode::ReadWrite; break; default: - BREAKPOINT(); + UNREACHABLE(); } auto in_addr = reinterpret_cast(*addr); @@ -121,8 +100,7 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl if (flags == 0) { out_addr = VirtualMemory::memory_alloc_aligned(in_addr, len, cpu_mode, alignment); } - LOG_INFO_IF(log_file_memory, "in_addr = {:#x}\n", in_addr); - LOG_INFO_IF(log_file_memory, "out_addr = {:#x}\n", out_addr); + LOG_INFO(Kernel_Vmm, "in_addr = {:#x}, out_addr = {:#x}", in_addr, out_addr); *addr = reinterpret_cast(out_addr); // return out_addr to first functions parameter @@ -132,7 +110,7 @@ int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int fl auto* physical_memory = Common::Singleton::Instance(); if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode, gpu_mode)) { - BREAKPOINT(); + UNREACHABLE(); } if (gpu_mode != GPU::MemoryMode::NoAccess) { diff --git a/src/core/hle/libraries/libc/libc.cpp b/src/core/hle/libraries/libc/libc.cpp index d3a90b22..127c3eb9 100644 --- a/src/core/hle/libraries/libc/libc.cpp +++ b/src/core/hle/libraries/libc/libc.cpp @@ -3,7 +3,7 @@ #include #include "common/debug.h" -#include "common/log.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/hle/libraries/libc/libc.h" #include "core/hle/libraries/libc/libc_cxa.h" @@ -49,15 +49,15 @@ void PS4_SYSV_ABI ps4___cxa_pure_virtual() { } static PS4_SYSV_ABI void ps4_init_env() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_INFO(Lib_LibC, "called"); } static PS4_SYSV_ABI void ps4_catchReturnFromMain(int status) { - LOG_INFO_IF(log_file_libc, "catchReturnFromMain returned ={}\n", status); + LOG_INFO(Lib_LibC, "returned = {}", status); } static PS4_SYSV_ABI void ps4__Assert() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_INFO(Lib_LibC, "called"); BREAKPOINT(); } @@ -66,18 +66,18 @@ PS4_SYSV_ABI void ps4__ZdlPv(void* ptr) { } PS4_SYSV_ABI void ps4__ZSt11_Xbad_allocv() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_INFO(Lib_LibC, "called"); BREAKPOINT(); } PS4_SYSV_ABI void ps4__ZSt14_Xlength_errorPKc() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_INFO(Lib_LibC, "called"); BREAKPOINT(); } PS4_SYSV_ABI void* ps4__Znwm(u64 count) { if (count == 0) { - LOG_ERROR_IF(log_file_libc, "_Znwm count ={}\n", count); + LOG_INFO(Lib_LibC, "_Znwm count ={}", count); BREAKPOINT(); } void* ptr = std::malloc(count); @@ -457,6 +457,7 @@ void libcSymbolsRegister(Loader::SymbolsResolver* sym) { LIB_FUNCTION("8zTFvBIAIN8", "libc", 1, "libc", 1, 1, ps4_memset); // stdio functions + LIB_FUNCTION("xeYO4u7uyJ0", "libc", 1, "libc", 1, 1, ps4_fopen); LIB_FUNCTION("hcuQgD53UxM", "libc", 1, "libc", 1, 1, ps4_printf); LIB_FUNCTION("Q2V+iqvjgC0", "libc", 1, "libc", 1, 1, ps4_vsnprintf); LIB_FUNCTION("YQ0navp+YIc", "libc", 1, "libc", 1, 1, ps4_puts); diff --git a/src/core/hle/libraries/libc/libc_cxa.cpp b/src/core/hle/libraries/libc/libc_cxa.cpp index 6d5dc7f8..e1e693ae 100644 --- a/src/core/hle/libraries/libc/libc_cxa.cpp +++ b/src/core/hle/libraries/libc/libc_cxa.cpp @@ -1,8 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/logging/log.h" #include "core/hle/libraries/libc/libc_cxa.h" // adapted from @@ -10,8 +9,6 @@ namespace Core::Libraries::LibC { -constexpr bool log_file_cxa = true; // disable it to disable logging - // This file implements the __cxa_guard_* functions as defined at: // http://www.codesourcery.com/public/cxx-abi/abi.html // @@ -103,8 +100,7 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) { int result = ::pthread_mutex_lock(guard_mutex()); if (result != 0) { - LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_lock failed with {}\n", - result); + LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result); } // At this point all other threads will block in __cxa_guard_acquire() @@ -112,8 +108,7 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) { if (initializerHasRun(guard_object)) { int result = ::pthread_mutex_unlock(guard_mutex()); if (result != 0) { - LOG_TRACE_IF(log_file_cxa, - "__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n", result); + LOG_ERROR(Lib_LibC, "pthread_mutex_lock failed with {}", result); } return 0; } @@ -123,8 +118,8 @@ int PS4_SYSV_ABI ps4___cxa_guard_acquire(u64* guard_object) { // But if the same thread can call __cxa_guard_acquire() on the // *same* guard object again, we call abort(); if (inUse(guard_object)) { - LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): initializer for function local static " - "variable called enclosing function\n"); + LOG_ERROR(Lib_LibC, + "initializer for function local static variable called enclosing function"); } // mark this guard object as being in use @@ -146,8 +141,7 @@ void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) { // release global mutex int result = ::pthread_mutex_unlock(guard_mutex()); if (result != 0) { - LOG_TRACE_IF(log_file_cxa, "__cxa_guard_acquire(): pthread_mutex_unlock failed with {}\n", - result); + LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result); } } @@ -157,8 +151,7 @@ void PS4_SYSV_ABI ps4___cxa_guard_release(u64* guard_object) { void PS4_SYSV_ABI ps4___cxa_guard_abort(u64* guard_object) { int result = ::pthread_mutex_unlock(guard_mutex()); if (result != 0) { - LOG_TRACE_IF(log_file_cxa, "__cxa_guard_abort(): pthread_mutex_unlock failed with {}\n", - result); + LOG_ERROR(Lib_LibC, "pthread_mutex_unlock failed with {}", result); } // now reset state, so possible to try to initialize again diff --git a/src/core/hle/libraries/libc/libc_stdio.cpp b/src/core/hle/libraries/libc/libc_stdio.cpp index 72c14e3d..67568e29 100644 --- a/src/core/hle/libraries/libc/libc_stdio.cpp +++ b/src/core/hle/libraries/libc/libc_stdio.cpp @@ -1,13 +1,17 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/singleton.h" +#include "core/file_sys/fs.h" #include "core/hle/libraries/libc/libc_stdio.h" namespace Core::Libraries::LibC { -constexpr bool log_file_libc = true; // disable it to disable logging +std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) { + auto* mnt = Common::Singleton::Instance(); + return std::fopen(mnt->GetHostFile(filename).c_str(), mode); +} int PS4_SYSV_ABI ps4_printf(VA_ARGS) { VA_CTX(ctx); @@ -20,8 +24,8 @@ int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) { VA_CTX(ctx); return printf_ctx(&ctx); } - LOG_ERROR_IF(log_file_libc, "libc:Unimplemented fprintf case\n"); - BREAKPOINT(); + + UNREACHABLE_MSG("Unimplemented fprintf case"); return 0; } diff --git a/src/core/hle/libraries/libc/libc_stdio.h b/src/core/hle/libraries/libc/libc_stdio.h index f4308213..c2911f36 100644 --- a/src/core/hle/libraries/libc/libc_stdio.h +++ b/src/core/hle/libraries/libc/libc_stdio.h @@ -8,6 +8,7 @@ namespace Core::Libraries::LibC { +std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode); int PS4_SYSV_ABI ps4_printf(VA_ARGS); int PS4_SYSV_ABI ps4_vsnprintf(char* s, size_t n, const char* format, VaList* arg); int PS4_SYSV_ABI ps4_puts(const char* s); diff --git a/src/core/hle/libraries/libc/libc_stdlib.cpp b/src/core/hle/libraries/libc/libc_stdlib.cpp index f055ae58..0ec3de08 100644 --- a/src/core/hle/libraries/libc/libc_stdlib.cpp +++ b/src/core/hle/libraries/libc/libc_stdlib.cpp @@ -2,24 +2,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" #include "core/hle/libraries/libc/libc_stdlib.h" namespace Core::Libraries::LibC { -constexpr bool log_file_libc = true; // disable it to disable logging - void PS4_SYSV_ABI ps4_exit(int code) { std::exit(code); } int PS4_SYSV_ABI ps4_atexit(void (*func)()) { int rt = std::atexit(func); - if (rt != 0) { - LOG_ERROR_IF(log_file_libc, "atexit returned {}\n", rt); - BREAKPOINT(); - } + ASSERT_MSG(rt == 0, "atexit returned {}", rt); return rt; } diff --git a/src/core/hle/libraries/libc/printf.h b/src/core/hle/libraries/libc/printf.h index e2560879..8bf98ada 100644 --- a/src/core/hle/libraries/libc/printf.h +++ b/src/core/hle/libraries/libc/printf.h @@ -59,6 +59,7 @@ #include #include #include +#include #include #include "va_ctx.h" diff --git a/src/core/hle/libraries/libkernel/file_system.cpp b/src/core/hle/libraries/libkernel/file_system.cpp index d164274f..6d4c6162 100644 --- a/src/core/hle/libraries/libkernel/file_system.cpp +++ b/src/core/hle/libraries/libkernel/file_system.cpp @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/file_sys/fs.h" #include "core/hle/error_codes.h" @@ -11,45 +11,41 @@ namespace Core::Libraries::LibKernel { -constexpr bool log_file_fs = true; // disable it to disable logging - int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { - LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {:#x} mode = {:#x}\n", path, flags, - mode); + LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {:#x}", path, flags, mode); auto* h = Common::Singleton::Instance(); auto* mnt = Common::Singleton::Instance(); // only open files support! - u32 handle = h->createHandle(); - auto* file = h->getFile(handle); + u32 handle = h->CreateHandle(); + auto* file = h->GetFile(handle); file->m_guest_name = path; - file->m_host_name = mnt->getHostFile(file->m_guest_name); + file->m_host_name = mnt->GetHostFile(file->m_guest_name); - bool result = file->f.open(file->m_host_name); - if (!result) { - h->deleteHandle(handle); + file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read); + if (!file->f.IsOpen()) { + h->DeleteHandle(handle); return SCE_KERNEL_ERROR_EACCES; } - file->isOpened = true; + file->is_opened = true; return handle; } int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { - LOG_INFO_IF(log_file_fs, "posix open redirect to sceKernelOpen\n"); + LOG_INFO(Kernel_Fs, "posix open redirect to sceKernelOpen\n"); int result = sceKernelOpen(path, flags, mode); - if (result < 0) { - BREAKPOINT(); // posix calls different only for their return values - } + // Posix calls different only for their return values + ASSERT(result >= 0); return result; } size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) { auto* h = Common::Singleton::Instance(); - auto* file = h->getFile(d); + auto* file = h->GetFile(d); size_t total_read = 0; file->m_mutex.lock(); for (int i = 0; i < iovcnt; i++) { - total_read += file->f.readBytes(iov[i].iov_base, iov[i].iov_len).second; + total_read += file->f.ReadRaw(iov[i].iov_base, iov[i].iov_len); } file->m_mutex.unlock(); return total_read; diff --git a/src/core/hle/libraries/libkernel/file_system.h b/src/core/hle/libraries/libkernel/file_system.h index 1648904e..a6319da5 100644 --- a/src/core/hle/libraries/libkernel/file_system.h +++ b/src/core/hle/libraries/libkernel/file_system.h @@ -13,7 +13,7 @@ namespace Core::Libraries::LibKernel { struct SceKernelIovec { void* iov_base; - size_t iov_len; + std::size_t iov_len; }; int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, /* SceKernelMode*/ u16 mode); diff --git a/src/core/hle/libraries/libkernel/libkernel.cpp b/src/core/hle/libraries/libkernel/libkernel.cpp index 1e244d2b..8fbeb2d0 100644 --- a/src/core/hle/libraries/libkernel/libkernel.cpp +++ b/src/core/hle/libraries/libkernel/libkernel.cpp @@ -1,10 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" -#include "common/singleton.h" -#include "core/hle/kernel/Objects/physical_memory.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "core/hle/kernel/cpu_management.h" #include "core/hle/kernel/event_queues.h" #include "core/hle/kernel/memory_management.h" @@ -24,21 +22,19 @@ namespace Core::Libraries::LibKernel { -constexpr bool log_libkernel_file = true; // disable it to disable logging - static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return int32_t PS4_SYSV_ABI sceKernelReleaseDirectMemory(off_t start, size_t len) { - BREAKPOINT(); + UNREACHABLE(); return 0; } static PS4_SYSV_ABI void stack_chk_fail() { - BREAKPOINT(); + UNREACHABLE(); } int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { - BREAKPOINT(); + UNREACHABLE(); } void PS4_SYSV_ABI sceKernelUsleep(unsigned int microseconds) { @@ -71,10 +67,9 @@ int* PS4_SYSV_ABI __Error() { int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, off_t offset, void** res) { #ifdef _WIN64 - PRINT_FUNCTION_NAME(); - if (prot > 3) // READ,WRITE or bitwise READ | WRITE supported - { - LOG_ERROR_IF(log_libkernel_file, "sceKernelMmap prot ={} not supported\n", prot); + LOG_INFO(Kernel_Vmm, "called"); + if (prot > 3) { + LOG_ERROR(Kernel_Vmm, "prot = {} not supported", prot); } DWORD flProtect; if (prot & PROT_WRITE) { @@ -114,13 +109,11 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, PS4_SYSV_ABI void* posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) { void* ptr; - LOG_INFO_IF(log_libkernel_file, "posix mmap redirect to sceKernelMmap\n"); + LOG_INFO(Kernel_Vmm, "posix mmap redirect to sceKernelMmap\n"); // posix call the difference is that there is a different behaviour when it doesn't return 0 or // SCE_OK int result = sceKernelMmap(addr, len, prot, flags, fd, offset, &ptr); - if (result != 0) { - BREAKPOINT(); - } + ASSERT(result == 0); return ptr; } diff --git a/src/core/hle/libraries/libkernel/thread_management.cpp b/src/core/hle/libraries/libkernel/thread_management.cpp index 782351cb..343a64a8 100644 --- a/src/core/hle/libraries/libkernel/thread_management.cpp +++ b/src/core/hle/libraries/libkernel/thread_management.cpp @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "core/hle/error_codes.h" #include "core/hle/libraries/libkernel/thread_management.h" #include "core/hle/libraries/libs.h" @@ -12,8 +12,6 @@ namespace Core::Libraries::LibKernel { thread_local ScePthread g_pthread_self{}; PThreadCxt* g_pthread_cxt = nullptr; -constexpr bool log_pthread_file = true; // disable it to disable logging - void init_pthreads() { g_pthread_cxt = new PThreadCxt{}; // default mutex init @@ -73,9 +71,7 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst pstate = PTHREAD_CREATE_DETACHED; break; default: - LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetdetachstate invalid detachstate: {}\n", - detachstate); - std::exit(0); + UNREACHABLE_MSG("Invalid detachstate: {}", detachstate); } // int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work @@ -101,9 +97,7 @@ int PS4_SYSV_ABI scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inherit pinherit_sched = PTHREAD_INHERIT_SCHED; break; default: - LOG_TRACE_IF(log_pthread_file, "scePthreadAttrSetinheritsched invalid inheritSched: {}\n", - inheritSched); - std::exit(0); + UNREACHABLE_MSG("Invalid inheritSched: {}", inheritSched); } int result = pthread_attr_setinheritsched(&(*attr)->pth_attr, pinherit_sched); @@ -138,9 +132,7 @@ int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) int ppolicy = SCHED_OTHER; // winpthreads only supports SCHED_OTHER if (policy != SCHED_OTHER) { - LOG_TRACE_IF(log_pthread_file, - "scePthreadAttrSetschedpolicy policy={} not supported by winpthreads\n", - policy); + LOG_ERROR(Kernel_Pthread, "policy={} not supported by winpthreads\n", policy); } (*attr)->policy = policy; @@ -154,7 +146,7 @@ ScePthread PS4_SYSV_ABI scePthreadSelf() { int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, const /*SceKernelCpumask*/ u64 mask) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); if (pattr == nullptr || *pattr == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -166,7 +158,7 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr, } int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpumask*/ u64 mask) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); if (thread == nullptr) { return SCE_KERNEL_ERROR_ESRCH; @@ -178,12 +170,10 @@ int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpuma } int PS4_SYSV_ABI scePthreadCreate(ScePthread* thread, const ScePthreadAttr* attr, pthreadEntryFunc start_routine, void* arg, const char* name) { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "(STUBBED) called"); return 0; } -/**** - * Mutex calls - */ + void* createMutex(void* addr) { if (addr == nullptr || *static_cast(addr) != nullptr) { return addr; @@ -197,7 +187,7 @@ void* createMutex(void* addr) { int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr, const char* name) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); if (mutex == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } @@ -215,7 +205,7 @@ int PS4_SYSV_ABI scePthreadMutexInit(ScePthreadMutex* mutex, const ScePthreadMut int result = pthread_mutex_init(&(*mutex)->pth_mutex, &(*attr)->pth_mutex_attr); if (name != nullptr) { - LOG_INFO_IF(log_pthread_file, "mutex_init name={},result={}\n", name, result); + LOG_INFO(Kernel_Pthread, "name={}, result={}", name, result); } switch (result) { @@ -264,8 +254,7 @@ int PS4_SYSV_ABI scePthreadMutexattrSettype(ScePthreadMutexattr* attr, int type) ptype = PTHREAD_MUTEX_NORMAL; break; default: - LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSettype invalid type: {}\n", type); - std::exit(0); + UNREACHABLE_MSG("Invalid type: {}", type); } int result = pthread_mutexattr_settype(&(*attr)->pth_mutex_attr, ptype); @@ -286,9 +275,7 @@ int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int p pprotocol = PTHREAD_PRIO_PROTECT; break; default: - LOG_TRACE_IF(log_pthread_file, "scePthreadMutexattrSetprotocol invalid protocol: {}\n", - protocol); - std::exit(0); + UNREACHABLE_MSG("Invalid protocol: {}", protocol); } int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that @@ -298,7 +285,7 @@ int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int p return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL; } int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); mutex = static_cast(createMutex(mutex)); if (mutex == nullptr) { @@ -306,8 +293,7 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) { } int result = pthread_mutex_lock(&(*mutex)->pth_mutex); - LOG_INFO_IF(log_pthread_file, "scePthreadMutexLock name={} result={}\n", (*mutex)->name, - result); + LOG_INFO(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result); switch (result) { case 0: return SCE_OK; @@ -322,15 +308,14 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) { } } int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); mutex = static_cast(createMutex(mutex)); if (mutex == nullptr) { return SCE_KERNEL_ERROR_EINVAL; } int result = pthread_mutex_unlock(&(*mutex)->pth_mutex); - LOG_INFO_IF(log_pthread_file, "scePthreadMutexUnlock name={} result={}\n", (*mutex)->name, - result); + LOG_INFO(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result); switch (result) { case 0: return SCE_OK; @@ -344,9 +329,6 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) { } } -/**** - * Cond calls - */ void* createCond(void* addr) { if (addr == nullptr || *static_cast(addr) != nullptr) { return addr; @@ -379,7 +361,7 @@ int PS4_SYSV_ABI scePthreadCondInit(ScePthreadCond* cond, const ScePthreadCondat int result = pthread_cond_init(&(*cond)->cond, &(*attr)->cond_attr); if (name != nullptr) { - LOG_INFO_IF(log_pthread_file, "cond init name={},result={}\n", (*cond)->name, result); + LOG_INFO(Kernel_Pthread, "name={}, result={}", (*cond)->name, result); } switch (result) { @@ -412,7 +394,7 @@ int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr) { } int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) { - PRINT_FUNCTION_NAME(); + LOG_INFO(Kernel_Pthread, "called"); cond = static_cast(createCond(cond)); if (cond == nullptr) { @@ -421,15 +403,13 @@ int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) { int result = pthread_cond_broadcast(&(*cond)->cond); - LOG_INFO_IF(log_pthread_file, "cond broadcast name={},result={}\n", (*cond)->name, result); + LOG_INFO(Kernel_Pthread, "name={}, result={}", (*cond)->name, result); return (result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL); } -/**** - * Posix calls - */ + int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthreadMutexattr* attr) { - LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_init redirect to scePthreadMutexInit\n"); + LOG_INFO(Kernel_Pthread, "posix pthread_mutex_init redirect to scePthreadMutexInit"); int result = scePthreadMutexInit(mutex, attr, nullptr); if (result < 0) { int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP @@ -441,7 +421,7 @@ int PS4_SYSV_ABI posix_pthread_mutex_init(ScePthreadMutex* mutex, const ScePthre } int PS4_SYSV_ABI posix_pthread_mutex_lock(ScePthreadMutex* mutex) { - LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_lock redirect to scePthreadMutexLock\n"); + LOG_INFO(Kernel_Pthread, "posix pthread_mutex_lock redirect to scePthreadMutexLock"); int result = scePthreadMutexLock(mutex); if (result < 0) { int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP @@ -453,7 +433,7 @@ int PS4_SYSV_ABI posix_pthread_mutex_lock(ScePthreadMutex* mutex) { } int PS4_SYSV_ABI posix_pthread_mutex_unlock(ScePthreadMutex* mutex) { - LOG_INFO_IF(log_pthread_file, "posix pthread_mutex_unlock redirect to scePthreadMutexUnlock\n"); + LOG_INFO(Kernel_Pthread, "posix pthread_mutex_unlock redirect to scePthreadMutexUnlock"); int result = scePthreadMutexUnlock(mutex); if (result < 0) { int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP @@ -465,8 +445,8 @@ int PS4_SYSV_ABI posix_pthread_mutex_unlock(ScePthreadMutex* mutex) { } int PS4_SYSV_ABI posix_pthread_cond_broadcast(ScePthreadCond* cond) { - LOG_INFO_IF(log_pthread_file, - "posix posix_pthread_cond_broadcast redirect to scePthreadCondBroadcast\n"); + LOG_INFO(Kernel_Pthread, + "posix posix_pthread_cond_broadcast redirect to scePthreadCondBroadcast"); int result = scePthreadCondBroadcast(cond); if (result != 0) { int rt = result > SCE_KERNEL_ERROR_UNKNOWN && result <= SCE_KERNEL_ERROR_ESTOP @@ -510,4 +490,4 @@ void pthreadSymbolsRegister(Loader::SymbolsResolver* sym) { LIB_FUNCTION("mkx2fVhNMsg", "libkernel", 1, "libkernel", 1, 1, posix_pthread_cond_broadcast); } -} // namespace Core::Libraries::LibKernel \ No newline at end of file +} // namespace Core::Libraries::LibKernel diff --git a/src/core/hle/libraries/libpad/pad.cpp b/src/core/hle/libraries/libpad/pad.cpp index d9588b9e..b9bdd8ee 100644 --- a/src/core/hle/libraries/libpad/pad.cpp +++ b/src/core/hle/libraries/libpad/pad.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "Emulator/Host/controller.h" -#include "common/log.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/hle/error_codes.h" #include "core/hle/libraries/libpad/pad.h" @@ -10,15 +10,14 @@ namespace Core::Libraries::LibPad { -constexpr bool log_file_pad = true; // disable it to disable logging - int PS4_SYSV_ABI scePadInit() { + LOG_WARNING(Lib_Pad, "(STUBBED) called"); return SCE_OK; } -int PS4_SYSV_ABI scePadOpen(Core::Libraries::LibUserService::SceUserServiceUserId userId, s32 type, +int PS4_SYSV_ABI scePadOpen(Core::Libraries::LibUserService::SceUserServiceUserId user_id, s32 type, s32 index, const ScePadOpenParam* pParam) { - LOG_INFO_IF(log_file_pad, "scePadOpen userid = {} type = {} index = {}\n", userId, type, index); + LOG_INFO(Lib_Pad, "(STUBBED) called user_id = {} type = {} index = {}", user_id, type, index); return 1; // dummy } diff --git a/src/core/hle/libraries/libs.h b/src/core/hle/libraries/libs.h index a0f56283..56c90f13 100644 --- a/src/core/hle/libraries/libs.h +++ b/src/core/hle/libraries/libs.h @@ -34,15 +34,6 @@ sym->AddSymbol(sr, func); \ } -#define PRINT_FUNCTION_NAME() \ - { LOG_INFO_IF(true, "{}()\n", __func__); } - -#define PRINT_DUMMY_FUNCTION_NAME() \ - { LOG_WARN_IF(true, "dummy {}()\n", __func__); } - -#define PRINT_UNIMPLEMENTED_FUNCTION_NAME() \ - { LOG_ERROR_IF(true, "{}()\n", __func__); } - namespace Core::Libraries { void InitHLELibs(Loader::SymbolsResolver* sym); diff --git a/src/core/hle/libraries/libscegnmdriver/libscegnmdriver.cpp b/src/core/hle/libraries/libscegnmdriver/libscegnmdriver.cpp index 98aad084..9f24c280 100644 --- a/src/core/hle/libraries/libscegnmdriver/libscegnmdriver.cpp +++ b/src/core/hle/libraries/libscegnmdriver/libscegnmdriver.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/log.h" +#include "common/logging/log.h" #include "core/PS4/GPU/gpu_memory.h" #include "core/hle/libraries/libs.h" #include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h" @@ -10,12 +10,12 @@ namespace Core::Libraries::LibSceGnmDriver { int32_t sceGnmSubmitDone() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_WARNING(Lib_GnmDriver, "(STUBBED) called"); return 0; } void sceGnmFlushGarlic() { - PRINT_FUNCTION_NAME(); + LOG_WARNING(Lib_GnmDriver, "(STUBBED) called"); GPU::flushGarlic(Emu::getGraphicCtx()); } diff --git a/src/core/hle/libraries/libsystemservice/system_service.cpp b/src/core/hle/libraries/libsystemservice/system_service.cpp index dfffa3e3..b25be615 100644 --- a/src/core/hle/libraries/libsystemservice/system_service.cpp +++ b/src/core/hle/libraries/libsystemservice/system_service.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/log.h" +#include "common/logging/log.h" #include "core/hle/error_codes.h" #include "core/hle/libraries/libs.h" #include "core/hle/libraries/libsystemservice/system_service.h" @@ -9,7 +9,7 @@ namespace Core::Libraries::LibSystemService { s32 PS4_SYSV_ABI sceSystemServiceHideSplashScreen() { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_WARNING(Lib_SystemService, "(STUBBED) called"); return SCE_OK; } diff --git a/src/core/hle/libraries/libuserservice/libuserservice.cpp b/src/core/hle/libraries/libuserservice/libuserservice.cpp index 55bf2355..0fe3905a 100644 --- a/src/core/hle/libraries/libuserservice/libuserservice.cpp +++ b/src/core/hle/libraries/libuserservice/libuserservice.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/log.h" +#include "common/logging/log.h" #include "core/hle/error_codes.h" #include "core/hle/libraries/libs.h" #include "core/hle/libraries/libuserservice/libuserservice.h" @@ -9,12 +9,12 @@ namespace Core::Libraries::LibUserService { s32 PS4_SYSV_ABI sceUserServiceInitialize(const SceUserServiceInitializeParams* initParams) { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_WARNING(Lib_UserService, "(STUBBED) called"); return SCE_OK; } s32 PS4_SYSV_ABI sceUserServiceGetLoginUserIdList(SceUserServiceLoginUserIdList* userIdList) { - PRINT_DUMMY_FUNCTION_NAME(); + LOG_WARNING(Lib_UserService, "(STUBBED) called"); userIdList->user_id[0] = 1; userIdList->user_id[1] = -1; userIdList->user_id[2] = -1; diff --git a/src/core/libraries/libscegnmdriver.cpp b/src/core/libraries/libscegnmdriver.cpp index 4b389ab3..3cb81292 100644 --- a/src/core/libraries/libscegnmdriver.cpp +++ b/src/core/libraries/libscegnmdriver.cpp @@ -2,1264 +2,1264 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Generated By moduleGenerator -#include "common/log.h" +#include "common/logging/log.h" #include "error_codes.h" #include "libscegnmdriver.h" namespace Libraries::GnmDriver { int PS4_SYSV_ABI sceGnmAddEqEvent() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmAreSubmitsAllowed() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmBeginWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmComputeWaitOnAddress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmComputeWaitSemaphore() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmCreateWorkloadStream() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerGetAddressWatch() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerHaltWavefront() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerReadGds() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerReadSqIndirectRegister() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerResumeWavefront() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerResumeWavefrontCreation() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerSetAddressWatch() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerWriteGds() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebuggerWriteSqIndirectRegister() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebugHardwareStatus() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDeleteEqEvent() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDestroyWorkloadStream() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDingDong() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDingDongForWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDisableMipStatsReport() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDispatchDirect() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDispatchIndirect() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDispatchIndirectOnMec() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDispatchInitDefaultHardwareState() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndex() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexAuto() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexIndirect() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndexOffset() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndirect() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawIndirectMulti() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState175() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState200() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitDefaultHardwareState350() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitToDefaultContextState() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitToDefaultContextState400() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawOpaqueAuto() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverCaptureInProgress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterface() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForGpuDebugger() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForGpuException() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForHDRScopes() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForReplay() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForResourceRegistration() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalRetrieveGnmInterfaceForValidation() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverInternalVirtualQuery() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverTraceInProgress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDriverTriggerCapture() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmEndWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmFindResourcesPublic() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmFlushGarlic() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetCoredumpAddress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetCoredumpMode() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetCoredumpProtectionFaultTimestamp() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetDbgGcHandle() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetDebugTimestamp() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetEqEventType() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetEqTimeStamp() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetGpuBlockStatus() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetGpuInfoStatus() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetLastWaitedAddress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetNumTcaUnits() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetOffChipTessellationBufferSize() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetOwnerName() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetPhysicalCounterFromVirtualized() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetProtectionFaultTimeStamp() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceBaseAddressAndSizeInBytes() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceName() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceShaderGuid() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceType() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceUserData() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetShaderProgramBaseAddress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetShaderStatus() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetTheTessellationFactorRingBufferBaseAddress() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGpuPaDebugEnter() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGpuPaDebugLeave() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertDingDongMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertPopMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertPushColorMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertPushMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertSetColorMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertSetMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertThreadTraceMarker() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmInsertWaitFlipDone() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmIsCoredumpValid() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmIsUserPaEnabled() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmLogicalCuIndexToPhysicalCuIndex() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmLogicalCuMaskToPhysicalCuMask() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmLogicalTcaUnitToPhysical() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmMapComputeQueue() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmMapComputeQueueWithPriority() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmPaDisableFlipCallbacks() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmPaEnableFlipCallbacks() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmPaHeartbeat() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmQueryResourceRegistrationUserMemoryRequirements() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRaiseUserExceptionEvent() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRegisterGdsResource() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRegisterGnmLiveCallbackConfig() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRegisterOwner() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRegisterResource() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRequestMipStatsReportAndReset() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmResetVgtControl() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaClose() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaConstFill() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaCopyLinear() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaCopyTiled() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaCopyWindow() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaFlush() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaGetMinCmdSize() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSdmaOpen() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetCsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetCsShaderWithModifier() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetEmbeddedPsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetEmbeddedVsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetEsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetGsRingSizes() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetGsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetHsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetLsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetPsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetPsShader350() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetResourceRegistrationUserMemory() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetResourceUserData() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetSpiEnableSqCounters() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetSpiEnableSqCountersForUnitInstance() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetupMipStatsReport() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetVgtControl() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetVsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetWaveLimitMultiplier() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSetWaveLimitMultipliers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmEndSpm() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmInit() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmInit2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetDelay() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetMuxRam() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetMuxRam2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetSelectCounter() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetSpmSelects() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmSetSpmSelects2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSpmStartSpm() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttFini() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttFinishTrace() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetBcInfo() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetGpuClocks() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetHiWater() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetStatus() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetTraceCounter() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetTraceWptr() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetWrapCounts() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetWrapCounts2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttGetWritebackLabels() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttInit() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSelectMode() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSelectTarget() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSelectTokens() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetCuPerfMask() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetDceEventWrite() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetHiWater() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetTraceBuffer2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetTraceBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetUserData() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSetUserdataTimer() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttStartTrace() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttStopTrace() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSwitchTraceBuffer() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttSwitchTraceBuffer2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSqttWaitForEvent() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffersForWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSubmitCommandBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSubmitCommandBuffersForWorkload() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmSubmitDone() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUnmapComputeQueue() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUnregisterAllResourcesForOwner() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUnregisterOwnerAndResources() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUnregisterResource() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUpdateGsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUpdateHsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUpdatePsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUpdatePsShader350() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmUpdateVsShader() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateCommandBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateDisableDiagnostics2() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateDispatchCommandBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateDrawCommandBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateGetDiagnosticInfo() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateGetDiagnostics() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateGetVersion() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateOnSubmitEnabled() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidateResetState() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmValidationRegisterMemoryCheckCallback() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceRazorCaptureCommandBuffersOnlyImmediate() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceRazorCaptureCommandBuffersOnlySinceLastFlip() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceRazorCaptureImmediate() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceRazorCaptureSinceLastFlip() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceRazorIsLoaded() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_063D065A2D6359C3() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_0CABACAFB258429D() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_150CF336FC2E99A3() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_17CA687F9EE52D49() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_1870B89F759C6B45() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_26F9029EF68A955E() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_301E3DBBAB092DB0() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_30BAFE172AF17FEF() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_3E6A3E8203D95317() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_40FEEF0C6534C434() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_416B9079DE4CBACE() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_4774D83BB4DDBF9A() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_50678F1CCEEB9A00() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_54A2EC5FA4C62413() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_5A9C52C83138AE6B() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_5D22193A31EA1142() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_725A36DEBB60948D() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_8021A502FA61B9BB() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_9D002FE0FA40F0E6() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_9D297F36A7028B71() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_A2D7EC7A7BCF79B3() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_AA12A3CB8990854A() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_ADC8DDC005020BC6() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_B0A8688B679CB42D() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_B489020B5157A5FF() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_BADE7B4C199140DD() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D1511B9DCFFB3DD9() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D53446649B02E58E() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D8B6E8E28E1EF0A3() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D93D733A19DD7454() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_DE995443BC2A8317() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_DF6E9528150C23FF() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_ECB4C6BA41FE3350() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebugModuleReset() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDebugReset() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_C4C328B7CF3B4171() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitToDefaultContextStateInternalCommand() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmDrawInitToDefaultContextStateInternalSize() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmFindResources() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmGetResourceRegistrationBuffers() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceGnmRegisterOwnerForSystem() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_1C43886B16EE5530() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_81037019ECCD0E01() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_BFB41C057478F0BF() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_E51D44DB8151238C() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_F916890425496553() { - PRINT_UNIMPLEMENTED_FUNCTION_NAME(); + LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); return ORBIS_OK; } @@ -1735,4 +1735,4 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { Func_BADE7B4C199140DD); }; -} // namespace Libraries::GnmDriver \ No newline at end of file +} // namespace Libraries::GnmDriver diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 7bf7691e..0cbeb4c7 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -2,31 +2,29 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include -#include "common/log.h" +#include "common/logging/log.h" #include "common/string_util.h" #include "core/aerolib/aerolib.h" #include "core/aerolib/stubs.h" #include "core/hle/libraries/libkernel/thread_management.h" #include "core/linker.h" +#include "core/tls.h" #include "core/virtual_memory.h" namespace Core { -constexpr bool debug_loader = true; +static constexpr u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET; -static u64 g_load_addr = SYSTEM_RESERVED + CODE_BASE_OFFSET; - -static u64 get_aligned_size(const elf_program_header& phdr) { +static u64 GetAlignedSize(const elf_program_header& phdr) { return (phdr.p_align != 0 ? (phdr.p_memsz + (phdr.p_align - 1)) & ~(phdr.p_align - 1) : phdr.p_memsz); } -static u64 calculate_base_size(const elf_header& ehdr, std::span phdr) { +static u64 CalculateBaseSize(const elf_header& ehdr, std::span phdr) { u64 base_size = 0; for (u16 i = 0; i < ehdr.e_phnum; i++) { if (phdr[i].p_memsz != 0 && (phdr[i].p_type == PT_LOAD || phdr[i].p_type == PT_SCE_RELRO)) { - u64 last_addr = phdr[i].p_vaddr + get_aligned_size(phdr[i]); + u64 last_addr = phdr[i].p_vaddr + GetAlignedSize(phdr[i]); if (last_addr > base_size) { base_size = last_addr; } @@ -35,7 +33,7 @@ static u64 calculate_base_size(const elf_header& ehdr, std::span(); + m->elf.Open(elf_name); + + if (m->elf.IsElfFile()) { + LoadModuleToMemory(m.get()); + LoadDynamicInfo(m.get()); + LoadSymbols(m.get()); + Relocate(m.get()); } else { m_modules.pop_back(); return nullptr; // It is not a valid elf file //TODO check it why! } - return &m; + return m.get(); } -Module* Linker::FindModule(/*u32 id*/) { +Module* Linker::FindModule(u32 id) { // TODO atm we only have 1 module so we don't need to iterate on vector if (m_modules.empty()) [[unlikely]] { return nullptr; } - return &m_modules[0]; -} - -struct TLSPattern { - uint8_t pattern[5]; - uint8_t pattern_size; - uint8_t imm_size; - uint8_t target_reg; -}; - -constexpr TLSPattern tls_patterns[] = { - {{0x64, 0x48, 0xA1}, - 3, - 8, - 0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm] - - {{0x64, 0x48, 0x8B, 0x4, 0x25}, - 5, - 4, - 0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0] - {{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx - {{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx - {{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx - {{0x64, 0x48, 0x8B, 0x24, 0x25}, 5, 4, 4}, // rsp - {{0x64, 0x48, 0x8B, 0x2C, 0x25}, 5, 4, 5}, // rbp - {{0x64, 0x48, 0x8B, 0x34, 0x25}, 5, 4, 6}, // rsi - {{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi - {{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8 - {{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9 - {{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10}, // r10 - {{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11}, // r11 - {{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12}, // r12 - {{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13}, // r13 - {{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14}, // r14 - {{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15}, // r15 -}; - -void PatchTLS(u64 segment_addr, u64 segment_size) { - uint8_t* code = (uint8_t*)segment_addr; - auto remaining_size = segment_size; - - while (remaining_size) { - for (auto& tls_pattern : tls_patterns) { - auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size; - if (remaining_size >= total_size) { - if (memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) == 0) { - if (tls_pattern.imm_size == 4) - printf("PATTERN32 FOUND @ %p, reg: %d offset: %X\n", code, - tls_pattern.target_reg, - *(uint32_t*)(code + tls_pattern.pattern_size)); - else - printf("PATTERN64 FOUND @ %p, reg: %d offset: %lX\n", code, - tls_pattern.target_reg, - *(uint64_t*)(code + tls_pattern.pattern_size)); - code[0] = 0xcd; - code[1] = 0x80 + tls_pattern.target_reg; - code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4); - code += total_size - 1; - remaining_size -= total_size - 1; - break; - } - } - } - code++; - remaining_size--; - } + return m_modules[0].get(); } void Linker::LoadModuleToMemory(Module* m) { @@ -155,18 +93,18 @@ void Linker::LoadModuleToMemory(Module* m) { const auto elf_header = m->elf.GetElfHeader(); const auto elf_pheader = m->elf.GetProgramHeader(); - u64 base_size = calculate_base_size(elf_header, elf_pheader); + u64 base_size = CalculateBaseSize(elf_header, elf_pheader); m->aligned_base_size = (base_size & ~(static_cast(0x1000) - 1)) + 0x1000; // align base size to 0x1000 block size (TODO is that the default // block size or it can be changed? - m->base_virtual_addr = VirtualMemory::memory_alloc(g_load_addr, m->aligned_base_size, + m->base_virtual_addr = VirtualMemory::memory_alloc(LoadAddress, m->aligned_base_size, VirtualMemory::MemoryMode::ExecuteReadWrite); - LOG_INFO_IF(debug_loader, "====Load Module to Memory ========\n"); - LOG_INFO_IF(debug_loader, "base_virtual_addr ......: {:#018x}\n", m->base_virtual_addr); - LOG_INFO_IF(debug_loader, "base_size ..............: {:#018x}\n", base_size); - LOG_INFO_IF(debug_loader, "aligned_base_size ......: {:#018x}\n", m->aligned_base_size); + LOG_INFO(Core_Linker, "====Load Module to Memory ========"); + LOG_INFO(Core_Linker, "base_virtual_addr ......: {:#018x}", m->base_virtual_addr); + LOG_INFO(Core_Linker, "base_size ..............: {:#018x}", base_size); + LOG_INFO(Core_Linker, "aligned_base_size ......: {:#018x}", m->aligned_base_size); for (u16 i = 0; i < elf_header.e_phnum; i++) { switch (elf_pheader[i].p_type) { @@ -175,14 +113,14 @@ void Linker::LoadModuleToMemory(Module* m) { if (elf_pheader[i].p_memsz != 0) { u64 segment_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr; u64 segment_file_size = elf_pheader[i].p_filesz; - u64 segment_memory_size = get_aligned_size(elf_pheader[i]); + u64 segment_memory_size = GetAlignedSize(elf_pheader[i]); auto segment_mode = m->elf.ElfPheaderFlagsStr(elf_pheader[i].p_flags); - LOG_INFO_IF(debug_loader, "program header = [{}] type = {}\n", i, - m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); - LOG_INFO_IF(debug_loader, "segment_addr ..........: {:#018x}\n", segment_addr); - LOG_INFO_IF(debug_loader, "segment_file_size .....: {}\n", segment_file_size); - LOG_INFO_IF(debug_loader, "segment_memory_size ...: {}\n", segment_memory_size); - LOG_INFO_IF(debug_loader, "segment_mode ..........: {}\n", segment_mode); + LOG_INFO(Core_Linker, "program header = [{}] type = {}", i, + m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); + LOG_INFO(Core_Linker, "segment_addr ..........: {:#018x}", segment_addr); + LOG_INFO(Core_Linker, "segment_file_size .....: {}", segment_file_size); + LOG_INFO(Core_Linker, "segment_memory_size ...: {}", segment_memory_size); + LOG_INFO(Core_Linker, "segment_mode ..........: {}", segment_mode); m->elf.LoadSegment(segment_addr, elf_pheader[i].p_offset, segment_file_size); @@ -190,8 +128,8 @@ void Linker::LoadModuleToMemory(Module* m) { PatchTLS(segment_addr, segment_file_size); } } else { - LOG_ERROR_IF(debug_loader, "p_memsz==0 in type {}\n", - m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); + LOG_ERROR(Core_Linker, "p_memsz==0 in type {}", + m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); } break; case PT_DYNAMIC: @@ -200,8 +138,8 @@ void Linker::LoadModuleToMemory(Module* m) { m->elf.LoadSegment(reinterpret_cast(m->m_dynamic.data()), elf_pheader[i].p_offset, elf_pheader[i].p_filesz); } else { - LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n", - m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); + LOG_ERROR(Core_Linker, "p_filesz==0 in type {}", + m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); } break; case PT_SCE_DYNLIBDATA: @@ -210,23 +148,23 @@ void Linker::LoadModuleToMemory(Module* m) { m->elf.LoadSegment(reinterpret_cast(m->m_dynamic_data.data()), elf_pheader[i].p_offset, elf_pheader[i].p_filesz); } else { - LOG_ERROR_IF(debug_loader, "p_filesz==0 in type {}\n", - m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); + LOG_ERROR(Core_Linker, "p_filesz==0 in type {}", + m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); } break; case PT_TLS: m->tls.image_virtual_addr = elf_pheader[i].p_vaddr + m->base_virtual_addr; - m->tls.image_size = get_aligned_size(elf_pheader[i]); - LOG_INFO_IF(debug_loader, "tls virtual address ={:#x}\n", m->tls.image_virtual_addr); - LOG_INFO_IF(debug_loader, "tls image size ={}\n", m->tls.image_size); + m->tls.image_size = GetAlignedSize(elf_pheader[i]); + LOG_INFO(Core_Linker, "tls virtual address ={:#x}", m->tls.image_virtual_addr); + LOG_INFO(Core_Linker, "tls image size ={}", m->tls.image_size); break; default: - LOG_ERROR_IF(debug_loader, "Unimplemented type {}\n", - m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); + LOG_ERROR(Core_Linker, "Unimplemented type {}", + m->elf.ElfPheaderTypeStr(elf_pheader[i].p_type)); } } - LOG_INFO_IF(debug_loader, "program entry addr ..........: {:#018x}\n", - m->elf.GetElfEntry() + m->base_virtual_addr); + LOG_INFO(Core_Linker, "program entry addr ..........: {:#018x}", + m->elf.GetElfEntry() + m->base_virtual_addr); } void Linker::LoadDynamicInfo(Module* m) { @@ -273,7 +211,7 @@ void Linker::LoadDynamicInfo(Module* m) { case DT_SCE_PLTREL: // The type of relocations in the relocation table. Should be DT_RELA m->dynamic_info.jmp_relocation_type = dyn->d_un.d_val; if (m->dynamic_info.jmp_relocation_type != DT_RELA) { - LOG_WARN_IF(debug_loader, "DT_SCE_PLTREL is NOT DT_RELA should check!"); + LOG_WARNING(Core_Linker, "DT_SCE_PLTREL is NOT DT_RELA should check!"); } break; case DT_SCE_RELA: // Offset of the relocation table. @@ -288,7 +226,7 @@ void Linker::LoadDynamicInfo(Module* m) { if (m->dynamic_info.relocation_table_entries_size != 0x18) // this value should always be 0x18 { - LOG_WARN_IF(debug_loader, "DT_SCE_RELAENT is NOT 0x18 should check!"); + LOG_WARNING(Core_Linker, "DT_SCE_RELAENT is NOT 0x18 should check!"); } break; case DT_INIT_ARRAY: // Address of the array of pointers to initialization functions @@ -314,7 +252,7 @@ void Linker::LoadDynamicInfo(Module* m) { if (m->dynamic_info.symbol_table_entries_size != 0x18) // this value should always be 0x18 { - LOG_WARN_IF(debug_loader, "DT_SCE_SYMENT is NOT 0x18 should check!"); + LOG_WARNING(Core_Linker, "DT_SCE_SYMENT is NOT 0x18 should check!"); } break; case DT_DEBUG: @@ -327,7 +265,7 @@ void Linker::LoadDynamicInfo(Module* m) { m->dynamic_info.flags = dyn->d_un.d_val; if (m->dynamic_info.flags != 0x04) // this value should always be DF_TEXTREL (0x04) { - LOG_WARN_IF(debug_loader, "DT_FLAGS is NOT 0x04 should check!"); + LOG_WARNING(Core_Linker, "DT_FLAGS is NOT 0x04 should check!"); } break; case DT_NEEDED: // Offset of the library string in the string table to be linked in. @@ -336,21 +274,21 @@ void Linker::LoadDynamicInfo(Module* m) { { m->dynamic_info.needed.push_back(m->dynamic_info.str_table + dyn->d_un.d_val); } else { - LOG_ERROR_IF(debug_loader, "DT_NEEDED str table is not loaded should check!"); + LOG_ERROR(Core_Linker, "DT_NEEDED str table is not loaded should check!"); } break; case DT_SCE_NEEDED_MODULE: { ModuleInfo info{}; info.value = dyn->d_un.d_val; info.name = m->dynamic_info.str_table + info.name_offset; - info.enc_id = encodeId(info.id); + info.enc_id = EncodeId(info.id); m->dynamic_info.import_modules.push_back(info); } break; case DT_SCE_IMPORT_LIB: { LibraryInfo info{}; info.value = dyn->d_un.d_val; info.name = m->dynamic_info.str_table + info.name_offset; - info.enc_id = encodeId(info.id); + info.enc_id = EncodeId(info.id); m->dynamic_info.import_libs.push_back(info); } break; case DT_SCE_FINGERPRINT: @@ -358,16 +296,14 @@ void Linker::LoadDynamicInfo(Module* m) { // the given app. How exactly this is generated isn't known, however it is not necessary // to have a valid fingerprint. While an invalid fingerprint will cause a warning to be // printed to the kernel log, the ELF will still load and run. - LOG_INFO_IF(debug_loader, - "unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}\n", - dyn->d_un.d_val); + LOG_INFO(Core_Linker, "unsupported DT_SCE_FINGERPRINT value = ..........: {:#018x}", + dyn->d_un.d_val); break; case DT_SCE_IMPORT_LIB_ATTR: // The upper 32-bits should contain the module index multiplied by 0x10000. The lower // 32-bits should be a constant 0x9. - LOG_INFO_IF(debug_loader, - "unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}\n", - dyn->d_un.d_val); + LOG_INFO(Core_Linker, "unsupported DT_SCE_IMPORT_LIB_ATTR value = ......: {:#018x}", + dyn->d_un.d_val); break; case DT_SCE_ORIGINAL_FILENAME: m->dynamic_info.filename = m->dynamic_info.str_table + dyn->d_un.d_val; @@ -377,24 +313,23 @@ void Linker::LoadDynamicInfo(Module* m) { ModuleInfo info{}; info.value = dyn->d_un.d_val; info.name = m->dynamic_info.str_table + info.name_offset; - info.enc_id = encodeId(info.id); + info.enc_id = EncodeId(info.id); m->dynamic_info.export_modules.push_back(info); } break; case DT_SCE_MODULE_ATTR: // TODO? - LOG_INFO_IF(debug_loader, - "unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}\n", - dyn->d_un.d_val); + LOG_INFO(Core_Linker, "unsupported DT_SCE_MODULE_ATTR value = ..........: {:#018x}", + dyn->d_un.d_val); break; case DT_SCE_EXPORT_LIB: { LibraryInfo info{}; info.value = dyn->d_un.d_val; info.name = m->dynamic_info.str_table + info.name_offset; - info.enc_id = encodeId(info.id); + info.enc_id = EncodeId(info.id); m->dynamic_info.export_libs.push_back(info); } break; default: - LOG_INFO_IF(debug_loader, "unsupported dynamic tag ..........: {:#018x}\n", dyn->d_tag); + LOG_INFO(Core_Linker, "unsupported dynamic tag ..........: {:#018x}", dyn->d_tag); } } } @@ -442,7 +377,7 @@ const LibraryInfo* Linker::FindLibrary(const Module& m, const std::string& id) { void Linker::LoadSymbols(Module* m) { if (m->dynamic_info.symbol_table == nullptr || m->dynamic_info.str_table == nullptr || m->dynamic_info.symbol_table_total_size == 0) { - LOG_INFO_IF(debug_loader, "Symbol table not found!\n"); + LOG_INFO(Core_Linker, "Symbol table not found!"); return; } @@ -466,8 +401,8 @@ void Linker::LoadSymbols(Module* m) { case STB_WEAK: break; default: - LOG_INFO_IF(debug_loader, "Unsupported bind {} for name symbol {} \n", bind, - ids.at(0)); + LOG_INFO(Core_Linker, "Unsupported bind {} for name symbol {}", bind, + ids.at(0)); continue; } switch (type) { @@ -475,16 +410,16 @@ void Linker::LoadSymbols(Module* m) { case STT_FUN: break; default: - LOG_INFO_IF(debug_loader, "Unsupported type {} for name symbol {} \n", type, - ids.at(0)); + LOG_INFO(Core_Linker, "Unsupported type {} for name symbol {}", type, + ids.at(0)); continue; } switch (visibility) { case STV_DEFAULT: break; default: - LOG_INFO_IF(debug_loader, "Unsupported visibility {} for name symbol {} \n", - visibility, ids.at(0)); + LOG_INFO(Core_Linker, "Unsupported visibility {} for name symbol {}", + visibility, ids.at(0)); continue; } // if st_value!=0 then it's export symbol @@ -515,97 +450,98 @@ void Linker::LoadSymbols(Module* m) { m->import_sym.AddSymbol(sym_r, 0); } - LOG_INFO_IF( - debug_loader, - "name {} function {} library {} module {} bind {} type {} visibility {}\n", - ids.at(0), nidName, library->name, module->name, bind, type, visibility); + LOG_INFO(Core_Linker, + "name = {}, function = {}, library = {}, module = {}, bind = {}, type = " + "{}, visibility = {}", + ids.at(0), nidName, library->name, module->name, bind, type, visibility); } } } } -static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) { - auto type = rel->GetType(); - auto symbol = rel->GetSymbol(); - auto addend = rel->rel_addend; - auto* symbolsTlb = m->dynamic_info.symbol_table; - auto* namesTlb = m->dynamic_info.str_table; - - u64 rel_value = 0; - u64 rel_base_virtual_addr = m->base_virtual_addr; - u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset; - bool rel_isResolved = false; - u8 rel_sym_type = 0; - std::string rel_name; - - switch (type) { - case R_X86_64_RELATIVE: - if (symbol != 0) // should be always zero - { - // LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, - // symbol);//found it openorbis but i am not sure it worth logging - } - rel_value = rel_base_virtual_addr + addend; - rel_isResolved = true; - break; - case R_X86_64_64: - case R_X86_64_JUMP_SLOT: // similar but addend is not take into account - { - auto sym = symbolsTlb[symbol]; - auto sym_bind = sym.GetBind(); - auto sym_type = sym.GetType(); - auto sym_visibility = sym.GetVisibility(); - u64 symbol_vitrual_addr = 0; - Loader::SymbolRecord symrec{}; - switch (sym_type) { - case STT_FUN: - rel_sym_type = 2; - break; - case STT_OBJECT: - rel_sym_type = 1; - break; - default: - LOG_INFO_IF(debug_loader, "unknown symbol type {}\n", sym_type); - } - if (sym_visibility != 0) // should be zero log if else - { - LOG_INFO_IF(debug_loader, "symbol visilibity !=0\n"); - } - switch (sym_bind) { - case STB_GLOBAL: - rel_name = namesTlb + sym.st_name; - m->linker->Resolve(rel_name, rel_sym_type, m, &symrec); - symbol_vitrual_addr = symrec.virtual_address; - rel_isResolved = (symbol_vitrual_addr != 0); - - rel_name = symrec.name; - if (type == R_X86_64_JUMP_SLOT) { - addend = 0; - } - rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); - if (!rel_isResolved) { - LOG_INFO_IF(debug_loader, - "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : " - "{:#010x}\n", - sym_type, symbol); - } - break; - default: - LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind); - } - - } break; - default: - LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol); - } - - if (rel_isResolved) { - VirtualMemory::memory_patch(rel_virtual_addr, rel_value); - } else { - LOG_INFO_IF(debug_loader, "function not patched! {}\n", rel_name); - } -} void Linker::Relocate(Module* m) { + const auto relocate = [this](u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) { + auto type = rel->GetType(); + auto symbol = rel->GetSymbol(); + auto addend = rel->rel_addend; + auto* symbolsTlb = m->dynamic_info.symbol_table; + auto* namesTlb = m->dynamic_info.str_table; + + u64 rel_value = 0; + u64 rel_base_virtual_addr = m->base_virtual_addr; + u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset; + bool rel_isResolved = false; + u8 rel_sym_type = 0; + std::string rel_name; + + switch (type) { + case R_X86_64_RELATIVE: + if (symbol != 0) // should be always zero + { + // LOG_INFO(Core_Linker, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, + // symbol);//found it openorbis but i am not sure it worth logging + } + rel_value = rel_base_virtual_addr + addend; + rel_isResolved = true; + break; + case R_X86_64_64: + case R_X86_64_JUMP_SLOT: // similar but addend is not take into account + { + auto sym = symbolsTlb[symbol]; + auto sym_bind = sym.GetBind(); + auto sym_type = sym.GetType(); + auto sym_visibility = sym.GetVisibility(); + u64 symbol_vitrual_addr = 0; + Loader::SymbolRecord symrec{}; + switch (sym_type) { + case STT_FUN: + rel_sym_type = 2; + break; + case STT_OBJECT: + rel_sym_type = 1; + break; + default: + LOG_INFO(Core_Linker, "unknown symbol type {}", sym_type); + } + if (sym_visibility != 0) // should be zero log if else + { + LOG_INFO(Core_Linker, "symbol visilibity !=0"); + } + switch (sym_bind) { + case STB_GLOBAL: + rel_name = namesTlb + sym.st_name; + Resolve(rel_name, rel_sym_type, m, &symrec); + symbol_vitrual_addr = symrec.virtual_address; + rel_isResolved = (symbol_vitrual_addr != 0); + + rel_name = symrec.name; + if (type == R_X86_64_JUMP_SLOT) { + addend = 0; + } + rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); + if (!rel_isResolved) { + LOG_INFO(Core_Linker, + "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : " + "{:#010x}", + sym_type, symbol); + } + break; + default: + LOG_INFO(Core_Linker, "UNK bind {}", sym_bind); + } + + } break; + default: + LOG_INFO(Core_Linker, "UNK type {:#010x} rel symbol : {:#010x}", type, symbol); + } + + if (rel_isResolved) { + VirtualMemory::memory_patch(rel_virtual_addr, rel_value); + } else { + LOG_INFO(Core_Linker, "function not patched! {}", rel_name); + } + }; + u32 idx = 0; for (auto* rel = m->dynamic_info.relocation_table; reinterpret_cast(rel) < reinterpret_cast(m->dynamic_info.relocation_table) + @@ -654,8 +590,8 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, return_info->virtual_address = AeroLib::GetStub(sr.name.c_str()); return_info->name = "Unknown !!!"; } - LOG_ERROR_IF(debug_loader, "Linker: Stub resolved {} as {} (lib: {}, mod: {}) \n", - sr.name, return_info->name, library->name, module->name); + LOG_ERROR(Core_Linker, "Linker: Stub resolved {} as {} (lib: {}, mod: {})", sr.name, + return_info->name, library->name, module->name); } } else { //__debugbreak();//den tha prepei na ftasoume edo @@ -672,7 +608,7 @@ static PS4_SYSV_ABI void ProgramExitFunc() { fmt::print("exit function called\n"); } -static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) { +static void RunMainEntry(u64 addr, EntryParams* params, exit_func_t exit_func) { // reinterpret_cast(addr)(params, exit_func); // can't be used, stack has to have // a specific layout @@ -702,7 +638,7 @@ void Linker::Execute() { p.argv[0] = "eboot.bin"; // hmm should be ok? const auto& module = m_modules.at(0); - run_main_entry(module.elf.GetElfEntry() + module.base_virtual_addr, &p, ProgramExitFunc); + RunMainEntry(module->elf.GetElfEntry() + module->base_virtual_addr, &p, ProgramExitFunc); } } // namespace Core diff --git a/src/core/linker.h b/src/core/linker.h index 5ee28f59..89d556b2 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -51,6 +51,7 @@ struct PS4ThreadLocal { u64 image_size = 0; u64 handler_virtual_addr = 0; }; + struct DynamicModuleInfo { void* hash_table = nullptr; u64 hash_table_size = 0; @@ -97,9 +98,7 @@ struct DynamicModuleInfo { struct Module { Loader::Elf elf; u64 aligned_base_size = 0; - u64 base_virtual_addr = 0; // Base virtual address - - Linker* linker = nullptr; + u64 base_virtual_addr = 0; std::vector m_dynamic; std::vector m_dynamic_data; @@ -116,8 +115,8 @@ public: Linker(); virtual ~Linker(); - Module* LoadModule(const std::string& elf_name); - Module* FindModule(/*u32 id*/); + Module* LoadModule(const std::filesystem::path& elf_name); + Module* FindModule(u32 id = 0); void LoadModuleToMemory(Module* m); void LoadDynamicInfo(Module* m); void LoadSymbols(Module* m); @@ -133,7 +132,7 @@ private: const ModuleInfo* FindModule(const Module& m, const std::string& id); const LibraryInfo* FindLibrary(const Module& program, const std::string& id); - std::vector m_modules; + std::vector> m_modules; Loader::SymbolsResolver m_hle_symbols{}; std::mutex m_mutex; }; diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index a10cf999..2e6dd60d 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -2,15 +2,15 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include -#include "common/debug.h" -#include "common/log.h" +#include "common/assert.h" +#include "common/logging/log.h" #include "core/loader/elf.h" namespace Core::Loader { -constexpr bool log_file_loader = false; // disable it to disable logging +using namespace Common::FS; -static std::string_view getProgramTypeName(program_type_es type) { +static std::string_view GetProgramTypeName(program_type_es type) { switch (type) { case PT_FAKE: return "PT_FAKE"; @@ -33,7 +33,7 @@ static std::string_view getProgramTypeName(program_type_es type) { } } -static std::string_view getIdentClassName(ident_class_es elf_class) { +static std::string_view GetIdentClassName(ident_class_es elf_class) { switch (elf_class) { case ELF_CLASS_NONE: return "ELF_CLASS_NONE"; @@ -48,7 +48,7 @@ static std::string_view getIdentClassName(ident_class_es elf_class) { } } -static std::string_view getIdentEndianName(ident_endian_es endian) { +static std::string_view GetIdentEndianName(ident_endian_es endian) { switch (endian) { case ELF_DATA_NONE: return "ELF_DATA_NONE"; @@ -63,7 +63,7 @@ static std::string_view getIdentEndianName(ident_endian_es endian) { } } -static std::string_view getIdentVersionName(ident_version_es version) { +static std::string_view GetIdentVersionName(ident_version_es version) { switch (version) { case ELF_VERSION_NONE: return "ELF_VERSION_NONE"; @@ -76,7 +76,7 @@ static std::string_view getIdentVersionName(ident_version_es version) { } } -static std::string_view getIdentOsabiName(ident_osabi_es osabi) { +static std::string_view GetIdentOsabiName(ident_osabi_es osabi) { switch (osabi) { case ELF_OSABI_NONE: return "ELF_OSABI_NONE"; @@ -117,7 +117,7 @@ static std::string_view getIdentOsabiName(ident_osabi_es osabi) { } } -static std::string_view getIdentAbiversionName(ident_abiversion_es version) { +static std::string_view GetIdentAbiversionName(ident_abiversion_es version) { switch (version) { case ELF_ABI_VERSION_AMDGPU_HSA_V2: return "ELF_ABI_VERSION_AMDGPU_HSA_V2"; @@ -131,7 +131,7 @@ static std::string_view getIdentAbiversionName(ident_abiversion_es version) { return "INVALID"; } } -static std::string_view getVersion(e_version_es version) { +static std::string_view GetVersion(e_version_es version) { switch (version) { case EV_NONE: return "EV_NONE"; @@ -142,7 +142,7 @@ static std::string_view getVersion(e_version_es version) { } } -static std::string_view getType(e_type_s type) { +static std::string_view GetType(e_type_s type) { switch (type) { case ET_NONE: return "ET_NONE"; @@ -167,7 +167,7 @@ static std::string_view getType(e_type_s type) { } } -static std::string_view getMachine(e_machine_es machine) { +static std::string_view GetMachine(e_machine_es machine) { switch (machine) { case EM_X86_64: return "EM_X86_64"; @@ -176,30 +176,25 @@ static std::string_view getMachine(e_machine_es machine) { } } -Elf::~Elf() { - Reset(); -} +Elf::~Elf() = default; -void Elf::Reset() { - m_f.close(); -} - -void Elf::Open(const std::string& file_name) { - Reset(); - - m_f.open(file_name, Common::FS::OpenMode::Read); - m_f.read(m_self); - - if (is_self = isSelfFile(); !is_self) { - m_f.seek(0, Common::FS::SeekMode::Set); - } else { - m_self_segments.resize(m_self.segment_count); - m_f.read(m_self_segments); +void Elf::Open(const std::filesystem::path& file_name) { + m_f.Open(file_name, FileAccessMode::Read); + if (!m_f.ReadObject(m_self)) { + LOG_ERROR(Loader, "Unable to read self header!"); + return; } - const u64 elf_header_pos = m_f.tell(); - m_f.read(m_elf_header); - if (!isElfFile()) { + if (is_self = IsSelfFile(); !is_self) { + m_f.Seek(0, SeekOrigin::SetOrigin); + } else { + m_self_segments.resize(m_self.segment_count); + m_f.Read(m_self_segments); + } + + const u64 elf_header_pos = m_f.Tell(); + m_f.Read(m_elf_header); + if (!IsElfFile()) { return; } @@ -209,8 +204,8 @@ void Elf::Open(const std::string& file_name) { } out.resize(num); - m_f.seek(offset, Common::FS::SeekMode::Set); - m_f.read(out); + m_f.Seek(offset, SeekOrigin::SetOrigin); + m_f.Read(out); }; load_headers(m_elf_phdr, elf_header_pos + m_elf_header.e_phoff, m_elf_header.e_phnum); @@ -227,96 +222,95 @@ void Elf::Open(const std::string& file_name) { header_size &= ~15; // Align if (m_elf_header.e_ehsize - header_size >= sizeof(elf_program_id_header)) { - m_f.seek(header_size, Common::FS::SeekMode::Set); - m_f.read(m_self_id_header); + m_f.Seek(header_size, SeekOrigin::SetOrigin); + m_f.ReadObject(m_self_id_header); } } DebugDump(); } -bool Elf::isSelfFile() const { +bool Elf::IsSelfFile() const { if (m_self.magic != self_header::signature) [[unlikely]] { - LOG_ERROR_IF(log_file_loader, - "Not a SELF file.Magic file mismatched !current = {:#x} required = {:#x}\n ", - m_self.magic, self_header::signature); + LOG_INFO(Loader, "Not a SELF file. Magic mismatch current = {:#x} expected = {:#x}", + m_self.magic, self_header::signature); return false; } if (m_self.version != 0x00 || m_self.mode != 0x01 || m_self.endian != 0x01 || m_self.attributes != 0x12) [[unlikely]] { - LOG_ERROR_IF(log_file_loader, "Unknown SELF file\n"); + LOG_INFO(Loader, "Unknown SELF file"); return false; } if (m_self.category != 0x01 || m_self.program_type != 0x01) [[unlikely]] { - LOG_ERROR_IF(log_file_loader, "Unknown SELF file\n"); + LOG_INFO(Loader, "Unknown SELF file"); return false; } return true; } -bool Elf::isElfFile() const { +bool Elf::IsElfFile() const { if (m_elf_header.e_ident.magic[EI_MAG0] != ELFMAG0 || m_elf_header.e_ident.magic[EI_MAG1] != ELFMAG1 || m_elf_header.e_ident.magic[EI_MAG2] != ELFMAG2 || m_elf_header.e_ident.magic[EI_MAG3] != ELFMAG3) { - LOG_ERROR_IF(log_file_loader, "Not an ELF file magic is wrong!\n"); + LOG_INFO(Loader, "Not an ELF file magic is wrong!"); return false; } if (m_elf_header.e_ident.ei_class != ELF_CLASS_64) { - LOG_ERROR_IF(log_file_loader, "e_ident[EI_CLASS] expected 0x02 is ({:#x})\n", - static_cast(m_elf_header.e_ident.ei_class)); + LOG_INFO(Loader, "e_ident[EI_CLASS] expected 0x02 is ({:#x})", + static_cast(m_elf_header.e_ident.ei_class)); return false; } if (m_elf_header.e_ident.ei_data != ELF_DATA_2LSB) { - LOG_ERROR_IF(log_file_loader, "e_ident[EI_DATA] expected 0x01 is ({:#x})\n", - static_cast(m_elf_header.e_ident.ei_data)); + LOG_INFO(Loader, "e_ident[EI_DATA] expected 0x01 is ({:#x})", + static_cast(m_elf_header.e_ident.ei_data)); return false; } if (m_elf_header.e_ident.ei_version != ELF_VERSION_CURRENT) { - LOG_ERROR_IF(log_file_loader, "e_ident[EI_VERSION] expected 0x01 is ({:#x})\n", - static_cast(m_elf_header.e_ident.ei_version)); + LOG_INFO(Loader, "e_ident[EI_VERSION] expected 0x01 is ({:#x})", + static_cast(m_elf_header.e_ident.ei_version)); return false; } if (m_elf_header.e_ident.ei_osabi != ELF_OSABI_FREEBSD) { - LOG_ERROR_IF(log_file_loader, "e_ident[EI_OSABI] expected 0x09 is ({:#x})\n", - static_cast(m_elf_header.e_ident.ei_osabi)); + LOG_INFO(Loader, "e_ident[EI_OSABI] expected 0x09 is ({:#x})", + static_cast(m_elf_header.e_ident.ei_osabi)); return false; } if (m_elf_header.e_ident.ei_abiversion != ELF_ABI_VERSION_AMDGPU_HSA_V2) { - LOG_ERROR_IF(log_file_loader, "e_ident[EI_ABIVERSION] expected 0x00 is ({:#x})\n", - static_cast(m_elf_header.e_ident.ei_abiversion)); + LOG_INFO(Loader, "e_ident[EI_ABIVERSION] expected 0x00 is ({:#x})", + static_cast(m_elf_header.e_ident.ei_abiversion)); return false; } if (m_elf_header.e_type != ET_SCE_DYNEXEC && m_elf_header.e_type != ET_SCE_DYNAMIC && m_elf_header.e_type != ET_SCE_EXEC) { - LOG_ERROR_IF(log_file_loader, "e_type expected 0xFE10 OR 0xFE18 OR 0xfe00 is ({:#x})\n", - static_cast(m_elf_header.e_type)); + LOG_INFO(Loader, "e_type expected 0xFE10 OR 0xFE18 OR 0xfe00 is ({:#x})", + static_cast(m_elf_header.e_type)); return false; } if (m_elf_header.e_machine != EM_X86_64) { - LOG_ERROR_IF(log_file_loader, "e_machine expected 0x3E is ({:#x})\n", - static_cast(m_elf_header.e_machine)); + LOG_INFO(Loader, "e_machine expected 0x3E is ({:#x})", + static_cast(m_elf_header.e_machine)); return false; } if (m_elf_header.e_version != EV_CURRENT) { - LOG_ERROR_IF(log_file_loader, "m_elf_header.e_version expected 0x01 is ({:#x})\n", - static_cast(m_elf_header.e_version)); + LOG_INFO(Loader, "m_elf_header.e_version expected 0x01 is ({:#x})", + static_cast(m_elf_header.e_version)); return false; } if (m_elf_header.e_phentsize != sizeof(elf_program_header)) { - LOG_ERROR_IF(log_file_loader, "e_phentsize ({}) != sizeof(elf_program_header)\n", - static_cast(m_elf_header.e_phentsize)); + LOG_INFO(Loader, "e_phentsize ({}) != sizeof(elf_program_header)", + m_elf_header.e_phentsize); return false; } @@ -324,8 +318,8 @@ bool Elf::isElfFile() const { m_elf_header.e_shentsize != sizeof(elf_section_header)) // Commercial games doesn't appear to have section headers { - LOG_ERROR_IF(log_file_loader, "e_shentsize ({}) != sizeof(elf_section_header)\n", - m_elf_header.e_shentsize); + LOG_INFO(Loader, "e_shentsize ({}) != sizeof(elf_section_header)", + m_elf_header.e_shentsize); return false; } @@ -334,50 +328,49 @@ bool Elf::isElfFile() const { void Elf::DebugDump() { if (is_self) { // If we load elf instead - LOG_INFO_IF(log_file_loader, (SElfHeaderStr())); + LOG_INFO(Loader, "{}", SElfHeaderStr()); for (u16 i = 0; i < m_self.segment_count; i++) { - LOG_INFO_IF(log_file_loader, SELFSegHeader(i)); + LOG_INFO(Loader, "{}", SELFSegHeader(i)); } } - LOG_INFO_IF(log_file_loader, ElfHeaderStr()); + LOG_INFO(Loader, "{}", ElfHeaderStr()); if (m_elf_header.e_phentsize > 0) { - LOG_INFO_IF(log_file_loader, "Program headers:\n"); + LOG_INFO(Loader, "Program headers:"); for (u16 i = 0; i < m_elf_header.e_phnum; i++) { - LOG_INFO_IF(log_file_loader, ElfPHeaderStr(i)); + LOG_INFO(Loader, "{}", ElfPHeaderStr(i)); } } if (m_elf_header.e_shentsize > 0) { - LOG_INFO_IF(log_file_loader, "Section headers:\n"); + LOG_INFO(Loader, "Section headers:"); for (u16 i = 0; i < m_elf_header.e_shnum; i++) { - LOG_INFO_IF(log_file_loader, "--- shdr {} --\n", i); - LOG_INFO_IF(log_file_loader, "sh_name ........: {}\n", m_elf_shdr[i].sh_name); - LOG_INFO_IF(log_file_loader, "sh_type ........: {:#010x}\n", m_elf_shdr[i].sh_type); - LOG_INFO_IF(log_file_loader, "sh_flags .......: {:#018x}\n", m_elf_shdr[i].sh_flags); - LOG_INFO_IF(log_file_loader, "sh_addr ........: {:#018x}\n", m_elf_shdr[i].sh_addr); - LOG_INFO_IF(log_file_loader, "sh_offset ......: {:#018x}\n", m_elf_shdr[i].sh_offset); - LOG_INFO_IF(log_file_loader, "sh_size ........: {:#018x}\n", m_elf_shdr[i].sh_size); - LOG_INFO_IF(log_file_loader, "sh_link ........: {:#010x}\n", m_elf_shdr[i].sh_link); - LOG_INFO_IF(log_file_loader, "sh_info ........: {:#010x}\n", m_elf_shdr[i].sh_info); - LOG_INFO_IF(log_file_loader, "sh_addralign ...: {:#018x}\n", - m_elf_shdr[i].sh_addralign); - LOG_INFO_IF(log_file_loader, "sh_entsize .....: {:#018x}\n", m_elf_shdr[i].sh_entsize); + LOG_INFO(Loader, "--- shdr {} --", i); + LOG_INFO(Loader, "sh_name ........: {}", m_elf_shdr[i].sh_name); + LOG_INFO(Loader, "sh_type ........: {:#010x}", m_elf_shdr[i].sh_type); + LOG_INFO(Loader, "sh_flags .......: {:#018x}", m_elf_shdr[i].sh_flags); + LOG_INFO(Loader, "sh_addr ........: {:#018x}", m_elf_shdr[i].sh_addr); + LOG_INFO(Loader, "sh_offset ......: {:#018x}", m_elf_shdr[i].sh_offset); + LOG_INFO(Loader, "sh_size ........: {:#018x}", m_elf_shdr[i].sh_size); + LOG_INFO(Loader, "sh_link ........: {:#010x}", m_elf_shdr[i].sh_link); + LOG_INFO(Loader, "sh_info ........: {:#010x}", m_elf_shdr[i].sh_info); + LOG_INFO(Loader, "sh_addralign ...: {:#018x}", m_elf_shdr[i].sh_addralign); + LOG_INFO(Loader, "sh_entsize .....: {:#018x}", m_elf_shdr[i].sh_entsize); } } if (is_self) { - LOG_INFO_IF(log_file_loader, "SELF info:\n"); - LOG_INFO_IF(log_file_loader, "auth id ............: {:#018x}\n", m_self_id_header.authid); - LOG_INFO_IF(log_file_loader, "program type .......: {}\n", - getProgramTypeName(m_self_id_header.program_type)); - LOG_INFO_IF(log_file_loader, "app version ........: {:#018x}\n", m_self_id_header.appver); - LOG_INFO_IF(log_file_loader, "fw version .........: {:#018x}\n", m_self_id_header.firmver); + LOG_INFO(Loader, "SELF info:"); + LOG_INFO(Loader, "auth id ............: {:#018x}", m_self_id_header.authid); + LOG_INFO(Loader, "program type .......: {}", + GetProgramTypeName(m_self_id_header.program_type)); + LOG_INFO(Loader, "app version ........: {:#018x}", m_self_id_header.appver); + LOG_INFO(Loader, "fw version .........: {:#018x}", m_self_id_header.firmver); std::string digest; for (int i = 0; i < 32; i++) { digest += fmt::format("{:02X}", m_self_id_header.digest[i]); } - LOG_INFO_IF(log_file_loader, "digest..............: 0x{}\n", digest); + LOG_INFO(Loader, "digest..............: 0x{}", digest); } } @@ -420,15 +413,15 @@ std::string Elf::ElfHeaderStr() { header += fmt::format("\n"); header += - fmt::format("ident class.......: {}\n", getIdentClassName(m_elf_header.e_ident.ei_class)); + fmt::format("ident class.......: {}\n", GetIdentClassName(m_elf_header.e_ident.ei_class)); header += - fmt::format("ident data .......: {}\n", getIdentEndianName(m_elf_header.e_ident.ei_data)); + fmt::format("ident data .......: {}\n", GetIdentEndianName(m_elf_header.e_ident.ei_data)); header += fmt::format("ident version.....: {}\n", - getIdentVersionName(m_elf_header.e_ident.ei_version)); + GetIdentVersionName(m_elf_header.e_ident.ei_version)); header += - fmt::format("ident osabi .....: {}\n", getIdentOsabiName(m_elf_header.e_ident.ei_osabi)); + fmt::format("ident osabi .....: {}\n", GetIdentOsabiName(m_elf_header.e_ident.ei_osabi)); header += fmt::format("ident abiversion..: {}\n", - getIdentAbiversionName(m_elf_header.e_ident.ei_abiversion)); + GetIdentAbiversionName(m_elf_header.e_ident.ei_abiversion)); header += fmt::format("ident UNK ........: 0x"); for (auto i : m_elf_header.e_ident.pad) { @@ -436,9 +429,9 @@ std::string Elf::ElfHeaderStr() { } header += fmt::format("\n"); - header += fmt::format("type ............: {}\n", getType(m_elf_header.e_type)); - header += fmt::format("machine ..........: {}\n", getMachine(m_elf_header.e_machine)); - header += fmt::format("version ..........: {}\n", getVersion(m_elf_header.e_version)); + header += fmt::format("type ............: {}\n", GetType(m_elf_header.e_type)); + header += fmt::format("machine ..........: {}\n", GetMachine(m_elf_header.e_machine)); + header += fmt::format("version ..........: {}\n", GetVersion(m_elf_header.e_version)); header += fmt::format("entry ............: {:#018x}\n", m_elf_header.e_entry); header += fmt::format("phoff ............: {:#018x}\n", m_elf_header.e_phoff); header += fmt::format("shoff ............: {:#018x}\n", m_elf_header.e_shoff); @@ -522,8 +515,8 @@ std::string Elf::ElfPHeaderStr(u16 no) { void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) { if (!is_self) { // It's elf file - m_f.seek(file_offset, Common::FS::SeekMode::Set); - m_f.read(reinterpret_cast(static_cast(virtual_addr)), size); + m_f.Seek(file_offset, SeekOrigin::SetOrigin); + m_f.ReadRaw(reinterpret_cast(virtual_addr), size); return; } @@ -536,13 +529,13 @@ void Elf::LoadSegment(u64 virtual_addr, u64 file_offset, u64 size) { if (file_offset >= phdr.p_offset && file_offset < phdr.p_offset + phdr.p_filesz) { auto offset = file_offset - phdr.p_offset; - m_f.seek(offset + seg.file_offset, Common::FS::SeekMode::Set); - m_f.read(reinterpret_cast(static_cast(virtual_addr)), size); + m_f.Seek(offset + seg.file_offset, SeekOrigin::SetOrigin); + m_f.ReadRaw(reinterpret_cast(virtual_addr), size); return; } } } - BREAKPOINT(); // Hmm we didn't return something... + UNREACHABLE(); } } // namespace Core::Loader diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index 9a570f28..3a8df6be 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -8,11 +8,11 @@ #include #include -#include "common/fs_file.h" +#include "common/io_file.h" #include "common/types.h" struct self_header { - static const u32 signature = 0x1D3D154Fu; + static constexpr u32 signature = 0x1D3D154Fu; u32 magic; u8 version; @@ -455,11 +455,11 @@ namespace Core::Loader { class Elf { public: Elf() = default; - virtual ~Elf(); + ~Elf(); - void Open(const std::string& file_name); - bool isSelfFile() const; - bool isElfFile() const; + void Open(const std::filesystem::path& file_name); + bool IsSelfFile() const; + bool IsElfFile() const; void DebugDump(); [[nodiscard]] self_header GetSElfHeader() const { @@ -492,10 +492,7 @@ public: void LoadSegment(u64 virtual_addr, u64 file_offset, u64 size); private: - void Reset(); - -private: - Common::FS::File m_f{}; + Common::FS::IOFile m_f{}; bool is_self{}; self_header m_self{}; std::vector m_self_segments; diff --git a/src/core/loader/symbols_resolver.cpp b/src/core/loader/symbols_resolver.cpp index 221e764e..9c90875b 100644 --- a/src/core/loader/symbols_resolver.cpp +++ b/src/core/loader/symbols_resolver.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/log.h" +#include "common/logging/log.h" #include "common/types.h" #include "core/loader/symbols_resolver.h" @@ -27,7 +27,7 @@ const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolRes& s) const { } } - LOG_INFO("Unresolved! {}\n", name); + LOG_INFO(Core_Linker, "Unresolved! {}", name); return nullptr; } diff --git a/src/core/tls.cpp b/src/core/tls.cpp new file mode 100644 index 00000000..6291d1ab --- /dev/null +++ b/src/core/tls.cpp @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "common/types.h" +#include "core/tls.h" + +#ifdef _WIN32 +#include +#endif + +namespace Core { + +thread_local u8 TLS[1024]; + +struct TLSPattern { + uint8_t pattern[5]; + uint8_t pattern_size; + uint8_t imm_size; + uint8_t target_reg; +}; + +constexpr static TLSPattern TlsPatterns[] = { + {{0x64, 0x48, 0xA1}, + 3, + 8, + 0}, // 64 48 A1 | 00 00 00 00 00 00 00 00 # mov rax, qword ptr fs:[64b imm] + + {{0x64, 0x48, 0x8B, 0x4, 0x25}, + 5, + 4, + 0}, // 64 48 8B 04 25 | 00 00 00 00 # mov rax,qword ptr fs:[0] + {{0x64, 0x48, 0x8B, 0xC, 0x25}, 5, 4, 1}, // rcx + {{0x64, 0x48, 0x8B, 0x14, 0x25}, 5, 4, 2}, // rdx + {{0x64, 0x48, 0x8B, 0x1C, 0x25}, 5, 4, 3}, // rbx + {{0x64, 0x48, 0x8B, 0x24, 0x25}, 5, 4, 4}, // rsp + {{0x64, 0x48, 0x8B, 0x2C, 0x25}, 5, 4, 5}, // rbp + {{0x64, 0x48, 0x8B, 0x34, 0x25}, 5, 4, 6}, // rsi + {{0x64, 0x48, 0x8B, 0x3C, 0x25}, 5, 4, 7}, // rdi + {{0x64, 0x4C, 0x8B, 0x4, 0x25}, 5, 4, 8}, // r8 + {{0x64, 0x4C, 0x8B, 0xC, 0x25}, 5, 4, 9}, // r9 + {{0x64, 0x4C, 0x8B, 0x14, 0x25}, 5, 4, 10}, // r10 + {{0x64, 0x4C, 0x8B, 0x1C, 0x25}, 5, 4, 11}, // r11 + {{0x64, 0x4C, 0x8B, 0x24, 0x25}, 5, 4, 12}, // r12 + {{0x64, 0x4C, 0x8B, 0x2C, 0x25}, 5, 4, 13}, // r13 + {{0x64, 0x4C, 0x8B, 0x34, 0x25}, 5, 4, 14}, // r14 + {{0x64, 0x4C, 0x8B, 0x3C, 0x25}, 5, 4, 15}, // r15 +}; + +uintptr_t GetGuestTls(s64 tls_offset) { + if (tls_offset == 0) { + return reinterpret_cast(TLS); + } + UNREACHABLE_MSG("Unimplemented offset info tls"); +} + +#ifdef _WIN64 +static LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS pExp) noexcept { + auto orig_rip = pExp->ContextRecord->Rip; + while (*(u8*)pExp->ContextRecord->Rip == 0x66) { + pExp->ContextRecord->Rip++; + } + + if (*(u8*)pExp->ContextRecord->Rip == 0xcd) { + int reg = *(u8*)(pExp->ContextRecord->Rip + 1) - 0x80; + int sizes = *(u8*)(pExp->ContextRecord->Rip + 2); + int pattern_size = sizes & 0xF; + int imm_size = sizes >> 4; + + int64_t tls_offset; + if (imm_size == 4) { + tls_offset = *(s32*)(pExp->ContextRecord->Rip + pattern_size); + } else { + tls_offset = *(s64*)(pExp->ContextRecord->Rip + pattern_size); + } + + (&pExp->ContextRecord->Rax)[reg] = GetGuestTls(tls_offset); /* GetGuestTls */ + pExp->ContextRecord->Rip += pattern_size + imm_size; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + pExp->ContextRecord->Rip = orig_rip; + const u32 ec = pExp->ExceptionRecord->ExceptionCode; + switch (ec) { + case EXCEPTION_ACCESS_VIOLATION: { + LOG_CRITICAL(Core, "Exception EXCEPTION_ACCESS_VIOLATION ({:#x})", ec); + const auto info = pExp->ExceptionRecord->ExceptionInformation; + switch (info[0]) { + case 0: + LOG_CRITICAL(Core, "Read violation at address {:#x}", info[1]); + break; + case 1: + LOG_CRITICAL(Core, "Write violation at address {:#x}", info[1]); + break; + case 8: + LOG_CRITICAL(Core, "DEP violation at address {:#x}", info[1]); + break; + default: + break; + } + break; + } + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + LOG_CRITICAL(Core, "Exception EXCEPTION_ARRAY_BOUNDS_EXCEEDED ({:#x})", ec); + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + LOG_CRITICAL(Core, "Exception EXCEPTION_DATATYPE_MISALIGNMENT ({:#x})", ec); + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + LOG_CRITICAL(Core, "Exception EXCEPTION_FLT_DIVIDE_BY_ZERO ({:#x})", ec); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + LOG_CRITICAL(Core, "Exception EXCEPTION_ILLEGAL_INSTRUCTION ({:#x})", ec); + break; + case EXCEPTION_IN_PAGE_ERROR: + LOG_CRITICAL(Core, "Exception EXCEPTION_IN_PAGE_ERROR ({:#x})", ec); + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + LOG_CRITICAL(Core, "Exception EXCEPTION_INT_DIVIDE_BY_ZERO ({:#x})", ec); + break; + case EXCEPTION_PRIV_INSTRUCTION: + LOG_CRITICAL(Core, "Exception EXCEPTION_PRIV_INSTRUCTION ({:#x})", ec); + break; + case EXCEPTION_STACK_OVERFLOW: + LOG_CRITICAL(Core, "Exception EXCEPTION_STACK_OVERFLOW ({:#x})", ec); + break; + default: + return EXCEPTION_CONTINUE_SEARCH; + } + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +void InstallTlsHandler() { +#ifdef _WIN64 + if (!AddVectoredExceptionHandler(0, ExceptionHandler)) { + LOG_CRITICAL(Core, "Failed to register an exception handler"); + } +#endif +} + +void PatchTLS(u64 segment_addr, u64 segment_size) { + u8* code = reinterpret_cast(segment_addr); + auto remaining_size = segment_size; + + while (remaining_size) { + for (const auto& tls_pattern : TlsPatterns) { + const auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size; + if (remaining_size < total_size) { + continue; + } + if (std::memcmp(code, tls_pattern.pattern, tls_pattern.pattern_size) != 0) { + continue; + } + if (tls_pattern.imm_size == 4) { + LOG_INFO(Core_Linker, "PATTERN32 FOUND at {}, reg: {} offset: {:#x}", + fmt::ptr(code), tls_pattern.target_reg, + *(u32*)(code + tls_pattern.pattern_size)); + } else { + LOG_INFO(Core_Linker, "PATTERN64 FOUND at {}, reg: {} offset: {:#x}", + fmt::ptr(code), tls_pattern.target_reg, + *(u32*)(code + tls_pattern.pattern_size)); + } + code[0] = 0xcd; + code[1] = 0x80 + tls_pattern.target_reg; + code[2] = tls_pattern.pattern_size | (tls_pattern.imm_size << 4); + code += total_size - 1; + remaining_size -= total_size - 1; + break; + } + code++; + remaining_size--; + } +} + +} // namespace Core diff --git a/src/core/tls.h b/src/core/tls.h new file mode 100644 index 00000000..aa001178 --- /dev/null +++ b/src/core/tls.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core { + +/// Installs a host exception handler to handle guest TLS access. +void InstallTlsHandler(); + +/// Patches any instructions that access TLS to trigger the exception handler. +void PatchTLS(u64 segment_addr, u64 segment_size); + +} // namespace Core diff --git a/src/core/virtual_memory.cpp b/src/core/virtual_memory.cpp index 9f3aacc1..3c9c2e20 100644 --- a/src/core/virtual_memory.cpp +++ b/src/core/virtual_memory.cpp @@ -1,10 +1,11 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/assert.h" +#include "common/error.h" +#include "common/logging/log.h" #include "core/virtual_memory.h" -#include "common/log.h" - #ifdef _WIN64 #include #else @@ -72,7 +73,7 @@ u64 memory_alloc(u64 address, u64 size, MemoryMode mode) { if (ptr == 0) { auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "VirtualAlloc() failed: 0x{:X}\n", err); + LOG_ERROR(Common_Memory, "VirtualAlloc() failed: 0x{:X}", err); } #else auto ptr = reinterpret_cast( @@ -80,7 +81,7 @@ u64 memory_alloc(u64 address, u64 size, MemoryMode mode) { PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); if (ptr == reinterpret_cast MAP_FAILED) { - LOG_ERROR_IF(true, "mmap() failed: {}\n", std::strerror(errno)); + LOG_ERROR(Common_Memory, "mmap() failed: {}", std::strerror(errno)); } #endif return ptr; @@ -91,7 +92,7 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode if (VirtualProtect(reinterpret_cast(static_cast(address)), size, convertMemoryMode(mode), &old_protect) == 0) { auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "VirtualProtect() failed: 0x{:X}\n", err); + LOG_ERROR(Common_Memory, "VirtualProtect() failed: 0x{:X}", err); return false; } if (old_mode != nullptr) { @@ -100,6 +101,10 @@ bool memory_protect(u64 address, u64 size, MemoryMode mode, MemoryMode* old_mode return true; #else int ret = mprotect(reinterpret_cast(address), size, convertMemoryMode(mode)); + if (ret != 0) { + const auto error = Common::GetLastErrorMsg(); + ASSERT(false); + } return true; #endif } @@ -110,7 +115,7 @@ bool memory_flush(u64 address, u64 size) { reinterpret_cast(static_cast(address)), size) == 0) { auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "FlushInstructionCache() failed: 0x{:X}\n", err); + LOG_ERROR(Common_Memory, "FlushInstructionCache() failed: 0x{:X}", err); return false; } return true; @@ -120,7 +125,7 @@ bool memory_flush(u64 address, u64 size) { } bool memory_patch(u64 vaddr, u64 value) { MemoryMode old_mode{}; - memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); + // memory_protect(vaddr, 8, MemoryMode::ReadWrite, &old_mode); auto* ptr = reinterpret_cast(vaddr); @@ -128,7 +133,7 @@ bool memory_patch(u64 vaddr, u64 value) { *ptr = value; - memory_protect(vaddr, 8, old_mode, nullptr); + // memory_protect(vaddr, 8, old_mode, nullptr); // if mode is executable flush it so insure that cpu finds it if (containsExecuteMode(old_mode)) { @@ -161,15 +166,13 @@ u64 memory_alloc_aligned(u64 address, u64 size, MemoryMode mode, u64 alignment) if (ptr == 0) { auto err = static_cast(GetLastError()); - LOG_ERROR_IF(true, "VirtualAlloc2() failed: 0x{:X}\n", err); + LOG_ERROR(Common_Memory, "VirtualAlloc2() failed: 0x{:X}", err); } return ptr; #else void* hint_address = reinterpret_cast(AlignUp(address, alignment)); void* ptr = mmap(hint_address, size, convertMemoryMode(mode), MAP_ANON | MAP_PRIVATE, -1, 0); - if (ptr == MAP_FAILED) { - std::abort(); - } + ASSERT(ptr != MAP_FAILED); return reinterpret_cast(ptr); #endif } diff --git a/src/emulator.cpp b/src/emulator.cpp index 77e07f7c..8962a5bb 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -197,7 +197,6 @@ void emuRun() { } } } - std::exit(0); } HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { diff --git a/src/main.cpp b/src/main.cpp index 95b7845c..10255db8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,13 +12,15 @@ #include #include "Util/config.h" #include "common/discord.h" -#include "common/log.h" +#include "common/logging/backend.h" +#include "common/path_util.h" #include "common/singleton.h" #include "common/types.h" #include "core/PS4/HLE/Graphics/video_out.h" #include "core/file_sys/fs.h" #include "core/hle/libraries/libs.h" #include "core/linker.h" +#include "core/tls.h" #include "emulator.h" int main(int argc, char* argv[]) { @@ -26,8 +28,10 @@ int main(int argc, char* argv[]) { fmt::print("Usage: {} \n", argv[0]); return -1; } - Config::load("config.toml"); - Common::Log::Init(true); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + Config::load(config_dir / "config.toml"); + Common::Log::Initialize(); + Common::Log::Start(); Core::Libraries::LibKernel::init_pthreads(); auto width = Config::getScreenWidth(); auto height = Config::getScreenHeight(); @@ -39,10 +43,11 @@ int main(int argc, char* argv[]) { auto* mnt = Common::Singleton::Instance(); std::filesystem::path p = std::string(path); - mnt->mount(p.parent_path().string(), "/app0"); + mnt->Mount(p.parent_path(), "/app0"); auto linker = Common::Singleton::Instance(); Core::Libraries::InitHLELibs(&linker->getHLESymbols()); + Core::InstallTlsHandler(); linker->LoadModule(path); std::jthread mainthread([linker](std::stop_token stop_token, void*) { linker->Execute(); }, nullptr); diff --git a/src/vulkan_util.cpp b/src/vulkan_util.cpp index 326ec81e..7190d7d8 100644 --- a/src/vulkan_util.cpp +++ b/src/vulkan_util.cpp @@ -6,15 +6,14 @@ #include #include #include +#include "common/assert.h" #include "common/debug.h" -#include "common/log.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "vulkan_util.h" #include -constexpr bool log_file_vulkanutil = true; // disable it to disable logging - void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) { Emu::VulkanExt ext; vulkanGetInstanceExtensions(&ext); @@ -38,19 +37,12 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) { inst_info.enabledLayerCount = 0; inst_info.ppEnabledLayerNames = nullptr; - VkResult result = vkCreateInstance(&inst_info, nullptr, &ctx->m_graphic_ctx.m_instance); - if (result == VK_ERROR_INCOMPATIBLE_DRIVER) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't find an compatiblie vulkan driver\n"); - std::exit(0); - } else if (result != VK_SUCCESS) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan instance\n"); - std::exit(0); - } + const VkResult result = vkCreateInstance(&inst_info, nullptr, &ctx->m_graphic_ctx.m_instance); + ASSERT_MSG(result == VK_SUCCESS, "Can't create an vulkan instance"); if (SDL_Vulkan_CreateSurface(ctx->m_window, ctx->m_graphic_ctx.m_instance, &ctx->m_surface) == SDL_FALSE) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create an vulkan surface\n"); - std::exit(0); + UNREACHABLE_MSG("Can't create an vulkan surface"); } // TODO i am not sure if it's that it is neccesary or if it needs more @@ -64,22 +56,16 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) { device_extensions, &ctx->m_surface_capabilities, &ctx->m_graphic_ctx.m_physical_device, &queues); - if (ctx->m_graphic_ctx.m_physical_device == nullptr) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't find compatible vulkan device\n"); - std::exit(0); - } + ASSERT_MSG(ctx->m_graphic_ctx.m_physical_device, "Can't find compatible vulkan device"); VkPhysicalDeviceProperties device_properties{}; vkGetPhysicalDeviceProperties(ctx->m_graphic_ctx.m_physical_device, &device_properties); - LOG_INFO_IF(log_file_vulkanutil, "GFX device to be used : {}\n", device_properties.deviceName); + LOG_INFO(Render_Vulkan, "GFX device to be used : {}", device_properties.deviceName); ctx->m_graphic_ctx.m_device = vulkanCreateDevice( ctx->m_graphic_ctx.m_physical_device, ctx->m_surface, &ext, queues, device_extensions); - if (ctx->m_graphic_ctx.m_device == nullptr) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan device\n"); - std::exit(0); - } + ASSERT_MSG(ctx->m_graphic_ctx.m_device, "Can't create vulkan device"); vulkanCreateQueues(&ctx->m_graphic_ctx, queues); ctx->swapchain = vulkanCreateSwapchain(&ctx->m_graphic_ctx, 2); @@ -160,11 +146,8 @@ Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics vkCreateImageView(ctx->m_device, &create_info, nullptr, &s.swapchain_image_views[i]); } - if (s.swapchain == nullptr) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Could not create swapchain\n"); - std::exit(0); - } + ASSERT_MSG(s.swapchain, "Could not create swapchain"); s.current_index = static_cast(-1); VkSemaphoreCreateInfo present_complete_info{}; @@ -181,10 +164,7 @@ Emu::VulkanSwapchain Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics fence_info.flags = 0; result = vkCreateFence(ctx->m_device, &fence_info, nullptr, &s.present_complete_fence); - if (result != VK_SUCCESS) { - LOG_CRITICAL_IF(log_file_vulkanutil, "Can't create vulkan fence\n"); - std::exit(0); - } + ASSERT_MSG(result == VK_SUCCESS, "Can't create vulkan fence"); return s; } @@ -282,18 +262,18 @@ void Graphics::Vulkan::vulkanGetInstanceExtensions(Emu::VulkanExt* ext) { vkEnumerateInstanceLayerProperties(&available_layers_count, ext->available_layers.data()); for (const char* ext : ext->required_extensions) { - LOG_INFO_IF(log_file_vulkanutil, "Vulkan required extension = {}\n", ext); + LOG_INFO(Render_Vulkan, "Vulkan required extension = {}", ext); } for (const auto& ext : ext->available_extensions) { - LOG_INFO_IF(log_file_vulkanutil, "Vulkan available extension: {}, version = {}\n", - ext.extensionName, ext.specVersion); + LOG_INFO(Render_Vulkan, "Vulkan available extension: {}, version = {}", ext.extensionName, + ext.specVersion); } for (const auto& l : ext->available_layers) { - LOG_INFO_IF(log_file_vulkanutil, - "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}\n", - l.layerName, l.specVersion, l.implementationVersion, l.description); + LOG_INFO(Render_Vulkan, + "Vulkan available layer: {}, specVersion = {}, implVersion = {}, {}", l.layerName, + l.specVersion, l.implementationVersion, l.description); } } @@ -320,7 +300,7 @@ void Graphics::Vulkan::vulkanFindCompatiblePhysicalDevice( continue; // we don't want integrated gpu for now .Later we will check the requirements // and see what we can support (TODO fix me) } - LOG_INFO_IF(log_file_vulkanutil, "Vulkan device: {}\n", device_properties.deviceName); + LOG_INFO(Render_Vulkan, "Vulkan device: {}", device_properties.deviceName); auto qs = vulkanFindQueues(device, surface); @@ -349,9 +329,9 @@ Emu::VulkanQueues Graphics::Vulkan::vulkanFindQueues(VkPhysicalDevice device, VkBool32 presentation_supported = VK_FALSE; vkGetPhysicalDeviceSurfaceSupportKHR(device, family, surface, &presentation_supported); - LOG_INFO_IF(log_file_vulkanutil, "queue family: {}, count = {}, present = {}\n", - string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, - (presentation_supported == VK_TRUE ? "true" : "false")); + LOG_INFO(Render_Vulkan, "queue family: {}, count = {}, present = {}", + string_VkQueueFlags(f.queueFlags).c_str(), f.queueCount, + (presentation_supported == VK_TRUE ? "true" : "false")); for (uint32_t i = 0; i < f.queueCount; i++) { Emu::VulkanQueueInfo info; info.family = family; diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index c640ab74..55a23c11 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -12,14 +12,6 @@ add_subdirectory(fmt EXCLUDE_FROM_ALL) # MagicEnum add_subdirectory(magic_enum EXCLUDE_FROM_ALL) -# Spdlog -set(SPDLOG_WCHAR_FILENAMES ON CACHE BOOL "") -set(SPDLOG_NO_THREAD_ID ON CACHE BOOL "") -set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "") -add_subdirectory(spdlog EXCLUDE_FROM_ALL) -add_library(stb INTERFACE) -target_include_directories(stb INTERFACE ./stb) - # SDL3 add_subdirectory(SDL EXCLUDE_FROM_ALL) diff --git a/third-party/spdlog b/third-party/spdlog deleted file mode 160000 index 134f9194..00000000 --- a/third-party/spdlog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 134f9194bb93072b72b8cfa27ac3bb30a0fb5b57