diff --git a/.gitmodules b/.gitmodules index 9267baa77..16f4946ae 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 90671cf1c..7853b91a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,7 +228,7 @@ add_executable(shadps4 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) diff --git a/src/common/assert.cpp b/src/common/assert.cpp index 5f50c3262..624f0ad14 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp @@ -4,13 +4,7 @@ #include "common/assert.h" #include "common/logging/backend.h" -#if defined(ARCHITECTURE_x86_64) #define Crash() __asm__ __volatile__("int $3") -#elif defined(ARCHITECTURE_arm64) -#define Crash() __asm__ __volatile__("brk #0") -#else -#define Crash() exit(1) -#endif void assert_fail_impl() { Common::Log::Stop(); @@ -18,7 +12,7 @@ void assert_fail_impl() { } [[noreturn]] void unreachable_impl() { - Common::Log::Stop(); + /*Common::Log::Stop(); Crash(); - throw std::runtime_error("Unreachable code"); + throw std::runtime_error("Unreachable code");*/ } diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp index 3ff7bc808..fda3353ef 100644 --- a/src/common/io_file.cpp +++ b/src/common/io_file.cpp @@ -28,14 +28,6 @@ namespace { #ifdef _WIN32 -/** - * Converts the file access mode and file type enums to a file access mode wide string. - * - * @param mode File access mode - * @param type File type - * - * @returns A pointer to a wide string representing the file access mode. - */ [[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) { switch (type) { case FileType::BinaryFile: @@ -71,13 +63,6 @@ namespace { return L""; } -/** - * Converts the file-share access flag enum to a Windows defined file-share access flag. - * - * @param flag File-share access flag - * - * @returns Windows defined file-share access flag. - */ [[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) { switch (flag) { case FileShareFlag::ShareNone: @@ -94,14 +79,6 @@ namespace { #else -/** - * Converts the file access mode and file type enums to a file access mode string. - * - * @param mode File access mode - * @param type File type - * - * @returns A pointer to a string representing the file access mode. - */ [[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) { switch (type) { case FileType::BinaryFile: @@ -139,13 +116,6 @@ namespace { #endif -/** - * Converts the seek origin enum to a seek origin integer. - * - * @param origin Seek origin - * - * @returns Seek origin integer. - */ [[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) { switch (origin) { case SeekOrigin::SetOrigin: diff --git a/src/common/io_file.h b/src/common/io_file.h index e570cece5..bd544a396 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -72,16 +72,6 @@ public: explicit IOFile(std::string_view path, FileAccessMode mode, FileType type = FileType::BinaryFile, FileShareFlag flag = FileShareFlag::ShareReadOnly); - - /** - * An IOFile is a lightweight wrapper on C Library file operations. - * Automatically closes an open file on the destruction of an IOFile object. - * - * @param path Filesystem path - * @param mode File access mode - * @param type File type, default is BinaryFile. Use TextFile to open the file as a text file - * @param flag (Windows only) File-share access flag, default is ShareReadOnly - */ explicit IOFile(const std::filesystem::path& path, FileAccessMode mode, FileType type = FileType::BinaryFile, FileShareFlag flag = FileShareFlag::ShareReadOnly); @@ -94,74 +84,37 @@ public: IOFile(IOFile&& other) noexcept; IOFile& operator=(IOFile&& other) noexcept; - /** - * Gets the path of the file. - * - * @returns The path of the file. - */ std::filesystem::path GetPath() const { return file_path; } - /** - * Gets the access mode of the file. - * - * @returns The access mode of the file. - */ FileAccessMode GetAccessMode() const { return file_access_mode; } - /** - * Gets the type of the file. - * - * @returns The type of the file. - */ FileType GetType() const { return file_type; } - /** - * Opens a file at path with the specified file access mode. - * This function behaves differently depending on the FileAccessMode. - * These behaviors are documented in each enum value of FileAccessMode. - * - * @param path Filesystem path - * @param mode File access mode - * @param type File type, default is BinaryFile. Use TextFile to open the file as a text file - * @param flag (Windows only) File-share access flag, default is ShareReadOnly - */ - void Open(const std::filesystem::path& path, FileAccessMode mode, - FileType type = FileType::BinaryFile, - FileShareFlag flag = FileShareFlag::ShareReadOnly); - - /// Closes the file if it is opened. - void Close(); - - /** - * Checks whether the file is open. - * Use this to check whether the calls to Open() or Close() succeeded. - * - * @returns True if the file is open, false otherwise. - */ bool IsOpen() const { return file != nullptr; } - /** - * Helper function which deduces the value type of a contiguous STL container used in ReadSpan. - * If T is not a contiguous container as defined by the concept IsContiguousContainer, this - * calls ReadObject and T must be a trivially copyable object. - * - * See ReadSpan for more details if T is a contiguous container. - * See ReadObject for more details if T is a trivially copyable object. - * - * @tparam T Contiguous container or trivially copyable object - * - * @param data Container of T::value_type data or reference to object - * - * @returns Count of T::value_type data or objects successfully read. - */ + 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) { @@ -174,20 +127,6 @@ public: } } - /** - * Helper function which deduces the value type of a contiguous STL container used in WriteSpan. - * If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this - * calls WriteObject and T must be a trivially copyable object. - * - * See WriteSpan for more details if T is a contiguous container. - * See WriteObject for more details if T is a trivially copyable object. - * - * @tparam T Contiguous container or trivially copyable object - * - * @param data Container of T::value_type data or const reference to object - * - * @returns Count of T::value_type data or objects successfully written. - */ template size_t Write(const T& data) const { if constexpr (IsContiguousContainer) { @@ -201,22 +140,6 @@ public: } } - /** - * Reads a span of T data from a file sequentially. - * This function reads from the current position of the file pointer and - * advances it by the (count of T * sizeof(T)) bytes successfully read. - * - * Failures occur when: - * - The file is not open - * - The opened file lacks read permissions - * - Attempting to read beyond the end-of-file - * - * @tparam T Data type - * - * @param data Span of T data - * - * @returns Count of T data successfully read. - */ template size_t ReadSpan(std::span data) const { static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); @@ -228,31 +151,11 @@ public: return ReadRaw(data.data(), data.size()); } - /** - * Reads data from a file sequentially to a provided memory address. - * This function reads from the current position of the file pointer and - * advances it by the (count of T * sizeof(T)) bytes successfully read. - */ template size_t ReadRaw(void* data, size_t size) const { return std::fread(data, sizeof(T), size, file); } - /** - * Writes a span of T data to a file sequentially. - * This function writes from the current position of the file pointer and - * advances it by the (count of T * sizeof(T)) bytes successfully written. - * - * Failures occur when: - * - The file is not open - * - The opened file lacks write permissions - * - * @tparam T Data type - * - * @param data Span of T data - * - * @returns Count of T data successfully written. - */ template size_t WriteSpan(std::span data) const { static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); @@ -264,22 +167,6 @@ public: return std::fwrite(data.data(), sizeof(T), data.size(), file); } - /** - * Reads a T object from a file sequentially. - * This function reads from the current position of the file pointer and - * advances it by the sizeof(T) bytes successfully read. - * - * Failures occur when: - * - The file is not open - * - The opened file lacks read permissions - * - Attempting to read beyond the end-of-file - * - * @tparam T Data type - * - * @param object Reference to object - * - * @returns True if the object is successfully read from the file, false otherwise. - */ template bool ReadObject(T& object) const { static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); @@ -292,21 +179,6 @@ public: return std::fread(&object, sizeof(T), 1, file) == 1; } - /** - * Writes a T object to a file sequentially. - * This function writes from the current position of the file pointer and - * advances it by the sizeof(T) bytes successfully written. - * - * Failures occur when: - * - The file is not open - * - The opened file lacks write permissions - * - * @tparam T Data type - * - * @param object Const reference to object - * - * @returns True if the object is successfully written to the file, false otherwise. - */ template bool WriteObject(const T& object) const { static_assert(std::is_trivially_copyable_v, "Data type must be trivially copyable."); @@ -319,88 +191,12 @@ public: return std::fwrite(&object, sizeof(T), 1, file) == 1; } - /** - * Specialized function to read a string of a given length from a file sequentially. - * This function writes from the current position of the file pointer and - * advances it by the number of characters successfully read. - * The size of the returned string may not match length if not all bytes are successfully read. - * - * @param length Length of the string - * - * @returns A string read from the file. - */ std::string ReadString(size_t length) const; - /** - * Specialized function to write a string to a file sequentially. - * This function writes from the current position of the file pointer and - * advances it by the number of characters successfully written. - * - * @param string Span of const char backed std::string or std::string_view - * - * @returns Number of characters successfully written. - */ size_t WriteString(std::span string) const { return WriteSpan(string); } - /** - * Attempts to flush any unwritten buffered data into the file. - * - * @returns True if the flush was successful, false otherwise. - */ - bool Flush() const; - - /** - * Attempts to commit the file into the disk. - * Note that this is an expensive operation as this forces the operating system to write - * the contents of the file associated with the file descriptor into the disk. - * - * @returns True if the commit was successful, false otherwise. - */ - bool Commit() const; - - /** - * Resizes the file to a given size. - * If the file is resized to a smaller size, the remainder of the file is discarded. - * If the file is resized to a larger size, the new area appears as if zero-filled. - * - * Failures occur when: - * - The file is not open - * - * @param size File size in bytes - * - * @returns True if the file resize succeeded, false otherwise. - */ - bool SetSize(u64 size) const; - - /** - * Gets the size of the file. - * - * Failures occur when: - * - The file is not open - * - * @returns The file size in bytes of the file. Returns 0 on failure. - */ - u64 GetSize() const; - - /** - * Moves the current position of the file pointer with the specified offset and seek origin. - * - * @param offset Offset from seek origin - * @param origin Seek origin - * - * @returns True if the file pointer has moved to the specified offset, false otherwise. - */ - bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const; - - /** - * Gets the current position of the file pointer. - * - * @returns The current position of the file pointer. - */ - s64 Tell() const; - private: std::filesystem::path file_path; FileAccessMode file_access_mode{}; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 34f0baddd..49e246a09 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -60,18 +60,8 @@ private: */ class FileBackend { public: - explicit FileBackend(const std::filesystem::path& filename) { - auto old_filename = filename; - old_filename += ".old.txt"; - - std::filesystem::remove(old_filename); - std::filesystem::rename(filename, old_filename); - - // _SH_DENYWR allows read only access to the file for other programs. - // It is #defined to 0 on other platforms - file = std::make_unique(filename, FS::FileAccessMode::Write, - FS::FileType::TextFile); - } + explicit FileBackend(const std::filesystem::path& filename) : file{filename, FS::FileAccessMode::Write, + FS::FileType::TextFile} {} ~FileBackend() = default; @@ -80,7 +70,7 @@ public: return; } - bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n')); + 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; @@ -91,16 +81,16 @@ public: // Don't close the file so we can print a stacktrace if necessary enabled = false; } - file->Flush(); + file.Flush(); } } void Flush() { - file->Flush(); + file.Flush(); } private: - std::unique_ptr file; + Common::FS::IOFile file; bool enabled = true; std::size_t bytes_written = 0; }; @@ -258,7 +248,6 @@ private: void Initialize(std::string_view log_file) { Impl::Initialize(log_file.empty() ? LOG_FILE : log_file); - Impl::Start(); } void Start() { @@ -280,7 +269,7 @@ void SetColorConsoleBackendEnabled(bool 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) { + if (!initialization_in_progress_suppress_logging) [[likely]] { Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, fmt::vformat(format, args)); } diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 02c60b04f..16ece3139 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -35,6 +35,8 @@ static auto UserPaths = [] { 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; }(); diff --git a/src/common/path_util.h b/src/common/path_util.h index 1a3e27d47..1836a3acb 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -13,6 +13,7 @@ enum class PathType { 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"; @@ -21,6 +22,7 @@ constexpr auto PORTABLE_DIR = "user"; 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"; diff --git a/src/core/aerolib/stubs.cpp b/src/core/aerolib/stubs.cpp index 22e9f400e..98b55e5a9 100644 --- a/src/core/aerolib/stubs.cpp +++ b/src/core/aerolib/stubs.cpp @@ -22,12 +22,12 @@ namespace Core::AeroLib { constexpr u32 MAX_STUBS = 128; u64 UnresolvedStub() { - LOG_ERROR(Core, "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(Core, "Returning zero to {}\n", __builtin_return_address(0)); + LOG_ERROR(Core, "Returning zero to {}", __builtin_return_address(0)); return 0; } @@ -38,10 +38,10 @@ template static u64 CommonStub() { auto entry = stub_nids[stub_index]; if (entry) { - LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}\n", entry->name, + LOG_ERROR(Core, "Stub: {} (nid: {}) called, returning zero to {}", entry->name, entry->nid, __builtin_return_address(0)); } else { - LOG_ERROR(Core, "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/hle/libraries/libc/libc.cpp b/src/core/hle/libraries/libc/libc.cpp index 0db8fb318..127c3eb9c 100644 --- a/src/core/hle/libraries/libc/libc.cpp +++ b/src/core/hle/libraries/libc/libc.cpp @@ -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_stdio.cpp b/src/core/hle/libraries/libc/libc_stdio.cpp index 0a957522c..67568e297 100644 --- a/src/core/hle/libraries/libc/libc_stdio.cpp +++ b/src/core/hle/libraries/libc/libc_stdio.cpp @@ -2,10 +2,17 @@ // SPDX-License-Identifier: GPL-2.0-or-later #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 { +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); return printf_ctx(&ctx); @@ -17,6 +24,7 @@ int PS4_SYSV_ABI ps4_fprintf(FILE* file, VA_ARGS) { VA_CTX(ctx); return printf_ctx(&ctx); } + 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 f4308213a..c2911f36a 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/printf.h b/src/core/hle/libraries/libc/printf.h index e25608794..8bf98adaa 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/linker.cpp b/src/core/linker.cpp index 7f4b6d219..30cc26700 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/assert.h" #include "common/logging/log.h" #include "common/string_util.h" #include "core/aerolib/aerolib.h" @@ -56,9 +57,14 @@ Linker::Linker() = default; Linker::~Linker() = default; -Module* Linker::LoadModule(const std::string& elf_name) { +Module* Linker::LoadModule(const std::filesystem::path& elf_name) { std::scoped_lock lock{m_mutex}; + if (!std::filesystem::exists(elf_name)) { + LOG_ERROR(Core_Linker, "Provided module {} does not exist", elf_name.string()); + return nullptr; + } + auto& m = m_modules.emplace_back(); m = std::make_unique(); m->linker = this; diff --git a/src/core/linker.h b/src/core/linker.h index a682d42c0..f4f91e2ba 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -116,7 +116,7 @@ public: Linker(); virtual ~Linker(); - Module* LoadModule(const std::string& elf_name); + Module* LoadModule(const std::filesystem::path& elf_name); Module* FindModule(/*u32 id*/); void LoadModuleToMemory(Module* m); void LoadDynamicInfo(Module* m); diff --git a/src/core/virtual_memory.cpp b/src/core/virtual_memory.cpp index bf270d0ec..ae90f2c38 100644 --- a/src/core/virtual_memory.cpp +++ b/src/core/virtual_memory.cpp @@ -101,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 } @@ -121,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); @@ -129,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)) { diff --git a/src/main.cpp b/src/main.cpp index 2b7ee4363..81ac15377 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ int main(int argc, char* argv[]) { 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(); @@ -41,7 +42,7 @@ 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(config_dir / "app0", "/app0"); auto linker = Common::Singleton::Instance(); Core::Libraries::InitHLELibs(&linker->getHLESymbols()); @@ -53,7 +54,6 @@ int main(int argc, char* argv[]) { discordRPC.update(Discord::RPCStatus::Idling, ""); Emu::emuRun(); - Common::Log::Stop(); discordRPC.stop(); return 0; } diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index c640ab74e..55a23c110 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 134f9194b..000000000 --- a/third-party/spdlog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 134f9194bb93072b72b8cfa27ac3bb30a0fb5b57