From e5c406d809a6f5a177ecf3699f0ebd3a32f3ddc0 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 24 May 2026 01:42:31 -0500 Subject: [PATCH] Upstreaming valid changes from others (#4469) * Fix nids for strcmp vs strncmp Co-Authored-By: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> * Fix sign_bit_set logic Co-Authored-By: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> * Fix IterateDirectory on mounts IterateDirectory would just retrieve the base path when trying to iterate /app0, since GetHostPath for the other path types would still return the base path. Co-Authored-By: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> * Fix function resolves If multiple modules export the same library and module, then we would only check the first one we find for the symbol. This can end up breaking the font library stack Co-Authored-By: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> * Update fs.cpp Co-Authored-By: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> * Oops --------- Co-authored-by: m33ts4k0z <3597723+m33ts4k0z@users.noreply.github.com> --- src/core/file_sys/fs.cpp | 27 ++++++++++++------ .../libc_internal/libc_internal_str.cpp | 4 +-- src/core/linker.cpp | 22 +++++++-------- src/core/linker.h | 2 -- .../backend/spirv/emit_spirv_atomic.cpp | 28 +++++++++++++------ 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index e694e636a..e9157d48a 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -63,25 +63,36 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea *is_read_only = mount->read_only; } - // Nothing to do if getting the mount itself. const auto corrected_path_sanitized = RemoveTrailingSlashes(corrected_path); - if (corrected_path_sanitized == mount->mount) { - return mount->host_path; - } + std::filesystem::path host_path = mount->host_path; - // Remove device (e.g /app0) from path to retrieve relative path. - const auto rel_path = std::string_view{corrected_path}.substr(mount->mount.size() + 1); - std::filesystem::path host_path = mount->host_path / rel_path; + // Update folder is either mount + "-UPDATE" or mount + "-patch" std::filesystem::path patch_path = mount->host_path; patch_path += "-UPDATE"; if (!std::filesystem::exists(patch_path)) { patch_path = mount->host_path; patch_path += "-patch"; } - patch_path /= rel_path; + // Mods folder can only be at mount + "-mods" std::filesystem::path mods_path = mount->host_path; mods_path += "-mods"; + + // If we're just retrieving the mount, return the correct mount path. + if (corrected_path_sanitized == mount->mount) { + if (path_type == HostPathType::Mod) { + return mods_path; + } else if (path_type == HostPathType::Patch) { + return patch_path; + } else { + return host_path; + } + } + + // Remove device (e.g /app0) from path to retrieve relative path. + const auto rel_path = std::string_view{corrected_path}.substr(mount->mount.size() + 1); + host_path /= rel_path; + patch_path /= rel_path; mods_path /= rel_path; if (path_type == HostPathType::Mod) { diff --git a/src/core/libraries/libc_internal/libc_internal_str.cpp b/src/core/libraries/libc_internal/libc_internal_str.cpp index a7997a193..e5c2e64bc 100644 --- a/src/core/libraries/libc_internal/libc_internal_str.cpp +++ b/src/core/libraries/libc_internal/libc_internal_str.cpp @@ -63,8 +63,8 @@ const char* PS4_SYSV_ABI internal_strchr(const char* str, int c) { void RegisterlibSceLibcInternalStr(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("5Xa2ACNECdo", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strcpy_s); LIB_FUNCTION("K+gcnFFJKVc", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strcat_s); - LIB_FUNCTION("aesyjrHVWy4", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strcmp); - LIB_FUNCTION("Ovb2dSJOAuE", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strncmp); + LIB_FUNCTION("Ovb2dSJOAuE", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strcmp); + LIB_FUNCTION("aesyjrHVWy4", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strncmp); LIB_FUNCTION("j4ViWNHEgww", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strlen); LIB_FUNCTION("6sJWiWSRuqk", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strncpy); LIB_FUNCTION("YNzNkJzYqEg", "libSceLibcInternal", 1, "libSceLibcInternal", internal_strncpy_s); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index edf5b6f36..720aa9650 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -326,14 +326,6 @@ void Linker::Relocate(Module* module) { }); } -const Module* Linker::FindExportedModule(const ModuleInfo& module, const LibraryInfo& library) { - const auto it = std::ranges::find_if(m_modules, [&](const auto& m) { - return std::ranges::contains(m->GetExportLibs(), library) && - std::ranges::contains(m->GetExportModules(), module); - }); - return it == m_modules.end() ? nullptr : it->get(); -} - bool Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Module* m, Loader::SymbolRecord* return_info) { const auto ids = Common::SplitString(name, '#'); @@ -362,10 +354,16 @@ bool Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Modul return true; } - // Check if it an export function - const auto* p = FindExportedModule(*module, *library); - if (p && p->export_sym.GetSize() > 0) { - record = p->export_sym.FindSymbol(sr); + // Check if it an exported function from one of our loaded libraries + for (const auto& mod : m_modules) { + if (!std::ranges::contains(mod->GetExportLibs(), *library) || + !std::ranges::contains(mod->GetExportModules(), *module)) { + continue; + } + if (mod->export_sym.GetSize() == 0) { + continue; + } + record = mod->export_sym.FindSymbol(sr); if (record) { *return_info = *record; return true; diff --git a/src/core/linker.h b/src/core/linker.h index 895901f08..f210c2e57 100644 --- a/src/core/linker.h +++ b/src/core/linker.h @@ -155,8 +155,6 @@ public: void DebugDump(); private: - const Module* FindExportedModule(const ModuleInfo& m, const LibraryInfo& l); - MemoryManager* memory; Libraries::Kernel::Thread main_thread; std::mutex mutex; diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 806169217..4273b8f0a 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -252,8 +252,11 @@ Id EmitBufferAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre } const auto u32_value = ctx.OpBitcast(ctx.U32[1], value); - const auto sign_bit_set = - ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); + // OpSelect requires a bool condition; produce one by comparing the sign bit to 0. + const auto sign_bit_set = ctx.OpINotEqual( + ctx.U1[1], + ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)), + ctx.u32_zero_value); // FIXME this needs control flow because it currently executes both atomics const auto result = ctx.OpSelect( @@ -287,8 +290,11 @@ Id EmitBufferAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre } const auto u32_value = ctx.OpBitcast(ctx.U32[1], value); - const auto sign_bit_set = - ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); + // OpSelect requires a bool condition; produce one by comparing the sign bit to 0. + const auto sign_bit_set = ctx.OpINotEqual( + ctx.U1[1], + ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)), + ctx.u32_zero_value); // FIXME this needs control flow because it currently executes both atomics const auto result = ctx.OpSelect( @@ -364,8 +370,11 @@ Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords } const auto u32_value = ctx.OpBitcast(ctx.U32[1], value); - const auto sign_bit_set = - ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); + // OpSelect requires a bool condition; produce one by comparing the sign bit to 0. + const auto sign_bit_set = ctx.OpINotEqual( + ctx.U1[1], + ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)), + ctx.u32_zero_value); const auto result = ctx.OpSelect( ctx.F32[1], sign_bit_set, @@ -381,8 +390,11 @@ Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords } const auto u32_value = ctx.OpBitcast(ctx.U32[1], value); - const auto sign_bit_set = - ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); + // OpSelect requires a bool condition; produce one by comparing the sign bit to 0. + const auto sign_bit_set = ctx.OpINotEqual( + ctx.U1[1], + ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)), + ctx.u32_zero_value); const auto result = ctx.OpSelect( ctx.F32[1], sign_bit_set,