Fix NID BHouLQzh0X0, doubled StartupStaticTlsReservation memory. Both needed to launch GTA V. (#454)

* Increased StartupStaticTlsReservation (doubled) and fixed mistake in NID BHouLQzh0X0. Now GTA V RAGE engine seems to start loading.

* fixed NID BHouLQzh0X0, this had an issue causing GTA V not to load. Also doubled StartupStaticTlsReservation.

* Removed .vscode folder and reverted global.json
This commit is contained in:
Job Meijer
2026-07-20 13:37:30 +02:00
committed by GitHub
parent db9b20481c
commit a1cbff8a9c
3 changed files with 40 additions and 17 deletions
+1
View File
@@ -42,3 +42,4 @@ ehthumbs.db
.vs/
.idea/
.vscode/
+1 -1
View File
@@ -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<ulong, ModuleTemplate> _modules = new();
private static readonly Dictionary<ulong, ThreadDtv> _threadDtvs = new();
@@ -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;
}
/// <summary>