[Kernel] Implement sceKernelMapDirectMemory2 (#433)

The "2" variant of sceKernelMapDirectMemory was unimplemented, so titles
that call it (seen in Gex Trilogy) got an unresolved import that returned
an error the guest then used as a mapped address.

v2 inserts a memoryType argument ahead of v1's protection, shifting the
remaining arguments down one register and pushing alignment onto the
stack. Extract v1's body into a shared MapDirectMemoryCore and route both
exports through it; v2 reads its shifted arguments and the stack alignment
and accepts the memoryType (which only selects cache/GPU attributes this
HLE does not model per mapping, so it does not affect placement).
This commit is contained in:
Nicola Pomarico
2026-07-19 13:35:40 +02:00
committed by GitHub
parent e56e74f960
commit d7f6e3f578
@@ -2827,12 +2827,51 @@ public static partial class KernelMemoryCompatExports
LibraryName = "libKernel")] LibraryName = "libKernel")]
public static int KernelMapDirectMemory(CpuContext ctx) public static int KernelMapDirectMemory(CpuContext ctx)
{ {
var inOutAddressPointer = ctx[CpuRegister.Rdi]; return MapDirectMemoryCore(
var length = ctx[CpuRegister.Rsi]; ctx,
var protection = unchecked((int)ctx[CpuRegister.Rdx]); inOutAddressPointer: ctx[CpuRegister.Rdi],
var flags = ctx[CpuRegister.Rcx]; length: ctx[CpuRegister.Rsi],
var directMemoryStart = ctx[CpuRegister.R8]; protection: unchecked((int)ctx[CpuRegister.Rdx]),
var alignment = ctx[CpuRegister.R9]; flags: ctx[CpuRegister.Rcx],
directMemoryStart: ctx[CpuRegister.R8],
alignment: ctx[CpuRegister.R9]);
}
[SysAbiExport(
Nid = "BQQniolj9tQ",
ExportName = "sceKernelMapDirectMemory2",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libKernel")]
public static int KernelMapDirectMemory2(CpuContext ctx)
{
// The "2" variant inserts a memoryType argument (rdx) ahead of v1's
// protection, shifting protection/flags/directMemoryStart down one
// register each and pushing alignment onto the stack (the 7th argument,
// at [rsp + 8], above the return address). The memoryType only selects
// cache/GPU access attributes, which this HLE does not model per
// mapping, so it is accepted but does not affect placement.
ulong alignment = 0;
_ = ctx.TryReadUInt64(ctx[CpuRegister.Rsp] + sizeof(ulong), out alignment);
return MapDirectMemoryCore(
ctx,
inOutAddressPointer: ctx[CpuRegister.Rdi],
length: ctx[CpuRegister.Rsi],
protection: unchecked((int)ctx[CpuRegister.Rcx]),
flags: ctx[CpuRegister.R8],
directMemoryStart: ctx[CpuRegister.R9],
alignment: alignment);
}
private static int MapDirectMemoryCore(
CpuContext ctx,
ulong inOutAddressPointer,
ulong length,
int protection,
ulong flags,
ulong directMemoryStart,
ulong alignment)
{
if (ShouldTraceDirectMemory()) if (ShouldTraceDirectMemory())
{ {
Console.Error.WriteLine( Console.Error.WriteLine(