Files
sharpemu/src/SharpEmu.Libs/LibcInternalExports.cs
T

79 lines
2.5 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using System.Runtime.InteropServices;
using SharpEmu.HLE;
namespace SharpEmu.Libs.LibcInternal;
public static class LibcInternalExports
{
private const ulong HeapTraceInfoSize = 32;
private const int HeapTraceTableEntryCount = 64;
private const int HeapTraceMaskOffset = 0;
private const int HeapTraceTableOffset = HeapTraceMaskOffset + sizeof(ulong);
private const int HeapTraceStorageSize = HeapTraceTableOffset + (HeapTraceTableEntryCount * sizeof(ulong));
private static readonly object _heapTraceGate = new();
private static nint _heapTraceStorage;
[SysAbiExport(
Nid = "NWtTN10cJzE",
ExportName = "LibcHeapGetTraceInfo",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "LibcInternalExt")]
public static int LibcHeapGetTraceInfo(CpuContext ctx)
{
var infoAddress = ctx[CpuRegister.Rdi];
if (infoAddress == 0 || !ctx.TryReadUInt64(infoAddress, out var size) || size != HeapTraceInfoSize)
{
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
}
var storage = EnsureHeapTraceStorage();
if (storage == 0)
{
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}
var maskAddress = unchecked((ulong)(storage + HeapTraceMaskOffset));
var tableAddress = unchecked((ulong)(storage + HeapTraceTableOffset));
if (!ctx.TryWriteUInt64(infoAddress + 16, maskAddress) ||
!ctx.TryWriteUInt64(infoAddress + 24, tableAddress))
{
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
private static nint EnsureHeapTraceStorage()
{
lock (_heapTraceGate)
{
if (_heapTraceStorage != 0)
{
return _heapTraceStorage;
}
var storage = Marshal.AllocHGlobal(HeapTraceStorageSize);
if (storage == 0)
{
return 0;
}
unsafe
{
NativeMemory.Clear((void*)storage, (nuint)HeapTraceStorageSize);
}
_heapTraceStorage = storage;
return storage;
}
}
}