From dd7d232ac3e7257a22aaada5b52408911e050ec1 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:28:08 +0300 Subject: [PATCH 01/12] event_queues: Use std placeholders --- src/core/libraries/kernel/event_queues.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/libraries/kernel/event_queues.cpp b/src/core/libraries/kernel/event_queues.cpp index 12f59e50..e42cc60d 100644 --- a/src/core/libraries/kernel/event_queues.cpp +++ b/src/core/libraries/kernel/event_queues.cpp @@ -7,8 +7,6 @@ #include "core/libraries/error_codes.h" #include "core/libraries/kernel/event_queues.h" -#include - namespace Libraries::Kernel { extern boost::asio::io_context io_context; @@ -137,7 +135,7 @@ s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec* io_context, std::chrono::microseconds(total_us - HrTimerSpinlockThresholdUs)); event.timer->async_wait( - std::bind(SmallTimerCallback, boost::asio::placeholders::error, eq, event.event)); + std::bind(SmallTimerCallback, std::placeholders::_1, eq, event.event)); if (!eq->AddEvent(event)) { return ORBIS_KERNEL_ERROR_ENOMEM; From 73d4aafc092e8237accacf4c1c612421c7895125 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:28:36 +0300 Subject: [PATCH 02/12] liverpool: Num submits should be atomic --- src/video_core/amdgpu/liverpool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index 0711b074..4245a995 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -1018,7 +1018,7 @@ private: Vulkan::Rasterizer* rasterizer{}; std::jthread process_thread{}; - u32 num_submits{}; + std::atomic num_submits{}; std::mutex submit_mutex; std::condition_variable_any submit_cv; }; From 432defd9929b77fd890b9205b06278768e5cd049 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:29:16 +0300 Subject: [PATCH 03/12] externals: Disable sdl pipewire * Fixes audio problems in certain games --- externals/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index a86c393f..08353fb3 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -59,6 +59,7 @@ endif() # SDL3 if (NOT TARGET SDL3::SDL3) + set(SDL_PIPEWIRE OFF) add_subdirectory(sdl3) endif() From 26f8fbf62865600fcfedc5ce070a7bfb47dcf092 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:48:57 +0300 Subject: [PATCH 04/12] tls: Use gs segment for linux --- src/core/tls.cpp | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 3f7bbceb..2afa5896 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -9,7 +9,8 @@ #ifdef _WIN32 #include #else -#include +#include /* Definition of ARCH_* constants */ +#include /* Definition of SYS_* constants */ #endif namespace Core { @@ -89,47 +90,28 @@ static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGe #else -static pthread_key_t slot = 0; +static u32 slot = 0; void SetTcbBase(void* image_address) { - ASSERT(pthread_setspecific(slot, image_address) == 0); + asm volatile("wrgsbase %0" :: "r" (image_address) : "memory"); } Tcb* GetTcbBase() { - return reinterpret_cast(pthread_getspecific(slot)); + Tcb* tcb; + asm volatile("rdgsbase %0" : "=r" (tcb) :: "memory"); + return tcb; } -static void AllocTcbKey() { - ASSERT(pthread_key_create(&slot, nullptr) == 0); -} +static void AllocTcbKey() {} static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGenerator& c) { using namespace Xbyak::util; const auto total_size = tls_pattern.pattern_size + tls_pattern.imm_size; - // Replace mov instruction with near jump to the trampoline. - static constexpr u32 NearJmpSize = 5; + // Replace fs read with gs read. auto patch = Xbyak::CodeGenerator(total_size, code); - patch.jmp(c.getCurr(), Xbyak::CodeGenerator::LabelType::T_NEAR); - patch.nop(total_size - NearJmpSize); - - // Write the trampoline. - // The following logic is based on the glibc implementation of pthread_getspecific - // https://github.com/bminor/glibc/blob/29807a27/nptl/pthread_getspecific.c#L23 - static constexpr u32 PthreadKeySecondLevelSize = 32; - static constexpr u32 PthreadSpecificOffset = 0x510; - static constexpr u32 PthreadKeyDataSize = 16; - ASSERT(slot >= PthreadKeySecondLevelSize); - - const u32 idx1st = slot / PthreadKeySecondLevelSize; - const u32 idx2nd = slot % PthreadKeySecondLevelSize; const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg); - c.mov(target_reg, PthreadSpecificOffset); - c.putSeg(fs); - c.mov(target_reg, qword[target_reg + idx1st * 8]); // Load first level specific array. - c.mov(target_reg, qword[target_reg + idx2nd * 16 + - 8]); // Load data member of pthread_key_data our slot specifies. - c.jmp(code + total_size); // Return to the instruction right after the mov. + patch.putSeg(gs); } #endif From dbeed80e3b6248703c20aa14fe39725f6ca1d404 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 03:37:30 +0300 Subject: [PATCH 05/12] fs: Actually functional linux case insensitive search --- src/common/io_file.h | 4 +- src/core/file_sys/fs.cpp | 111 +++++++++++++--------- src/core/file_sys/fs.h | 33 +++++-- src/core/libraries/kernel/file_system.cpp | 13 ++- src/core/libraries/kernel/libkernel.cpp | 2 +- src/core/libraries/libc/libc_stdio.cpp | 9 +- src/core/libraries/save_data/savedata.cpp | 81 ++++++++-------- 7 files changed, 145 insertions(+), 108 deletions(-) diff --git a/src/common/io_file.h b/src/common/io_file.h index 7cb3246c..2c3df3f6 100644 --- a/src/common/io_file.h +++ b/src/common/io_file.h @@ -205,9 +205,9 @@ public: return WriteSpan(string); } - static void WriteBytes(const std::filesystem::path path, std::span vec) { + static void WriteBytes(const std::filesystem::path path, std::span data) { IOFile out(path, FileAccessMode::Write); - out.Write(vec); + out.Write(data); } private: diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index e06a4b6e..f009dc2d 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -11,18 +11,12 @@ constexpr int RESERVED_HANDLES = 3; // First 3 handles are stdin,stdout,stderr 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.string(); - std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); - pair.guest_path = guest_folder; - - m_mnt_pairs.push_back(pair); + m_mnt_pairs.emplace_back(host_folder, guest_folder); } void MntPoints::Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder) { auto it = std::remove_if(m_mnt_pairs.begin(), m_mnt_pairs.end(), - [&](const MntPair& pair) { return pair.guest_path == guest_folder; }); + [&](const MntPair& pair) { return pair.mount == guest_folder; }); m_mnt_pairs.erase(it, m_mnt_pairs.end()); } @@ -31,47 +25,74 @@ void MntPoints::UnmountAll() { m_mnt_pairs.clear(); } -std::string MntPoints::GetHostDirectory(const std::string& guest_directory) { - std::scoped_lock lock{m_mutex}; - for (auto& pair : m_mnt_pairs) { - // horrible code but it works :D - int find = guest_directory.find(pair.guest_path); - if (find == 0) { - std::string npath = - guest_directory.substr(pair.guest_path.size(), guest_directory.size() - 1); - std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); - return pair.host_path + npath; - } +std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) { + const MntPair* mount = GetMount(guest_directory); + if (!mount) { + return guest_directory; } - return ""; -} -std::string MntPoints::GetHostFile(const std::string& guest_file) { - std::scoped_lock lock{m_mutex}; - - for (auto& pair : m_mnt_pairs) { - // horrible code but it works :D - int find = guest_file.find(pair.guest_path); - if (find != 0) { - continue; - } - std::string npath = guest_file.substr(pair.guest_path.size(), guest_file.size() - 1); - const auto host_path = pair.host_path + npath; -#ifndef _WIN64 - const std::filesystem::path path{host_path}; - if (!std::filesystem::exists(path)) { - const auto filename = Common::ToLower(path.filename()); - for (const auto& file : std::filesystem::directory_iterator(path.parent_path())) { - const auto exist_filename = Common::ToLower(file.path().filename()); - if (filename == exist_filename) { - return file.path(); - } - } - } -#endif + // Remove device (e.g /app0) from path to retrieve relative path. + const u32 pos = mount->mount.size() + 1; + const auto rel_path = std::string_view(guest_directory).substr(pos); + const auto host_path = mount->host_path / rel_path; + if (!NeedsCaseInsensiveSearch || std::filesystem::exists(host_path)) { return host_path; } - return ""; + + // If the path does not exist attempt to verify this. + // Retrieve parent path until we find one that exists. + path_parts.clear(); + auto current_path = host_path; + while (!std::filesystem::exists(current_path)) { + // We have probably cached this if it's a folder. + if (auto it = path_cache.find(current_path); it != path_cache.end()) { + current_path = it->second; + break; + } + path_parts.emplace_back(current_path.filename()); + current_path = current_path.parent_path(); + } + + // We have found an anchor. Traverse parts we recoded and see if they + // exist in filesystem but in different case. + auto guest_path = current_path; + while (!path_parts.empty()) { + const auto& part = path_parts.back(); + const auto add_match = [&](const auto& host_part) { + current_path += host_part; + guest_path += part; + path_cache[guest_path] = current_path; + path_parts.pop_back(); + }; + + // Can happen when the mismatch is in upper folder. + if (std::filesystem::exists(current_path / part)) { + add_match(part); + continue; + } + const auto part_low = Common::ToLower(part.string()); + bool found_match = false; + for (const auto& path : std::filesystem::directory_iterator(current_path)) { + const auto candidate = path.path().filename(); + const auto filename = Common::ToLower(candidate); + // Check if a filename matches in case insensitive manner. + if (filename != part_low) { + continue; + } + // We found a match, record the actual path in the cache. + add_match(candidate); + found_match = true; + break; + } + if (!found_match) { + // Opening the guest path will surely fail but at least gives + // a better error message than the empty path. + return guest_directory; + } + } + + // The path was found. + return current_path; } int HandleTable::CreateHandle() { diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index b31931d1..10fd10c4 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -7,28 +7,45 @@ #include #include #include +#include #include "common/io_file.h" namespace Core::FileSys { class MntPoints { +#ifdef _WIN64 + static constexpr bool NeedsCaseInsensiveSearch = false; +#else + static constexpr bool NeedsCaseInsensiveSearch = true; +#endif public: struct MntPair { - std::string host_path; - std::string guest_path; // e.g /app0/ + std::filesystem::path host_path; + std::string mount; // e.g /app0/ }; - MntPoints() = default; - virtual ~MntPoints() = default; + explicit MntPoints() = default; + ~MntPoints() = default; - void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder); - void Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder); + void Mount(const std::filesystem::path& host_folder, + const std::string& guest_folder); + void Unmount(const std::filesystem::path& host_folder, + const std::string& guest_folder); void UnmountAll(); - std::string GetHostDirectory(const std::string& guest_directory); - std::string GetHostFile(const std::string& guest_file); + + std::filesystem::path GetHostPath(const std::string& guest_directory); + + const MntPair* GetMount(const std::string& guest_path) { + const auto it = std::ranges::find_if(m_mnt_pairs, [&](const auto& mount) { + return guest_path.starts_with(mount.mount); + }); + return it == m_mnt_pairs.end() ? nullptr : &*it; + } private: std::vector m_mnt_pairs; + std::vector path_parts; + tsl::robin_map path_cache; std::mutex m_mutex; }; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index eb6248d0..be173320 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -58,7 +58,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { if (directory) { file->is_directory = true; file->m_guest_name = path; - file->m_host_name = mnt->GetHostDirectory(file->m_guest_name); + file->m_host_name = mnt->GetHostPath(file->m_guest_name); if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist h->DeleteHandle(handle); return ORBIS_KERNEL_ERROR_ENOTDIR; @@ -72,7 +72,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { } } else { file->m_guest_name = path; - file->m_host_name = mnt->GetHostFile(file->m_guest_name); + file->m_host_name = mnt->GetHostPath(file->m_guest_name); int e = 0; if (read) { e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read); @@ -165,8 +165,7 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) { auto* h = Common::Singleton::Instance(); auto* mnt = Common::Singleton::Instance(); - std::string host_path = mnt->GetHostFile(path); - + const auto host_path = mnt->GetHostPath(path); if (host_path.empty()) { return SCE_KERNEL_ERROR_EACCES; } @@ -250,7 +249,7 @@ int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) { return SCE_KERNEL_ERROR_EINVAL; } auto* mnt = Common::Singleton::Instance(); - std::string dir_name = mnt->GetHostFile(path); + const auto dir_name = mnt->GetHostPath(path); if (std::filesystem::exists(dir_name)) { return SCE_KERNEL_ERROR_EEXIST; } @@ -279,7 +278,7 @@ int PS4_SYSV_ABI posix_mkdir(const char* path, u16 mode) { int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) { LOG_INFO(Kernel_Fs, "(PARTIAL) path = {}", path); auto* mnt = Common::Singleton::Instance(); - const auto& path_name = mnt->GetHostFile(path); + const auto path_name = mnt->GetHostPath(path); std::memset(sb, 0, sizeof(OrbisKernelStat)); const bool is_dir = std::filesystem::is_directory(path_name); const bool is_file = std::filesystem::is_regular_file(path_name); @@ -314,7 +313,7 @@ int PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) { int PS4_SYSV_ABI sceKernelCheckReachability(const char* path) { auto* mnt = Common::Singleton::Instance(); - std::string path_name = mnt->GetHostFile(path); + const auto path_name = mnt->GetHostPath(path); if (!std::filesystem::exists(path_name)) { return SCE_KERNEL_ERROR_ENOENT; } diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 9f57ff53..c9073029 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -222,7 +222,7 @@ s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t arg } auto* mnt = Common::Singleton::Instance(); - const auto path = mnt->GetHostFile(moduleFileName); + const auto path = mnt->GetHostPath(moduleFileName); // Load PRX module and relocate any modules that import it. auto* linker = Common::Singleton::Instance(); diff --git a/src/core/libraries/libc/libc_stdio.cpp b/src/core/libraries/libc/libc_stdio.cpp index b1e94676..72337b83 100644 --- a/src/core/libraries/libc/libc_stdio.cpp +++ b/src/core/libraries/libc/libc_stdio.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/assert.h" +#include "common/logging/log.h" #include "common/singleton.h" #include "core/file_sys/fs.h" #include "core/libraries/libc/libc_stdio.h" @@ -10,11 +10,12 @@ namespace Libraries::LibC { std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) { auto* mnt = Common::Singleton::Instance(); - FILE* f = std::fopen(mnt->GetHostFile(filename).c_str(), mode); + const auto host_path = mnt->GetHostPath(filename); + FILE* f = std::fopen(host_path.c_str(), mode); if (f != nullptr) { - LOG_INFO(Lib_LibC, "fopen = {}", mnt->GetHostFile(filename).c_str()); + LOG_INFO(Lib_LibC, "fopen = {}", host_path.native()); } else { - LOG_INFO(Lib_LibC, "fopen can't open = {}", mnt->GetHostFile(filename).c_str()); + LOG_INFO(Lib_LibC, "fopen can't open = {}", host_path.native()); } return f; } diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 7d12ed81..2a2855cc 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -15,7 +15,8 @@ #include "error_codes.h" namespace Libraries::SaveData { -static std::string g_mount_point = "/savedata0"; // temp mount point (todo) + +static constexpr std::string_view g_mount_point = "/savedata0"; // temp mount point (todo) std::string game_serial; int PS4_SYSV_ABI sceSaveDataAbort() { @@ -50,11 +51,11 @@ int PS4_SYSV_ABI sceSaveDataChangeInternal() { int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* check) { auto* mnt = Common::Singleton::Instance(); - std::string mount_dir = mnt->GetHostFile(check->dirName->data); + const auto mount_dir = mnt->GetHostPath(check->dirName->data); if (!std::filesystem::exists(mount_dir)) { return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; } - LOG_INFO(Lib_SaveData, "called = {}", mount_dir); + LOG_INFO(Lib_SaveData, "called = {}", mount_dir.native()); return ORBIS_OK; } @@ -317,14 +318,14 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam return false; } file.Seek(getParam->data->offset); - size_t nbytes = file.ReadRaw(getParam->data->buf, getParam->data->bufSize); + file.ReadRaw(getParam->data->buf, getParam->data->bufSize); LOG_INFO(Lib_SaveData, "called: bufSize = {}, offset = {}", getParam->data->bufSize, getParam->data->offset); } if (getParam->param != nullptr) { - Common::FS::IOFile file1(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); - size_t nbytes = file1.ReadRaw(getParam->param, sizeof(OrbisSaveDataParam)); + Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Read); + file.ReadRaw(getParam->param, sizeof(OrbisSaveDataParam)); } return ORBIS_OK; @@ -394,13 +395,13 @@ int PS4_SYSV_ABI sceSaveDataIsMounted() { int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, OrbisSaveDataIcon* icon) { auto* mnt = Common::Singleton::Instance(); - std::string mount_dir = mnt->GetHostFile(mountPoint->data); - LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir); + const auto mount_dir = mnt->GetHostPath(mountPoint->data); + LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir.native()); if (icon != nullptr) { - Common::FS::IOFile file(mount_dir + "/save_data.png", Common::FS::FileAccessMode::Read); + Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Read); icon->bufSize = file.GetSize(); - size_t nbytes = file.ReadRaw(icon->buf, icon->bufSize); + file.ReadRaw(icon->buf, icon->bufSize); } return ORBIS_OK; } @@ -409,6 +410,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, OrbisSaveDataMountResult* mount_result) { const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / game_serial / dir_name; + auto* mnt = Common::Singleton::Instance(); switch (mount_mode) { case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY: case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: @@ -417,9 +419,8 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, if (!std::filesystem::exists(mount_dir)) { return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; } - auto* mnt = Common::Singleton::Instance(); mount_result->mount_status = 0; - std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + g_mount_point.copy(mount_result->mount_point.data, 16); mnt->Mount(mount_dir, mount_result->mount_point.data); } break; case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE: @@ -431,16 +432,15 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { - auto* mnt = Common::Singleton::Instance(); if (std::filesystem::exists(mount_dir)) { - std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + g_mount_point.copy(mount_result->mount_point.data, 16); mnt->Mount(mount_dir, mount_result->mount_point.data); mount_result->required_blocks = 0; mount_result->mount_status = 0; return ORBIS_SAVE_DATA_ERROR_EXISTS; } if (std::filesystem::create_directories(mount_dir)) { - std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + g_mount_point.copy(mount_result->mount_point.data, 16); mnt->Mount(mount_dir, mount_result->mount_point.data); mount_result->mount_status = 1; } @@ -451,8 +451,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode, if (!std::filesystem::exists(mount_dir)) { std::filesystem::create_directories(mount_dir); } - auto* mnt = Common::Singleton::Instance(); - std::strncpy(mount_result->mount_point.data, g_mount_point.c_str(), 16); + g_mount_point.copy(mount_result->mount_point.data, 16); mnt->Mount(mount_dir, mount_result->mount_point.data); mount_result->mount_status = 1; } break; @@ -534,12 +533,12 @@ int PS4_SYSV_ABI sceSaveDataRestoreLoadSaveDataMemory() { int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, const OrbisSaveDataIcon* icon) { auto* mnt = Common::Singleton::Instance(); - std::string mount_dir = mnt->GetHostFile(mountPoint->data); - LOG_INFO(Lib_SaveData, "called = {}", mount_dir); + const auto mount_dir = mnt->GetHostPath(mountPoint->data); + LOG_INFO(Lib_SaveData, "called = {}", mount_dir.native()); - if (icon != nullptr) { - Common::FS::IOFile file(mount_dir + "/save_data.png", Common::FS::FileAccessMode::Write); - file.WriteRaw((void*)icon->buf, icon->bufSize); + if (icon != nullptr) { + Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Write); + file.WriteRaw(icon->buf, icon->bufSize); } return ORBIS_OK; } @@ -558,12 +557,13 @@ int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, OrbisSaveDataParamType paramType, const void* paramBuf, size_t paramBufSize) { auto* mnt = Common::Singleton::Instance(); - std::string mount_dir = mnt->GetHostFile(mountPoint->data); - LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir, mountPoint->data); + const auto mount_dir = mnt->GetHostPath(mountPoint->data); + LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir.native(), + mountPoint->data); if (paramBuf != nullptr) { - Common::FS::IOFile file(mount_dir + "/param.txt", Common::FS::FileAccessMode::Write); - file.WriteRaw((void*)paramBuf, paramBufSize); + Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Write); + file.WriteRaw(paramBuf, paramBufSize); } return ORBIS_OK; } @@ -711,24 +711,23 @@ int PS4_SYSV_ABI sceSaveDataUmountSys() { int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) { LOG_ERROR(Lib_SaveData, "called = {}", std::string(mountPoint->data)); auto* mnt = Common::Singleton::Instance(); - std::string mount_dir = mnt->GetHostFile(mountPoint->data); + const auto mount_dir = mnt->GetHostPath(mountPoint->data); if (!std::filesystem::exists(mount_dir)) { return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; - } else { - std::filesystem::path mnt_dir(mount_dir); - std::filesystem::create_directories(mnt_dir.parent_path() / "backup"); - - for (const auto& entry : std::filesystem::recursive_directory_iterator(mnt_dir)) { - const auto& path = entry.path(); - std::filesystem::path target_path = mnt_dir.parent_path() / "backup"; - - if (std::filesystem::is_regular_file(path)) { - std::filesystem::copy(path, target_path, - std::filesystem::copy_options::overwrite_existing); - } - } - mnt->Unmount(mount_dir, mountPoint->data); } + + std::filesystem::create_directories(mount_dir.parent_path() / "backup"); + + for (const auto& entry : std::filesystem::recursive_directory_iterator(mount_dir)) { + const auto& path = entry.path(); + const auto target_path = mount_dir.parent_path() / "backup"; + if (std::filesystem::is_regular_file(path)) { + std::filesystem::copy(path, target_path, + std::filesystem::copy_options::overwrite_existing); + } + } + + mnt->Unmount(mount_dir, mountPoint->data); return ORBIS_OK; } From ce6a01bd418913f41d87b3c6a7edf76239aad656 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 03:47:10 +0300 Subject: [PATCH 06/12] clang format --- src/core/file_sys/fs.h | 11 ++++------- src/core/libraries/kernel/event_flag/event_flag_obj.h | 2 +- src/core/libraries/kernel/event_queues.cpp | 3 +-- src/core/libraries/save_data/savedata.cpp | 2 +- src/core/tls.cpp | 8 ++++---- src/shader_recompiler/ir/breadth_first_search.h | 4 ++-- src/shader_recompiler/ir/opcodes.h | 2 +- 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 10fd10c4..ede386e5 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -27,18 +27,15 @@ public: explicit MntPoints() = default; ~MntPoints() = default; - void Mount(const std::filesystem::path& host_folder, - const std::string& guest_folder); - void Unmount(const std::filesystem::path& host_folder, - const std::string& guest_folder); + void Mount(const std::filesystem::path& host_folder, const std::string& guest_folder); + void Unmount(const std::filesystem::path& host_folder, const std::string& guest_folder); void UnmountAll(); std::filesystem::path GetHostPath(const std::string& guest_directory); const MntPair* GetMount(const std::string& guest_path) { - const auto it = std::ranges::find_if(m_mnt_pairs, [&](const auto& mount) { - return guest_path.starts_with(mount.mount); - }); + const auto it = std::ranges::find_if( + m_mnt_pairs, [&](const auto& mount) { return guest_path.starts_with(mount.mount); }); return it == m_mnt_pairs.end() ? nullptr : &*it; } diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h index fe50be69..99ae1981 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.h +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h @@ -20,7 +20,7 @@ public: EventFlagInternal(const std::string& name, ThreadMode thread_mode, QueueMode queue_mode, uint64_t bits) - : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits){}; + : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits) {}; int Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, u32* ptr_micros); int Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result); diff --git a/src/core/libraries/kernel/event_queues.cpp b/src/core/libraries/kernel/event_queues.cpp index e42cc60d..bb3d8ba7 100644 --- a/src/core/libraries/kernel/event_queues.cpp +++ b/src/core/libraries/kernel/event_queues.cpp @@ -134,8 +134,7 @@ s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec* event.timer = std::make_unique( io_context, std::chrono::microseconds(total_us - HrTimerSpinlockThresholdUs)); - event.timer->async_wait( - std::bind(SmallTimerCallback, std::placeholders::_1, eq, event.event)); + event.timer->async_wait(std::bind(SmallTimerCallback, std::placeholders::_1, eq, event.event)); if (!eq->AddEvent(event)) { return ORBIS_KERNEL_ERROR_ENOMEM; diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 2a2855cc..9f3564e8 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -536,7 +536,7 @@ int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, const auto mount_dir = mnt->GetHostPath(mountPoint->data); LOG_INFO(Lib_SaveData, "called = {}", mount_dir.native()); - if (icon != nullptr) { + if (icon != nullptr) { Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Write); file.WriteRaw(icon->buf, icon->bufSize); } diff --git a/src/core/tls.cpp b/src/core/tls.cpp index 2afa5896..0c2d973b 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -9,8 +9,8 @@ #ifdef _WIN32 #include #else -#include /* Definition of ARCH_* constants */ -#include /* Definition of SYS_* constants */ +#include /* Definition of ARCH_* constants */ +#include /* Definition of SYS_* constants */ #endif namespace Core { @@ -93,12 +93,12 @@ static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGe static u32 slot = 0; void SetTcbBase(void* image_address) { - asm volatile("wrgsbase %0" :: "r" (image_address) : "memory"); + asm volatile("wrgsbase %0" ::"r"(image_address) : "memory"); } Tcb* GetTcbBase() { Tcb* tcb; - asm volatile("rdgsbase %0" : "=r" (tcb) :: "memory"); + asm volatile("rdgsbase %0" : "=r"(tcb)::"memory"); return tcb; } diff --git a/src/shader_recompiler/ir/breadth_first_search.h b/src/shader_recompiler/ir/breadth_first_search.h index 21a34a90..be46b48c 100644 --- a/src/shader_recompiler/ir/breadth_first_search.h +++ b/src/shader_recompiler/ir/breadth_first_search.h @@ -12,8 +12,8 @@ namespace Shader::IR { template -auto BreadthFirstSearch(const Value& value, Pred&& pred) - -> std::invoke_result_t { +auto BreadthFirstSearch(const Value& value, + Pred&& pred) -> std::invoke_result_t { if (value.IsImmediate()) { // Nothing to do with immediates return std::nullopt; diff --git a/src/shader_recompiler/ir/opcodes.h b/src/shader_recompiler/ir/opcodes.h index 66b60221..22cc8c2b 100644 --- a/src/shader_recompiler/ir/opcodes.h +++ b/src/shader_recompiler/ir/opcodes.h @@ -52,7 +52,7 @@ constexpr Type F64x2{Type::F64x2}; constexpr Type F64x3{Type::F64x3}; constexpr Type F64x4{Type::F64x4}; -constexpr OpcodeMeta META_TABLE[]{ +constexpr OpcodeMeta META_TABLE[] { #define OPCODE(name_token, type_token, ...) \ { \ .name{#name_token}, \ From 58d1cbd9b7b1c919e498657959b551ee8e13bddd Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:33:57 +0300 Subject: [PATCH 07/12] ssa_rewrite_pass: Correct phi node type for thread bitmask --- src/shader_recompiler/frontend/translate/export.cpp | 2 +- src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/export.cpp b/src/shader_recompiler/frontend/translate/export.cpp index cc631ff2..51840537 100644 --- a/src/shader_recompiler/frontend/translate/export.cpp +++ b/src/shader_recompiler/frontend/translate/export.cpp @@ -7,7 +7,7 @@ namespace Shader::Gcn { void Translator::EXP(const GcnInst& inst) { - if (ir.block->has_multiple_predecessors) { + if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) { LOG_WARNING(Render_Recompiler, "An ambiguous export appeared in translation"); ir.Discard(ir.LogicalNot(ir.GetExec())); } diff --git a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp index 8a24a68b..4699f09a 100644 --- a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp @@ -173,7 +173,7 @@ public: } template - IR::Value ReadVariable(Type variable, IR::Block* root_block) { + IR::Value ReadVariable(Type variable, IR::Block* root_block, bool is_thread_bit = false) { boost::container::small_vector, 64> stack{ ReadState(nullptr), ReadState(root_block), @@ -201,7 +201,7 @@ public: } else if (!block->IsSsaSealed()) { // Incomplete CFG IR::Inst* phi{&*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; - phi->SetFlags(IR::TypeOf(UndefOpcode(variable))); + phi->SetFlags(is_thread_bit ? IR::Type::U1 : IR::TypeOf(UndefOpcode(variable))); incomplete_phis[block].insert_or_assign(variable, phi); stack.back().result = IR::Value{&*phi}; @@ -214,7 +214,7 @@ public: } else { // Break potential cycles with operandless phi IR::Inst* const phi{&*block->PrependNewInst(block->begin(), IR::Opcode::Phi)}; - phi->SetFlags(IR::TypeOf(UndefOpcode(variable))); + phi->SetFlags(is_thread_bit ? IR::Type::U1 : IR::TypeOf(UndefOpcode(variable))); WriteVariable(variable, block, IR::Value{phi}); @@ -263,7 +263,8 @@ private: template IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { for (IR::Block* const imm_pred : block->ImmPredecessors()) { - phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred)); + const bool is_thread_bit = std::is_same_v && phi.Flags() == IR::Type::U1; + phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred, is_thread_bit)); } return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); } @@ -346,7 +347,7 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetThreadBitScalarReg: case IR::Opcode::GetScalarRegister: { const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; - inst.ReplaceUsesWith(pass.ReadVariable(reg, block)); + inst.ReplaceUsesWith(pass.ReadVariable(reg, block, opcode == IR::Opcode::GetThreadBitScalarReg)); break; } case IR::Opcode::GetVectorRegister: { From ba0be91c73a940bccdaf13a880ce8a3f72f60599 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 15 Jul 2024 14:18:28 +0300 Subject: [PATCH 08/12] clang format fix --- src/core/libraries/kernel/event_flag/event_flag_obj.h | 2 +- src/shader_recompiler/ir/breadth_first_search.h | 4 ++-- src/shader_recompiler/ir/opcodes.h | 2 +- src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp | 6 ++++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h index 99ae1981..fe50be69 100644 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.h +++ b/src/core/libraries/kernel/event_flag/event_flag_obj.h @@ -20,7 +20,7 @@ public: EventFlagInternal(const std::string& name, ThreadMode thread_mode, QueueMode queue_mode, uint64_t bits) - : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits) {}; + : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits){}; int Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, u32* ptr_micros); int Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result); diff --git a/src/shader_recompiler/ir/breadth_first_search.h b/src/shader_recompiler/ir/breadth_first_search.h index be46b48c..21a34a90 100644 --- a/src/shader_recompiler/ir/breadth_first_search.h +++ b/src/shader_recompiler/ir/breadth_first_search.h @@ -12,8 +12,8 @@ namespace Shader::IR { template -auto BreadthFirstSearch(const Value& value, - Pred&& pred) -> std::invoke_result_t { +auto BreadthFirstSearch(const Value& value, Pred&& pred) + -> std::invoke_result_t { if (value.IsImmediate()) { // Nothing to do with immediates return std::nullopt; diff --git a/src/shader_recompiler/ir/opcodes.h b/src/shader_recompiler/ir/opcodes.h index 22cc8c2b..66b60221 100644 --- a/src/shader_recompiler/ir/opcodes.h +++ b/src/shader_recompiler/ir/opcodes.h @@ -52,7 +52,7 @@ constexpr Type F64x2{Type::F64x2}; constexpr Type F64x3{Type::F64x3}; constexpr Type F64x4{Type::F64x4}; -constexpr OpcodeMeta META_TABLE[] { +constexpr OpcodeMeta META_TABLE[]{ #define OPCODE(name_token, type_token, ...) \ { \ .name{#name_token}, \ diff --git a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp index 4699f09a..6a43ad6b 100644 --- a/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp @@ -263,7 +263,8 @@ private: template IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { for (IR::Block* const imm_pred : block->ImmPredecessors()) { - const bool is_thread_bit = std::is_same_v && phi.Flags() == IR::Type::U1; + const bool is_thread_bit = + std::is_same_v && phi.Flags() == IR::Type::U1; phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred, is_thread_bit)); } return TryRemoveTrivialPhi(phi, block, UndefOpcode(variable)); @@ -347,7 +348,8 @@ void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) { case IR::Opcode::GetThreadBitScalarReg: case IR::Opcode::GetScalarRegister: { const IR::ScalarReg reg{inst.Arg(0).ScalarReg()}; - inst.ReplaceUsesWith(pass.ReadVariable(reg, block, opcode == IR::Opcode::GetThreadBitScalarReg)); + inst.ReplaceUsesWith( + pass.ReadVariable(reg, block, opcode == IR::Opcode::GetThreadBitScalarReg)); break; } case IR::Opcode::GetVectorRegister: { From 02988891313c523e2c901478fc3d8f3614a2ee8b Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Mon, 15 Jul 2024 14:50:23 +0300 Subject: [PATCH 09/12] windows std::filesystem fixes --- src/core/file_sys/fs.cpp | 2 +- src/core/libraries/kernel/file_system.cpp | 6 +++--- src/core/libraries/libc/libc_stdio.cpp | 6 +++--- src/core/libraries/save_data/savedata.cpp | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index f009dc2d..8f7ec08b 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -74,7 +74,7 @@ std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) bool found_match = false; for (const auto& path : std::filesystem::directory_iterator(current_path)) { const auto candidate = path.path().filename(); - const auto filename = Common::ToLower(candidate); + const auto filename = Common::ToLower(candidate.string()); // Check if a filename matches in case insensitive manner. if (filename != part_low) { continue; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index be173320..f56b05da 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -58,7 +58,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { if (directory) { file->is_directory = true; file->m_guest_name = path; - file->m_host_name = mnt->GetHostPath(file->m_guest_name); + file->m_host_name = mnt->GetHostPath(file->m_guest_name).string(); if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist h->DeleteHandle(handle); return ORBIS_KERNEL_ERROR_ENOTDIR; @@ -72,7 +72,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { } } else { file->m_guest_name = path; - file->m_host_name = mnt->GetHostPath(file->m_guest_name); + file->m_host_name = mnt->GetHostPath(file->m_guest_name).string(); int e = 0; if (read) { e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read); @@ -174,7 +174,7 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) { return SCE_KERNEL_ERROR_EPERM; } - auto* file = h->getFile(host_path); + auto* file = h->getFile(host_path.string()); if (file != nullptr) { file->f.Unlink(); } diff --git a/src/core/libraries/libc/libc_stdio.cpp b/src/core/libraries/libc/libc_stdio.cpp index 72337b83..2b15bd36 100644 --- a/src/core/libraries/libc/libc_stdio.cpp +++ b/src/core/libraries/libc/libc_stdio.cpp @@ -10,12 +10,12 @@ namespace Libraries::LibC { std::FILE* PS4_SYSV_ABI ps4_fopen(const char* filename, const char* mode) { auto* mnt = Common::Singleton::Instance(); - const auto host_path = mnt->GetHostPath(filename); + const auto host_path = mnt->GetHostPath(filename).string(); FILE* f = std::fopen(host_path.c_str(), mode); if (f != nullptr) { - LOG_INFO(Lib_LibC, "fopen = {}", host_path.native()); + LOG_INFO(Lib_LibC, "fopen = {}", host_path); } else { - LOG_INFO(Lib_LibC, "fopen can't open = {}", host_path.native()); + LOG_INFO(Lib_LibC, "fopen can't open = {}", host_path); } return f; } diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 9f3564e8..71828b33 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -55,7 +55,7 @@ int PS4_SYSV_ABI sceSaveDataCheckBackupData(const OrbisSaveDataCheckBackupData* if (!std::filesystem::exists(mount_dir)) { return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; } - LOG_INFO(Lib_SaveData, "called = {}", mount_dir.native()); + LOG_INFO(Lib_SaveData, "called = {}", mount_dir.string()); return ORBIS_OK; } @@ -396,7 +396,7 @@ int PS4_SYSV_ABI sceSaveDataLoadIcon(const OrbisSaveDataMountPoint* mountPoint, OrbisSaveDataIcon* icon) { auto* mnt = Common::Singleton::Instance(); const auto mount_dir = mnt->GetHostPath(mountPoint->data); - LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir.native()); + LOG_INFO(Lib_SaveData, "called: dir = {}", mount_dir.string()); if (icon != nullptr) { Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Read); @@ -534,7 +534,7 @@ int PS4_SYSV_ABI sceSaveDataSaveIcon(const OrbisSaveDataMountPoint* mountPoint, const OrbisSaveDataIcon* icon) { auto* mnt = Common::Singleton::Instance(); const auto mount_dir = mnt->GetHostPath(mountPoint->data); - LOG_INFO(Lib_SaveData, "called = {}", mount_dir.native()); + LOG_INFO(Lib_SaveData, "called = {}", mount_dir.string()); if (icon != nullptr) { Common::FS::IOFile file(mount_dir / "save_data.png", Common::FS::FileAccessMode::Write); @@ -558,7 +558,7 @@ int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, size_t paramBufSize) { auto* mnt = Common::Singleton::Instance(); const auto mount_dir = mnt->GetHostPath(mountPoint->data); - LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir.native(), + LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir.string(), mountPoint->data); if (paramBuf != nullptr) { From 0599f4e6a5f0ccd5a767a7ea1ce4e846e107c6bb Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:38:42 +0300 Subject: [PATCH 10/12] fs: Fix case of getting the mount itself --- src/core/file_sys/fs.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index f009dc2d..ee900a9f 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -31,11 +31,16 @@ std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) return guest_directory; } + // Nothing to do if getting the mount itself. + if (guest_directory == mount->mount) { + return mount->host_path; + } + // Remove device (e.g /app0) from path to retrieve relative path. const u32 pos = mount->mount.size() + 1; const auto rel_path = std::string_view(guest_directory).substr(pos); const auto host_path = mount->host_path / rel_path; - if (!NeedsCaseInsensiveSearch || std::filesystem::exists(host_path)) { + if (!NeedsCaseInsensiveSearch) { return host_path; } @@ -87,7 +92,7 @@ std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) if (!found_match) { // Opening the guest path will surely fail but at least gives // a better error message than the empty path. - return guest_directory; + return host_path; } } From 356b59b041a72941c92147c8347b056f5880ad53 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:51:45 +0300 Subject: [PATCH 11/12] kernel: Remove linux hack * Breaks many games, only benefits BB. Tbd --- src/core/libraries/kernel/thread_management.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index b31e777d..351f12ee 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1002,17 +1002,7 @@ ScePthread PThreadPool::Create() { } } -#ifdef _WIN64 auto* ret = new PthreadInternal{}; -#else - // TODO: Linux specific hack - static u8* hint_address = reinterpret_cast(0x7FFFFC000ULL); - auto* ret = reinterpret_cast( - mmap(hint_address, sizeof(PthreadInternal), PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0)); - hint_address += Common::AlignUp(sizeof(PthreadInternal), 4_KB); -#endif - ret->is_free = false; ret->is_detached = false; ret->is_almost_done = false; From 3c8b3f9a290f99368814465e0c5a13ac6921c942 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Mon, 15 Jul 2024 15:14:04 +0300 Subject: [PATCH 12/12] fs: Remove some unnecessary string conversions --- src/core/file_sys/fs.cpp | 11 +++-------- src/core/file_sys/fs.h | 4 ++-- src/core/libraries/kernel/file_system.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index bfbd6737..5f462937 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -131,14 +131,9 @@ File* HandleTable::GetFile(int d) { 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) { - if (file != nullptr && file->m_host_name == host_name) { - return file; - } - } - return nullptr; +File* HandleTable::GetFile(const std::filesystem::path& host_name) { + const auto it = std::ranges::find(m_files, host_name, &File::m_host_name); + return it == m_files.end() ? nullptr : *it; } } // namespace Core::FileSys diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index ede386e5..d636f8bf 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -54,7 +54,7 @@ struct DirEntry { struct File { std::atomic_bool is_opened{}; std::atomic_bool is_directory{}; - std::string m_host_name; + std::filesystem::path m_host_name; std::string m_guest_name; Common::FS::IOFile f; std::vector dirents; @@ -70,7 +70,7 @@ public: int CreateHandle(); void DeleteHandle(int d); File* GetFile(int d); - File* getFile(const std::string& host_name); + File* GetFile(const std::filesystem::path& host_name); private: std::vector m_files; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index f56b05da..23b949a8 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -13,7 +13,7 @@ namespace Libraries::Kernel { -std::vector GetDirectoryEntries(const std::string& path) { +std::vector GetDirectoryEntries(const std::filesystem::path& path) { std::vector files; for (const auto& entry : std::filesystem::directory_iterator(path)) { auto& dir_entry = files.emplace_back(); @@ -58,7 +58,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { if (directory) { file->is_directory = true; file->m_guest_name = path; - file->m_host_name = mnt->GetHostPath(file->m_guest_name).string(); + file->m_host_name = mnt->GetHostPath(file->m_guest_name); if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist h->DeleteHandle(handle); return ORBIS_KERNEL_ERROR_ENOTDIR; @@ -72,7 +72,7 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { } } else { file->m_guest_name = path; - file->m_host_name = mnt->GetHostPath(file->m_guest_name).string(); + file->m_host_name = mnt->GetHostPath(file->m_guest_name); int e = 0; if (read) { e = file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read); @@ -174,7 +174,7 @@ int PS4_SYSV_ABI sceKernelUnlink(const char* path) { return SCE_KERNEL_ERROR_EPERM; } - auto* file = h->getFile(host_path.string()); + auto* file = h->GetFile(host_path); if (file != nullptr) { file->f.Unlink(); }