Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/SharpEmu.Libs/Ampr/AmprFileRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static bool TryGetHostPath(uint id, out string hostPath)
return _hostPathsById.TryGetValue(id, out hostPath!);
}

private static uint ComputeFileId(string guestPath)
internal static uint ComputeFileId(string guestPath)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(guestPath);

Expand Down
69 changes: 50 additions & 19 deletions src/SharpEmu.Libs/Kernel/KernelMemoryCompatExports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1689,15 +1689,15 @@ public static int KernelAprResolveFilepathsToIdsAndFileSizes(CpuContext ctx)
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
}

var entryCount = (int)count;
Span<uint> localIds = count <= 256 ? stackalloc uint[entryCount] : new uint[entryCount];
Span<ulong> localSizes = count <= 128 ? stackalloc ulong[entryCount] : new ulong[entryCount];
var resolvedGuestPaths = new string[entryCount];
var resolvedHostPaths = new string[entryCount];

for (ulong i = 0; i < count; i++)
{
if (idsAddress != 0 &&
!TryWriteUInt32Compat(ctx, idsAddress + (i * sizeof(uint)), uint.MaxValue))
{
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

var index = (int)i;
if (!TryResolveAprFilepath(ctx, pathListAddress, i, out var guestPath))
{
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
Expand All @@ -1712,23 +1712,47 @@ public static int KernelAprResolveFilepathsToIdsAndFileSizes(CpuContext ctx)
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
}

var fileId = AmprFileRegistry.Register(guestPath, hostPath);
var fileId = AmprFileRegistry.ComputeFileId(guestPath);
LogIoTrace("apr_resolve", guestPath, $"host='{hostPath}' index={i} count={count} id=0x{fileId:X8} size={fileSize}");

if (idsAddress != 0 &&
!TryWriteUInt32Compat(ctx, idsAddress + (i * sizeof(uint)), fileId))
localIds[index] = fileId;
localSizes[index] = fileSize;
resolvedGuestPaths[index] = guestPath;
resolvedHostPaths[index] = hostPath;
}

Span<byte> sizePayload = count <= 64 ? stackalloc byte[entryCount * sizeof(ulong)] : new byte[entryCount * sizeof(ulong)];
for (ulong i = 0; i < count; i++)
{
BinaryPrimitives.WriteUInt64LittleEndian(sizePayload[(int)(i * sizeof(ulong))..], localSizes[(int)i]);
}

if (!TryWriteCompat(ctx, sizesAddress, sizePayload))
{
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

if (idsAddress != 0)
{
Span<byte> idPayload = count <= 128 ? stackalloc byte[entryCount * sizeof(uint)] : new byte[entryCount * sizeof(uint)];
for (ulong i = 0; i < count; i++)
{
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
BinaryPrimitives.WriteUInt32LittleEndian(idPayload[(int)(i * sizeof(uint))..], localIds[(int)i]);
}

if (!TryWriteUInt64Compat(ctx, sizesAddress + (i * sizeof(ulong)), fileSize))
if (!TryWriteCompat(ctx, idsAddress, idPayload))
{
KernelRuntimeCompatExports.TrySetErrno(ctx, Efault);
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}
}

for (var i = 0; i < entryCount; i++)
{
AmprFileRegistry.Register(resolvedGuestPaths[i], resolvedHostPaths[i]);
}

ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
Expand Down Expand Up @@ -6350,19 +6374,19 @@ private static int KernelGetdirentriesCore(CpuContext ctx, int fd, ulong bufferA
}

var currentIndex = directory.NextIndex;
if (basePointerAddress != 0 && !TryWriteUInt64Compat(ctx, basePointerAddress, (ulong)currentIndex))
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

if (currentIndex >= directory.Entries.Length)
{
if (basePointerAddress != 0 &&
!TryWriteUInt64Compat(ctx, basePointerAddress, (ulong)currentIndex))
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}

var entryName = directory.Entries[currentIndex];
directory.NextIndex = currentIndex + 1;

var entryBytes = Encoding.UTF8.GetBytes(entryName);
var nameLength = Math.Min(entryBytes.Length, 255);
Expand All @@ -6381,6 +6405,13 @@ private static int KernelGetdirentriesCore(CpuContext ctx, int fd, ulong bufferA
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

if (basePointerAddress != 0 &&
!TryWriteUInt64Compat(ctx, basePointerAddress, (ulong)currentIndex))
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}

directory.NextIndex = currentIndex + 1;
ctx[CpuRegister.Rax] = 512;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
Expand Down