diff --git a/.gitignore b/.gitignore index f25ceb1..f8d0965 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ ehthumbs.db .vs/ .idea/ +.vscode/ \ No newline at end of file diff --git a/src/SharpEmu.HLE/GuestTlsTemplate.cs b/src/SharpEmu.HLE/GuestTlsTemplate.cs index 65cf835..c6303bc 100644 --- a/src/SharpEmu.HLE/GuestTlsTemplate.cs +++ b/src/SharpEmu.HLE/GuestTlsTemplate.cs @@ -17,7 +17,7 @@ public static class GuestTlsTemplate // Must match CpuDispatcher/DirectExecutionBackend's mapped prefix. PS5 // modules can require more than one host page of Variant II static TLS; // Dreaming Sarah's startup image, for example, reaches 0x1870 bytes. - public const ulong StartupStaticTlsReservation = 0x10000UL; + public const ulong StartupStaticTlsReservation = 0x20000UL; // Was 0x10000UL, but thats too small for GTA V private static readonly object _gate = new(); private static readonly SortedDictionary _modules = new(); private static readonly Dictionary _threadDtvs = new(); diff --git a/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs b/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs index 80e7e42..9ea4e43 100644 --- a/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs +++ b/src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs @@ -3455,7 +3455,7 @@ public static partial class KernelMemoryCompatExports public static int KernelDirectMemoryQuery(CpuContext ctx) { var offset = ctx[CpuRegister.Rdi]; - _ = ctx[CpuRegister.Rsi]; // flags + var flags = ctx[CpuRegister.Rsi]; var infoAddress = ctx[CpuRegister.Rdx]; var infoSize = ctx[CpuRegister.Rcx]; if (infoAddress == 0 || infoSize < 24) @@ -3463,27 +3463,49 @@ public static partial class KernelMemoryCompatExports return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT; } + if (offset >= DirectMemorySizeBytes) + { + // Real hardware returns EACCES here (0x8002000D), not ENOENT. + return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_DELETED; + } + + var findNext = (flags & 1) != 0; + var found = false; + var matchStart = 0UL; + var matchEnd = 0UL; + var matchMemoryType = 0; + lock (_memoryGate) { - foreach (var block in _directAllocations.Values) + var candidates = _directAllocations.Values + .Where(block => findNext + ? block.Start + block.Length > offset + : offset >= block.Start && offset < block.Start + block.Length) + .OrderBy(block => block.Start); + + foreach (var block in candidates) { - if (offset < block.Start || offset >= block.Start + block.Length) - { - continue; - } - - if (!ctx.TryWriteUInt64(infoAddress, block.Start) || - !ctx.TryWriteUInt64(infoAddress + sizeof(ulong), block.Start + block.Length) || - !TryWriteInt32(ctx, infoAddress + (sizeof(ulong) * 2), block.MemoryType)) - { - return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; - } - - return (int)OrbisGen2Result.ORBIS_GEN2_OK; + found = true; + matchStart = block.Start; + matchEnd = block.Start + block.Length; + matchMemoryType = block.MemoryType; + break; } } - return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND; + if (!found) + { + return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_DELETED; + } + + if (!ctx.TryWriteUInt64(infoAddress, matchStart) || + !ctx.TryWriteUInt64(infoAddress + sizeof(ulong), matchEnd) || + !TryWriteInt32(ctx, infoAddress + (sizeof(ulong) * 2), matchMemoryType)) + { + return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; + } + + return (int)OrbisGen2Result.ORBIS_GEN2_OK; } ///