From ce8f75411afdd16944740da052b186f790aa2020 Mon Sep 17 00:00:00 2001 From: Berk Date: Sun, 5 Jul 2026 22:10:37 +0300 Subject: [PATCH] [unity-fixes] support for Media/Modules/*.prx files (#27) --- .../Native/DirectExecutionBackend.Imports.cs | 68 ++++++++++++++++++- src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs | 6 +- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/SharpEmu.Core/Cpu/Native/DirectExecutionBackend.Imports.cs b/src/SharpEmu.Core/Cpu/Native/DirectExecutionBackend.Imports.cs index 8e084c7..b081dc0 100644 --- a/src/SharpEmu.Core/Cpu/Native/DirectExecutionBackend.Imports.cs +++ b/src/SharpEmu.Core/Cpu/Native/DirectExecutionBackend.Imports.cs @@ -338,10 +338,15 @@ public sealed partial class DirectExecutionBackend { orbisGen2Result = DispatchBootstrapBridge(); } - else if (string.Equals(importStubEntry.Nid, RuntimeStubNids.KernelDynlibDlsym, StringComparison.Ordinal)) + else if (string.Equals(importStubEntry.Nid, RuntimeStubNids.KernelDynlibDlsym, StringComparison.Ordinal) || + string.Equals(importStubEntry.Nid, "LwG8g3niqwA", StringComparison.Ordinal)) { orbisGen2Result = DispatchKernelDynlibDlsym(); } + else if (string.Equals(importStubEntry.Nid, "r8mvOaWdi28", StringComparison.Ordinal)) + { + orbisGen2Result = DispatchIl2CppApiLookupSymbol(); + } else if (importStubEntry.Export is { } cachedExport && (cachedExport.Target & cpuContext.TargetGeneration) != 0) { @@ -1180,8 +1185,11 @@ public sealed partial class DirectExecutionBackend cpuContext[CpuRegister.Rax] = 18446744073709551615uL; return OrbisGen2Result.ORBIS_GEN2_OK; } - if (!TryResolveRuntimeSymbolAddress(symbolName, out var resolvedAddress)) + if (!TryResolveRuntimeSymbolAddress(symbolName, out var resolvedAddress) && + !TryResolveRuntimeSymbolAlias(symbolName, out resolvedAddress)) { + Console.Error.WriteLine( + $"[LOADER][WARN] sceKernelDlsym failed: handle=0x{cpuContext[CpuRegister.Rdi]:X} symbol='{symbolName}'"); cpuContext[CpuRegister.Rax] = 18446744073709551615uL; return OrbisGen2Result.ORBIS_GEN2_OK; } @@ -1194,6 +1202,62 @@ public sealed partial class DirectExecutionBackend return OrbisGen2Result.ORBIS_GEN2_OK; } + private bool TryResolveRuntimeSymbolAlias(string symbolName, out ulong address) + { + address = 0; + var alias = symbolName switch + { + "scriptingGetMem" => "malloc", + "scriptingFreeMem" => "free", + "scriptingRealloc" => "realloc", + "scriptingCalloc" => "calloc", + _ => null, + }; + + return alias != null && TryResolveRuntimeSymbolAddress(alias, out address); + } + + private OrbisGen2Result DispatchIl2CppApiLookupSymbol() + { + var cpuContext = ActiveCpuContext; + if (cpuContext == null) + { + return OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT; + } + + var symbolNameAddress = cpuContext[CpuRegister.Rdi]; + var outputAddress = cpuContext[CpuRegister.Rsi]; + if (!TryReadAsciiZ(symbolNameAddress, 512, out var symbolName) || + outputAddress == 0 || + !TryResolveIl2CppApiAddress(symbolName, out var resolvedAddress) || + !TryWriteUInt64Compat(outputAddress, resolvedAddress)) + { + Console.Error.WriteLine( + $"[LOADER][WARN] il2cpp_api_lookup_symbol failed: name='{symbolName}' out=0x{outputAddress:X16}"); + if (outputAddress != 0) + { + _ = TryWriteUInt64Compat(outputAddress, 0); + } + + cpuContext[CpuRegister.Rax] = ulong.MaxValue; + return OrbisGen2Result.ORBIS_GEN2_OK; + } + + cpuContext[CpuRegister.Rax] = 0; + return OrbisGen2Result.ORBIS_GEN2_OK; + } + + private bool TryResolveIl2CppApiAddress(string symbolName, out ulong address) + { + if (TryResolveRuntimeSymbolAddress(symbolName, out address)) + { + return true; + } + + return Aerolib.Instance.TryGetByExportName(symbolName, out var symbol) && + TryResolveRuntimeSymbolAddress(symbol.Nid, out address); + } + private OrbisGen2Result DispatchBootstrapBridge() { var cpuContext = ActiveCpuContext; diff --git a/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs b/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs index 1b7601a..eab36fa 100644 --- a/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs +++ b/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs @@ -543,6 +543,7 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime { Path.Combine(ebootDirectory, "sce_module"), Path.Combine(ebootDirectory, "sce_modules"), + Path.Combine(ebootDirectory, "Media", "Modules"), } .Distinct(StringComparer.OrdinalIgnoreCase) .Where(Directory.Exists) @@ -554,7 +555,9 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime } var allModulePaths = moduleDirectories - .SelectMany(Directory.EnumerateFiles) + .SelectMany(directory => Directory + .EnumerateFiles(directory) + .OrderBy(path => path, StringComparer.OrdinalIgnoreCase)) .Where(path => { var extension = Path.GetExtension(path); @@ -562,7 +565,6 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime string.Equals(extension, ".sprx", StringComparison.OrdinalIgnoreCase); }) .Distinct(StringComparer.OrdinalIgnoreCase) - .OrderBy(path => path, StringComparer.OrdinalIgnoreCase) .ToArray(); var modulePaths = allModulePaths