[fixes] move repeating methods into CpuContext (#41)

This commit is contained in:
Dawid
2026-07-10 22:46:50 +02:00
committed by GitHub
parent c0fd6a80e8
commit 29021b5a71
31 changed files with 527 additions and 770 deletions
+71
View File
@@ -138,6 +138,51 @@ public sealed class CpuContext(ICpuMemory memory, Generation generation)
return true; return true;
} }
public bool TryReadUInt16(ulong address, out ushort value)
{
Span<byte> bytes = stackalloc byte[sizeof(ushort)];
if (!Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadUInt16LittleEndian(bytes);
return true;
}
public bool TryWriteUInt16(ulong address, ushort value)
{
Span<byte> buffer = stackalloc byte[sizeof(ushort)];
BinaryPrimitives.WriteUInt16LittleEndian(buffer, value);
return Memory.TryWrite(address, buffer);
}
public bool TryReadInt32(ulong address, out int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
if (!Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadInt32LittleEndian(bytes);
return true;
}
public bool TryWriteInt32(ulong address, int value, bool checkNil = false)
{
if (checkNil && address == 0)
{
return false;
}
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return Memory.TryWrite(address, bytes);
}
public bool TryReadUInt32(ulong address, out uint value) public bool TryReadUInt32(ulong address, out uint value)
{ {
Span<byte> buffer = stackalloc byte[sizeof(uint)]; Span<byte> buffer = stackalloc byte[sizeof(uint)];
@@ -158,6 +203,13 @@ public sealed class CpuContext(ICpuMemory memory, Generation generation)
return Memory.TryWrite(address, buffer); return Memory.TryWrite(address, buffer);
} }
public bool TryWriteInt64(ulong address, long value)
{
Span<byte> buffer = stackalloc byte[sizeof(long)];
BinaryPrimitives.WriteInt64LittleEndian(buffer, value);
return Memory.TryWrite(address, buffer);
}
public bool TryReadUInt64(ulong address, out ulong value) public bool TryReadUInt64(ulong address, out ulong value)
{ {
Span<byte> buffer = stackalloc byte[sizeof(ulong)]; Span<byte> buffer = stackalloc byte[sizeof(ulong)];
@@ -224,4 +276,23 @@ public sealed class CpuContext(ICpuMemory memory, Generation generation)
this[CpuRegister.Rsp] = rsp + sizeof(ulong); this[CpuRegister.Rsp] = rsp + sizeof(ulong);
return true; return true;
} }
public int SetReturn(int result, Type? cast = null)
{
var value = cast switch
{
null => (ulong)result,
_ when cast == typeof(long) => (ulong)(long)result,
_ => throw new NotSupportedException(),
};
this[CpuRegister.Rax] = unchecked(value);
return result;
}
public int SetReturn(OrbisGen2Result result)
{
this[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
}
} }
+51 -57
View File
@@ -407,11 +407,11 @@ public static class AgcExports
var version = (uint)ctx[CpuRegister.Rsi]; var version = (uint)ctx[CpuRegister.Rsi];
if (stateAddress == 0 || !IsSupportedRegisterDefaultsVersion(version)) if (stateAddress == 0 || !IsSupportedRegisterDefaultsVersion(version))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
TraceAgc($"agc.init state=0x{stateAddress:X16} version={version}"); TraceAgc($"agc.init state=0x{stateAddress:X16} version={version}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -442,19 +442,19 @@ public static class AgcExports
var codeAddress = ctx[CpuRegister.Rdx]; var codeAddress = ctx[CpuRegister.Rdx];
if (headerAddress == 0 || codeAddress == 0) if (headerAddress == 0 || codeAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadUInt32(headerAddress, out var fileHeader) || if (!ctx.TryReadUInt32(headerAddress, out var fileHeader) ||
!ctx.TryReadUInt32(headerAddress + sizeof(uint), out var version)) !ctx.TryReadUInt32(headerAddress + sizeof(uint), out var version))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (fileHeader != ShaderFileHeader || version != ShaderVersion) if (fileHeader != ShaderFileHeader || version != ShaderVersion)
{ {
TraceCreateShader(destinationAddress, headerAddress, codeAddress, $"invalid-header file=0x{fileHeader:X8} version=0x{version:X8}"); TraceCreateShader(destinationAddress, headerAddress, codeAddress, $"invalid-header file=0x{fileHeader:X8} version=0x{version:X8}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!RelocatePointerField(ctx, headerAddress + ShaderCxRegistersOffset) || if (!RelocatePointerField(ctx, headerAddress + ShaderCxRegistersOffset) ||
@@ -465,12 +465,12 @@ public static class AgcExports
!RelocatePointerField(ctx, headerAddress + ShaderOutputSemanticsOffset) || !RelocatePointerField(ctx, headerAddress + ShaderOutputSemanticsOffset) ||
!ctx.TryWriteUInt64(headerAddress + ShaderCodeOffset, codeAddress)) !ctx.TryWriteUInt64(headerAddress + ShaderCodeOffset, codeAddress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (!ctx.TryReadUInt64(headerAddress + ShaderUserDataOffset, out var userDataAddress)) if (!ctx.TryReadUInt64(headerAddress + ShaderUserDataOffset, out var userDataAddress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (userDataAddress != 0 && if (userDataAddress != 0 &&
@@ -480,18 +480,18 @@ public static class AgcExports
!RelocatePointerField(ctx, userDataAddress + 0x18) || !RelocatePointerField(ctx, userDataAddress + 0x18) ||
!RelocatePointerField(ctx, userDataAddress + 0x20))) !RelocatePointerField(ctx, userDataAddress + 0x20)))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (!PatchShaderProgramRegisters(ctx, headerAddress, codeAddress)) if (!PatchShaderProgramRegisters(ctx, headerAddress, codeAddress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (destinationAddress != 0 && if (destinationAddress != 0 &&
!ctx.TryWriteUInt64(destinationAddress, headerAddress)) !ctx.TryWriteUInt64(destinationAddress, headerAddress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
lock (_submitTraceGate) lock (_submitTraceGate)
@@ -567,14 +567,14 @@ public static class AgcExports
if (cxRegistersAddress == 0 || ucRegistersAddress == 0 || hullShaderAddress != 0 || geometryShaderAddress == 0) if (cxRegistersAddress == 0 || ucRegistersAddress == 0 || hullShaderAddress != 0 || geometryShaderAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadByte(geometryShaderAddress + ShaderTypeOffset, out var shaderType) || !IsEsGeometryShaderType(shaderType) || if (!ctx.TryReadByte(geometryShaderAddress + ShaderTypeOffset, out var shaderType) || !IsEsGeometryShaderType(shaderType) ||
!ctx.TryReadUInt64(geometryShaderAddress + ShaderSpecialsOffset, out var specialsAddress) || !ctx.TryReadUInt64(geometryShaderAddress + ShaderSpecialsOffset, out var specialsAddress) ||
specialsAddress == 0) specialsAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!CopyShaderRegister(ctx, specialsAddress + ShaderSpecialVgtShaderStagesEnOffset, cxRegistersAddress) || if (!CopyShaderRegister(ctx, specialsAddress + ShaderSpecialVgtShaderStagesEnOffset, cxRegistersAddress) ||
@@ -584,7 +584,7 @@ public static class AgcExports
!ctx.TryWriteUInt32(ucRegistersAddress + 16, VgtPrimitiveType) || !ctx.TryWriteUInt32(ucRegistersAddress + 16, VgtPrimitiveType) ||
!ctx.TryWriteUInt32(ucRegistersAddress + 20, primitiveType)) !ctx.TryWriteUInt32(ucRegistersAddress + 20, primitiveType))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAgc($"agc.create_prim_state cx=0x{cxRegistersAddress:X16} uc=0x{ucRegistersAddress:X16} gs=0x{geometryShaderAddress:X16} type={shaderType} prim=0x{primitiveType:X8}"); TraceAgc($"agc.create_prim_state cx=0x{cxRegistersAddress:X16} uc=0x{ucRegistersAddress:X16} gs=0x{geometryShaderAddress:X16} type={shaderType} prim=0x{primitiveType:X8}");
@@ -605,13 +605,13 @@ public static class AgcExports
if (registersAddress == 0 || geometryShaderAddress == 0) if (registersAddress == 0 || geometryShaderAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadUInt64(geometryShaderAddress + ShaderOutputSemanticsOffset, out var outputSemanticsAddress) || if (!ctx.TryReadUInt64(geometryShaderAddress + ShaderOutputSemanticsOffset, out var outputSemanticsAddress) ||
!ctx.TryReadUInt32(geometryShaderAddress + ShaderNumOutputSemanticsOffset, out var outputSemanticsCount)) !ctx.TryReadUInt32(geometryShaderAddress + ShaderNumOutputSemanticsOffset, out var outputSemanticsCount))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
ulong inputSemanticsAddress = 0; ulong inputSemanticsAddress = 0;
@@ -619,7 +619,7 @@ public static class AgcExports
(!ctx.TryReadUInt64(pixelShaderAddress + ShaderInputSemanticsOffset, out inputSemanticsAddress) || (!ctx.TryReadUInt64(pixelShaderAddress + ShaderInputSemanticsOffset, out inputSemanticsAddress) ||
!ctx.TryReadUInt32(pixelShaderAddress + ShaderNumInputSemanticsOffset, out _))) !ctx.TryReadUInt32(pixelShaderAddress + ShaderNumInputSemanticsOffset, out _)))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
for (uint i = 0; i < 32; i++) for (uint i = 0; i < 32; i++)
@@ -641,7 +641,7 @@ public static class AgcExports
if (!ctx.TryWriteUInt32(destination, SpiPsInputCntl0 + i) || if (!ctx.TryWriteUInt32(destination, SpiPsInputCntl0 + i) ||
!ctx.TryWriteUInt32(destination + sizeof(uint), value)) !ctx.TryWriteUInt32(destination + sizeof(uint), value))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
@@ -662,7 +662,7 @@ public static class AgcExports
var type = (int)ctx[CpuRegister.Rdx]; var type = (int)ctx[CpuRegister.Rdx];
if (outputAddress == 0 || commandAddress == 0) if (outputAddress == 0 || commandAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var payloadAddress = commandAddress + 8; var payloadAddress = commandAddress + 8;
@@ -670,7 +670,7 @@ public static class AgcExports
{ {
if (!ctx.TryReadUInt32(commandAddress, out var header)) if (!ctx.TryReadUInt32(commandAddress, out var header))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
payloadAddress = (header & 0x3FFF_0000u) == 0x3FFF_0000u payloadAddress = (header & 0x3FFF_0000u) == 0x3FFF_0000u
@@ -680,7 +680,7 @@ public static class AgcExports
if (!ctx.TryWriteUInt64(outputAddress, payloadAddress)) if (!ctx.TryWriteUInt64(outputAddress, payloadAddress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (ShouldTraceHotPath(ref _packetPayloadTraceCount)) if (ShouldTraceHotPath(ref _packetPayloadTraceCount))
@@ -705,20 +705,20 @@ public static class AgcExports
var dwordCount = (uint)ctx[CpuRegister.Rsi]; var dwordCount = (uint)ctx[CpuRegister.Rsi];
if (commandBufferAddress == 0 || dwordCount < 2 || dwordCount > 0x4001) if (commandBufferAddress == 0 || dwordCount < 2 || dwordCount > 0x4001)
{ {
return ReturnPointer(ctx, 0); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!TryAllocateCommandDwords(ctx, commandBufferAddress, dwordCount, out var commandAddress) || if (!TryAllocateCommandDwords(ctx, commandBufferAddress, dwordCount, out var commandAddress) ||
!ctx.TryWriteUInt32(commandAddress, Pm4(dwordCount, ItNop, RZero))) !ctx.TryWriteUInt32(commandAddress, Pm4(dwordCount, ItNop, RZero)))
{ {
return ReturnPointer(ctx, 0); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
for (uint index = 1; index < dwordCount; index++) for (uint index = 1; index < dwordCount; index++)
{ {
if (!ctx.TryWriteUInt32(commandAddress + ((ulong)index * sizeof(uint)), 0)) if (!ctx.TryWriteUInt32(commandAddress + ((ulong)index * sizeof(uint)), 0))
{ {
return ReturnPointer(ctx, 0); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
@@ -1738,12 +1738,12 @@ public static class AgcExports
op != ItNop || op != ItNop ||
register != RDmaData) register != RDmaData)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
return ctx.TryWriteUInt64(commandAddress + 16, destinationAddress) return ctx.TryWriteUInt64(commandAddress + 16, destinationAddress)
? SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK) ? ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK)
: SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -1757,7 +1757,7 @@ public static class AgcExports
var address = ctx[CpuRegister.Rsi]; var address = ctx[CpuRegister.Rsi];
if (!TryGetPacketIdentity(ctx, commandAddress, out var op, out var register)) if (!TryGetPacketIdentity(ctx, commandAddress, out var op, out var register))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var fieldOffset = op == ItWaitRegMem var fieldOffset = op == ItWaitRegMem
@@ -1767,12 +1767,12 @@ public static class AgcExports
: 0; : 0;
if (fieldOffset == 0) if (fieldOffset == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
return ctx.TryWriteUInt64(commandAddress + fieldOffset, address) return ctx.TryWriteUInt64(commandAddress + fieldOffset, address)
? SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK) ? ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK)
: SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -1788,12 +1788,12 @@ public static class AgcExports
op != ItNop || op != ItNop ||
register != RReleaseMem) register != RReleaseMem)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
return ctx.TryWriteUInt64(commandAddress + 12, address) return ctx.TryWriteUInt64(commandAddress + 12, address)
? SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK) ? ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK)
: SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -1934,11 +1934,11 @@ public static class AgcExports
KernelEventQueueCompatExports.KernelEventFilterGraphics, KernelEventQueueCompatExports.KernelEventFilterGraphics,
userData)) userData))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
TraceAgc($"agc.driver_add_eq_event eq=0x{equeue:X16} id=0x{eventId:X16} udata=0x{userData:X16}"); TraceAgc($"agc.driver_add_eq_event eq=0x{equeue:X16} id=0x{eventId:X16} udata=0x{userData:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -1955,11 +1955,11 @@ public static class AgcExports
eventId, eventId,
KernelEventQueueCompatExports.KernelEventFilterGraphics)) KernelEventQueueCompatExports.KernelEventFilterGraphics))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
TraceAgc($"agc.driver_delete_eq_event eq=0x{equeue:X16} id=0x{eventId:X16}"); TraceAgc($"agc.driver_delete_eq_event eq=0x{equeue:X16} id=0x{eventId:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -1974,7 +1974,7 @@ public static class AgcExports
!ctx.TryReadUInt64(packetAddress, out var commandAddress) || !ctx.TryReadUInt64(packetAddress, out var commandAddress) ||
!ctx.TryReadUInt32(packetAddress + 8, out var dwordCount)) !ctx.TryReadUInt32(packetAddress + 8, out var dwordCount))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var tracePackets = false; var tracePackets = false;
@@ -2014,7 +2014,7 @@ public static class AgcExports
!ctx.TryReadUInt64(packetAddress, out var commandAddress) || !ctx.TryReadUInt64(packetAddress, out var commandAddress) ||
!ctx.TryReadUInt32(packetAddress + 8, out var dwordCount)) !ctx.TryReadUInt32(packetAddress + 8, out var dwordCount))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var tracePackets = false; var tracePackets = false;
@@ -2060,16 +2060,16 @@ public static class AgcExports
if (outAddress == 0) if (outAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryWriteUInt32(outAddress, 256)) if (!ctx.TryWriteUInt32(outAddress, 256))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAgc($"agc.driver_get_resource_registration_max_name_length out=0x{outAddress:X16} value=256"); TraceAgc($"agc.driver_get_resource_registration_max_name_length out=0x{outAddress:X16} value=256");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
private const uint DefaultAgcOwner = 1; private const uint DefaultAgcOwner = 1;
@@ -2084,16 +2084,16 @@ public static class AgcExports
if (ownerAddress == 0) if (ownerAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryWriteUInt32(ownerAddress, DefaultAgcOwner)) if (!ctx.TryWriteUInt32(ownerAddress, DefaultAgcOwner))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAgc($"agc.driver_get_default_owner out=0x{ownerAddress:X16} owner={DefaultAgcOwner}"); TraceAgc($"agc.driver_get_default_owner out=0x{ownerAddress:X16} owner={DefaultAgcOwner}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -2113,7 +2113,7 @@ public static class AgcExports
$"agc.driver_register_resource resource=0x{resourceAddress:X16} owner={owner} " + $"agc.driver_register_resource resource=0x{resourceAddress:X16} owner={owner} " +
$"name=0x{nameAddress:X16} type={type} flags={flags}"); $"name=0x{nameAddress:X16} type={type} flags={flags}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -2128,7 +2128,7 @@ public static class AgcExports
$"rsi=0x{ctx[CpuRegister.Rsi]:X16} rdx=0x{ctx[CpuRegister.Rdx]:X16} " + $"rsi=0x{ctx[CpuRegister.Rsi]:X16} rdx=0x{ctx[CpuRegister.Rdx]:X16} " +
$"rcx=0x{ctx[CpuRegister.Rcx]:X16} r8=0x{ctx[CpuRegister.R8]:X16} r9=0x{ctx[CpuRegister.R9]:X16}"); $"rcx=0x{ctx[CpuRegister.Rcx]:X16} r8=0x{ctx[CpuRegister.R8]:X16} r9=0x{ctx[CpuRegister.R9]:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -5118,13 +5118,13 @@ public static class AgcExports
var registersAddress = ctx[CpuRegister.Rsi]; var registersAddress = ctx[CpuRegister.Rsi];
if (commandAddress == 0 || registersAddress == 0) if (commandAddress == 0 || registersAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryWriteUInt32(commandAddress + 8, (uint)(registersAddress & 0xFFFF_FFFFUL)) || if (!ctx.TryWriteUInt32(commandAddress + 8, (uint)(registersAddress & 0xFFFF_FFFFUL)) ||
!ctx.TryWriteUInt32(commandAddress + 12, (uint)(registersAddress >> 32))) !ctx.TryWriteUInt32(commandAddress + 12, (uint)(registersAddress >> 32)))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAgc($"agc.patch_{registerSpace}_addr cmd=0x{commandAddress:X16} regs=0x{registersAddress:X16}"); TraceAgc($"agc.patch_{registerSpace}_addr cmd=0x{commandAddress:X16} regs=0x{registersAddress:X16}");
@@ -5138,13 +5138,13 @@ public static class AgcExports
var registerCount = (uint)ctx[CpuRegister.Rsi]; var registerCount = (uint)ctx[CpuRegister.Rsi];
if (commandAddress == 0) if (commandAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadUInt32(commandAddress + 4, out var currentCount) || if (!ctx.TryReadUInt32(commandAddress + 4, out var currentCount) ||
!ctx.TryWriteUInt32(commandAddress + 4, currentCount + registerCount)) !ctx.TryWriteUInt32(commandAddress + 4, currentCount + registerCount))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAgc($"agc.patch_{registerSpace}_add cmd=0x{commandAddress:X16} add={registerCount} total={currentCount + registerCount}"); TraceAgc($"agc.patch_{registerSpace}_add cmd=0x{commandAddress:X16} add={registerCount} total={currentCount + registerCount}");
@@ -5388,12 +5388,6 @@ public static class AgcExports
return (int)OrbisGen2Result.ORBIS_GEN2_OK; return (int)OrbisGen2Result.ORBIS_GEN2_OK;
} }
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
}
private static uint Pm4(uint lengthDwords, uint op, uint register) => private static uint Pm4(uint lengthDwords, uint op, uint register) =>
0xC0000000u | 0xC0000000u |
((((ushort)lengthDwords - 2u) & 0x3FFFu) << 16) | ((((ushort)lengthDwords - 2u) & 0x3FFFu) << 16) |
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary;
namespace SharpEmu.Libs.Agc; namespace SharpEmu.Libs.Agc;
@@ -36,9 +35,9 @@ internal static class Gen5ShaderMetadataReader
} }
} }
if (!TryReadUInt16(ctx, userDataAddress + 0x28, out var extendedUserDataSize) || if (!ctx.TryReadUInt16(userDataAddress + 0x28, out var extendedUserDataSize) ||
!TryReadUInt16(ctx, userDataAddress + 0x2A, out var shaderResourceTableSize) || !ctx.TryReadUInt16(userDataAddress + 0x2A, out var shaderResourceTableSize) ||
!TryReadUInt16(ctx, userDataAddress + 0x2C, out var directResourceCount) || !ctx.TryReadUInt16(userDataAddress + 0x2C, out var directResourceCount) ||
directResourceCount > MaxMetadataEntries) directResourceCount > MaxMetadataEntries)
{ {
return false; return false;
@@ -47,8 +46,7 @@ internal static class Gen5ShaderMetadataReader
var resourceCounts = new ushort[ResourceClassCount]; var resourceCounts = new ushort[ResourceClassCount];
for (var resourceClass = 0; resourceClass < ResourceClassCount; resourceClass++) for (var resourceClass = 0; resourceClass < ResourceClassCount; resourceClass++)
{ {
if (!TryReadUInt16( if (!ctx.TryReadUInt16(
ctx,
userDataAddress + 0x2E + (ulong)(resourceClass * sizeof(ushort)), userDataAddress + 0x2E + (ulong)(resourceClass * sizeof(ushort)),
out resourceCounts[resourceClass]) || out resourceCounts[resourceClass]) ||
resourceCounts[resourceClass] > MaxMetadataEntries) resourceCounts[resourceClass] > MaxMetadataEntries)
@@ -67,7 +65,7 @@ internal static class Gen5ShaderMetadataReader
for (uint type = 0; type < directResourceCount; type++) for (uint type = 0; type < directResourceCount; type++)
{ {
if (!TryReadUInt16(ctx, directResourceOffsetsAddress + type * sizeof(ushort), out var offset)) if (!ctx.TryReadUInt16(directResourceOffsetsAddress + type * sizeof(ushort), out var offset))
{ {
return false; return false;
} }
@@ -95,8 +93,7 @@ internal static class Gen5ShaderMetadataReader
for (uint slot = 0; slot < count; slot++) for (uint slot = 0; slot < count; slot++)
{ {
if (!TryReadUInt16( if (!ctx.TryReadUInt16(
ctx,
resourceOffsets[resourceClass] + slot * sizeof(ushort), resourceOffsets[resourceClass] + slot * sizeof(ushort),
out var sharp)) out var sharp))
{ {
@@ -124,17 +121,4 @@ internal static class Gen5ShaderMetadataReader
resources); resources);
return true; return true;
} }
private static bool TryReadUInt16(CpuContext ctx, ulong address, out ushort value)
{
Span<byte> bytes = stackalloc byte[sizeof(ushort)];
if (!ctx.Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadUInt16LittleEndian(bytes);
return true;
}
} }
@@ -73,7 +73,7 @@ public static class AppContentExports
var valueAddress = ctx[CpuRegister.Rsi]; var valueAddress = ctx[CpuRegister.Rsi];
if (valueAddress == 0) if (valueAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
int value; int value;
@@ -83,18 +83,18 @@ public static class AppContentExports
} }
else if (!TryReadUserDefinedParam(paramId, out value)) else if (!TryReadUserDefinedParam(paramId, out value))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> valueBytes = stackalloc byte[sizeof(int)]; Span<byte> valueBytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(valueBytes, value); BinaryPrimitives.WriteInt32LittleEndian(valueBytes, value);
if (!ctx.Memory.TryWrite(valueAddress, valueBytes)) if (!ctx.Memory.TryWrite(valueAddress, valueBytes))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceAppContent($"app_param_get_int id={paramId} value={value}"); TraceAppContent($"app_param_get_int id={paramId} value={value}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -168,12 +168,6 @@ public static class AppContentExports
} }
} }
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
}
private static void TraceAppContent(string message) private static void TraceAppContent(string message)
{ {
if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_APP_CONTENT"), "1", StringComparison.Ordinal)) if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_APP_CONTENT"), "1", StringComparison.Ordinal))
+24 -31
View File
@@ -3,7 +3,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Threading;
namespace SharpEmu.Libs.Audio; namespace SharpEmu.Libs.Audio;
@@ -37,7 +36,7 @@ public static class AudioOut2Exports
var paramAddress = ctx[CpuRegister.Rdi]; var paramAddress = ctx[CpuRegister.Rdi];
if (paramAddress == 0) if (paramAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> param = stackalloc byte[AudioOut2ContextParamSize]; Span<byte> param = stackalloc byte[AudioOut2ContextParamSize];
@@ -48,8 +47,8 @@ public static class AudioOut2Exports
BinaryPrimitives.WriteUInt32LittleEndian(param[0x0C..], 0x400); BinaryPrimitives.WriteUInt32LittleEndian(param[0x0C..], 0x400);
return ctx.Memory.TryWrite(paramAddress, param) return ctx.Memory.TryWrite(paramAddress, param)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -63,7 +62,7 @@ public static class AudioOut2Exports
var memoryInfoAddress = ctx[CpuRegister.Rsi]; var memoryInfoAddress = ctx[CpuRegister.Rsi];
if (paramAddress == 0 || memoryInfoAddress == 0) if (paramAddress == 0 || memoryInfoAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> memoryInfo = stackalloc byte[0x20]; Span<byte> memoryInfo = stackalloc byte[0x20];
@@ -74,8 +73,8 @@ public static class AudioOut2Exports
BinaryPrimitives.WriteUInt64LittleEndian(memoryInfo[0x18..], AudioOut2ContextMemoryAlignment); BinaryPrimitives.WriteUInt64LittleEndian(memoryInfo[0x18..], AudioOut2ContextMemoryAlignment);
return ctx.Memory.TryWrite(memoryInfoAddress, memoryInfo) return ctx.Memory.TryWrite(memoryInfoAddress, memoryInfo)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -91,13 +90,13 @@ public static class AudioOut2Exports
var outContextAddress = ctx[CpuRegister.Rcx]; var outContextAddress = ctx[CpuRegister.Rcx];
if (paramAddress == 0 || memoryAddress == 0 || memorySize == 0 || outContextAddress == 0) if (paramAddress == 0 || memoryAddress == 0 || memorySize == 0 || outContextAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var handle = (ulong)Interlocked.Increment(ref _nextContextHandle); var handle = (ulong)Interlocked.Increment(ref _nextContextHandle);
return ctx.TryWriteUInt64(outContextAddress, handle) return ctx.TryWriteUInt64(outContextAddress, handle)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -105,7 +104,7 @@ public static class AudioOut2Exports
ExportName = "sceAudioOut2ContextDestroy", ExportName = "sceAudioOut2ContextDestroy",
Target = Generation.Gen5, Target = Generation.Gen5,
LibraryName = "libSceAudioOut2")] LibraryName = "libSceAudioOut2")]
public static int AudioOut2ContextDestroy(CpuContext ctx) => SetReturn(ctx, 0); public static int AudioOut2ContextDestroy(CpuContext ctx) => ctx.SetReturn(0);
[SysAbiExport( [SysAbiExport(
Nid = "JK2wamZPzwM", Nid = "JK2wamZPzwM",
@@ -120,14 +119,14 @@ public static class AudioOut2Exports
var contextAddress = ctx[CpuRegister.Rcx]; var contextAddress = ctx[CpuRegister.Rcx];
if (type < 0 || type > 255 || paramAddress == 0 || outPortAddress == 0 || contextAddress == 0) if (type < 0 || type > 255 || paramAddress == 0 || outPortAddress == 0 || contextAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var portId = unchecked((uint)Interlocked.Increment(ref _nextPortId)) & 0xFF; var portId = unchecked((uint)Interlocked.Increment(ref _nextPortId)) & 0xFF;
var handle = 0x2000_0000UL | ((ulong)(uint)type << 16) | portId; var handle = 0x2000_0000UL | ((ulong)(uint)type << 16) | portId;
return ctx.TryWriteUInt64(outPortAddress, handle) return ctx.TryWriteUInt64(outPortAddress, handle)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -141,7 +140,7 @@ public static class AudioOut2Exports
var stateAddress = ctx[CpuRegister.Rsi]; var stateAddress = ctx[CpuRegister.Rsi];
if (handle == 0 || stateAddress == 0) if (handle == 0 || stateAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var type = (int)((handle >> 16) & 0xFF); var type = (int)((handle >> 16) & 0xFF);
@@ -154,8 +153,8 @@ public static class AudioOut2Exports
BinaryPrimitives.WriteInt16LittleEndian(state[0x04..], -1); BinaryPrimitives.WriteInt16LittleEndian(state[0x04..], -1);
return ctx.Memory.TryWrite(stateAddress, state) return ctx.Memory.TryWrite(stateAddress, state)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -168,7 +167,7 @@ public static class AudioOut2Exports
var infoAddress = ctx[CpuRegister.Rdi]; var infoAddress = ctx[CpuRegister.Rdi];
if (infoAddress == 0) if (infoAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> info = stackalloc byte[0x40]; Span<byte> info = stackalloc byte[0x40];
@@ -178,8 +177,8 @@ public static class AudioOut2Exports
BinaryPrimitives.WriteUInt32LittleEndian(info[0x08..], 48000); BinaryPrimitives.WriteUInt32LittleEndian(info[0x08..], 48000);
return ctx.Memory.TryWrite(infoAddress, info) return ctx.Memory.TryWrite(infoAddress, info)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -187,14 +186,14 @@ public static class AudioOut2Exports
ExportName = "sceAudioOut2PortDestroy", ExportName = "sceAudioOut2PortDestroy",
Target = Generation.Gen5, Target = Generation.Gen5,
LibraryName = "libSceAudioOut2")] LibraryName = "libSceAudioOut2")]
public static int AudioOut2PortDestroy(CpuContext ctx) => SetReturn(ctx, 0); public static int AudioOut2PortDestroy(CpuContext ctx) => ctx.SetReturn(0);
[SysAbiExport( [SysAbiExport(
Nid = "IaZXJ9M79uo", Nid = "IaZXJ9M79uo",
ExportName = "sceAudioOut2UserDestroy", ExportName = "sceAudioOut2UserDestroy",
Target = Generation.Gen5, Target = Generation.Gen5,
LibraryName = "libSceAudioOut2")] LibraryName = "libSceAudioOut2")]
public static int AudioOut2UserDestroy(CpuContext ctx) => SetReturn(ctx, 0); public static int AudioOut2UserDestroy(CpuContext ctx) => ctx.SetReturn(0);
[SysAbiExport( [SysAbiExport(
Nid = "xywYcRB7nbQ", Nid = "xywYcRB7nbQ",
@@ -207,18 +206,12 @@ public static class AudioOut2Exports
var outUserAddress = ctx[CpuRegister.Rsi]; var outUserAddress = ctx[CpuRegister.Rsi];
if ((userId != 0 && userId != 1 && userId != 255) || outUserAddress == 0) if ((userId != 0 && userId != 1 && userId != 255) || outUserAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var handle = (ulong)Interlocked.Increment(ref _nextUserHandle); var handle = (ulong)Interlocked.Increment(ref _nextUserHandle);
return ctx.TryWriteUInt64(outUserAddress, handle) return ctx.TryWriteUInt64(outUserAddress, handle)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
} }
+10 -18
View File
@@ -5,7 +5,6 @@ using SharpEmu.HLE;
using System.Buffers; using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace SharpEmu.Libs.Audio; namespace SharpEmu.Libs.Audio;
@@ -84,7 +83,7 @@ public static class AudioOutExports
ExportName = "sceAudioOutInit", ExportName = "sceAudioOutInit",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceAudioOut")] LibraryName = "libSceAudioOut")]
public static int AudioOutInit(CpuContext ctx) => SetReturn(ctx, 0); public static int AudioOutInit(CpuContext ctx) => ctx.SetReturn(0);
[SysAbiExport( [SysAbiExport(
Nid = "ekNvsT22rsY", Nid = "ekNvsT22rsY",
@@ -101,7 +100,7 @@ public static class AudioOutExports
if (bufferLength == 0 || frequency == 0 || if (bufferLength == 0 || frequency == 0 ||
!TryGetFormat(format, out var channels, out var bytesPerSample, out var isFloat)) !TryGetFormat(format, out var channels, out var bytesPerSample, out var isFloat))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
WinMmAudioPort? backend = null; WinMmAudioPort? backend = null;
@@ -133,7 +132,7 @@ public static class AudioOutExports
$"[LOADER][INFO] AudioOut port {handle}: {frequency} Hz, " + $"[LOADER][INFO] AudioOut port {handle}: {frequency} Hz, " +
$"{channels} ch, {(isFloat ? "float32" : "s16")}, " + $"{channels} ch, {(isFloat ? "float32" : "s16")}, " +
$"{bufferLength} frames, backend={backendName}"); $"{bufferLength} frames, backend={backendName}");
return SetReturn(ctx, handle); return ctx.SetReturn(handle);
} }
[SysAbiExport( [SysAbiExport(
@@ -146,11 +145,11 @@ public static class AudioOutExports
var handle = unchecked((int)ctx[CpuRegister.Rdi]); var handle = unchecked((int)ctx[CpuRegister.Rdi]);
if (!Ports.TryRemove(handle, out var port)) if (!Ports.TryRemove(handle, out var port))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
port.Dispose(); port.Dispose();
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -164,12 +163,12 @@ public static class AudioOutExports
var sourceAddress = ctx[CpuRegister.Rsi]; var sourceAddress = ctx[CpuRegister.Rsi];
if (!Ports.TryGetValue(handle, out var port)) if (!Ports.TryGetValue(handle, out var port))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (sourceAddress == 0) if (sourceAddress == 0)
{ {
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
var buffer = ArrayPool<byte>.Shared.Rent(port.BufferByteLength); var buffer = ArrayPool<byte>.Shared.Rent(port.BufferByteLength);
@@ -178,7 +177,7 @@ public static class AudioOutExports
var source = buffer.AsSpan(0, port.BufferByteLength); var source = buffer.AsSpan(0, port.BufferByteLength);
if (!ctx.Memory.TryRead(sourceAddress, source)) if (!ctx.Memory.TryRead(sourceAddress, source))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (port.Backend is null || if (port.Backend is null ||
@@ -192,7 +191,7 @@ public static class AudioOutExports
port.PaceSilence(); port.PaceSilence();
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
finally finally
{ {
@@ -208,19 +207,12 @@ public static class AudioOutExports
public static int AudioOutSetVolume(CpuContext ctx) public static int AudioOutSetVolume(CpuContext ctx)
{ {
var handle = unchecked((int)ctx[CpuRegister.Rdi]); var handle = unchecked((int)ctx[CpuRegister.Rdi]);
return SetReturn( return ctx.SetReturn(
ctx,
Ports.ContainsKey(handle) Ports.ContainsKey(handle)
? 0 ? 0
: (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); : (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
private static bool TryGetFormat( private static bool TryGetFormat(
int rawFormat, int rawFormat,
out int channels, out int channels,
+2 -11
View File
@@ -46,8 +46,7 @@ public static class AvPlayerExports
var dataAddress = ctx[CpuRegister.Rsi]; var dataAddress = ctx[CpuRegister.Rsi];
lock (StateGate) lock (StateGate)
{ {
return SetReturn( return ctx.SetReturn(
ctx,
handle != 0 && dataAddress != 0 && Players.Contains(handle) handle != 0 && dataAddress != 0 && Players.Contains(handle)
? 0 ? 0
: InvalidParameters); : InvalidParameters);
@@ -63,15 +62,7 @@ public static class AvPlayerExports
{ {
lock (StateGate) lock (StateGate)
{ {
return SetReturn( return ctx.SetReturn(Players.Remove(ctx[CpuRegister.Rdi]) ? 0 : InvalidParameters);
ctx,
Players.Remove(ctx[CpuRegister.Rdi]) ? 0 : InvalidParameters);
} }
} }
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
} }
+62 -68
View File
@@ -104,17 +104,17 @@ public static class FiberExports
var optParam = ctx[CpuRegister.Rdi]; var optParam = ctx[CpuRegister.Rdi];
if (optParam == 0) if (optParam == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
if ((optParam & 7) != 0) if ((optParam & 7) != 0)
{ {
return SetReturn(ctx, FiberErrorAlignment); return ctx.SetReturn(FiberErrorAlignment);
} }
return ctx.TryWriteUInt32(optParam, FiberOptSignature) return ctx.TryWriteUInt32(optParam, FiberOptSignature)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorInvalid); : ctx.SetReturn(FiberErrorInvalid);
} }
[SysAbiExport( [SysAbiExport(
@@ -127,24 +127,24 @@ public static class FiberExports
var fiber = ctx[CpuRegister.Rdi]; var fiber = ctx[CpuRegister.Rdi];
if (!TryValidateFiber(ctx, fiber, out var error)) if (!TryValidateFiber(ctx, fiber, out var error))
{ {
return SetReturn(ctx, error); return ctx.SetReturn(error);
} }
if (!ctx.TryReadUInt32(fiber + FiberStateOffset, out var state)) if (!ctx.TryReadUInt32(fiber + FiberStateOffset, out var state))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (state != FiberStateIdle) if (state != FiberStateIdle)
{ {
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
_continuations.TryRemove(fiber, out _); _continuations.TryRemove(fiber, out _);
_returnTargets.TryRemove(fiber, out _); _returnTargets.TryRemove(fiber, out _);
_stackRanges.TryRemove(fiber, out _); _stackRanges.TryRemove(fiber, out _);
_ = ctx.TryWriteUInt32(fiber + FiberStateOffset, FiberStateTerminated); _ = ctx.TryWriteUInt32(fiber + FiberStateOffset, FiberStateTerminated);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -229,20 +229,20 @@ public static class FiberExports
var fiberAddress = ResolveCurrentFiberAddress(ctx); var fiberAddress = ResolveCurrentFiberAddress(ctx);
if (fiberAddress == 0) if (fiberAddress == 0)
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
if (GuestThreadExecution.Scheduler is not { SupportsGuestContextTransfer: true } || if (GuestThreadExecution.Scheduler is not { SupportsGuestContextTransfer: true } ||
!GuestThreadExecution.TryGetCurrentImportCallFrame(out var frame)) !GuestThreadExecution.TryGetCurrentImportCallFrame(out var frame))
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
var returnArgument = ctx[CpuRegister.Rdi]; var returnArgument = ctx[CpuRegister.Rdi];
var argOnRunAddress = ctx[CpuRegister.Rsi]; var argOnRunAddress = ctx[CpuRegister.Rsi];
if (argOnRunAddress != 0 && !ctx.TryWriteUInt64(argOnRunAddress, 0)) if (argOnRunAddress != 0 && !ctx.TryWriteUInt64(argOnRunAddress, 0))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
GuestCpuContinuation transferTarget; GuestCpuContinuation transferTarget;
@@ -256,7 +256,7 @@ public static class FiberExports
if (!_returnTargets.TryRemove(fiberAddress, out var returnTarget)) if (!_returnTargets.TryRemove(fiberAddress, out var returnTarget))
{ {
_continuations.TryRemove(fiberAddress, out _); _continuations.TryRemove(fiberAddress, out _);
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
previousFiber = returnTarget.PreviousFiber; previousFiber = returnTarget.PreviousFiber;
@@ -267,7 +267,7 @@ public static class FiberExports
!ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateRun)) !ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateRun))
{ {
_continuations.TryRemove(fiberAddress, out _); _continuations.TryRemove(fiberAddress, out _);
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
transferTarget = previousContinuation.Context with { Rax = 0 }; transferTarget = previousContinuation.Context with { Rax = 0 };
@@ -278,7 +278,7 @@ public static class FiberExports
!TryWriteResumeArgument(ctx, returnTarget.ThreadContinuation.Value, returnArgument)) !TryWriteResumeArgument(ctx, returnTarget.ThreadContinuation.Value, returnArgument))
{ {
_continuations.TryRemove(fiberAddress, out _); _continuations.TryRemove(fiberAddress, out _);
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
transferTarget = returnTarget.ThreadContinuation.Value.Context with { Rax = 0 }; transferTarget = returnTarget.ThreadContinuation.Value.Context with { Rax = 0 };
@@ -286,7 +286,7 @@ public static class FiberExports
if (!ctx.TryWriteUInt32(fiberAddress + FiberStateOffset, FiberStateIdle)) if (!ctx.TryWriteUInt32(fiberAddress + FiberStateOffset, FiberStateIdle))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
} }
@@ -296,7 +296,7 @@ public static class FiberExports
TraceFiber( TraceFiber(
$"return fiber=0x{fiberAddress:X16} to=0x{previousFiber:X16} " + $"return fiber=0x{fiberAddress:X16} to=0x{previousFiber:X16} " +
$"resume=0x{transferTarget.Rip:X16} rsp=0x{transferTarget.Rsp:X16} arg=0x{returnArgument:X16}"); $"resume=0x{transferTarget.Rip:X16} rsp=0x{transferTarget.Rsp:X16} arg=0x{returnArgument:X16}");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -309,18 +309,18 @@ public static class FiberExports
var outAddress = ctx[CpuRegister.Rdi]; var outAddress = ctx[CpuRegister.Rdi];
if (outAddress == 0) if (outAddress == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
var fiberAddress = ResolveCurrentFiberAddress(ctx); var fiberAddress = ResolveCurrentFiberAddress(ctx);
if (fiberAddress == 0) if (fiberAddress == 0)
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
return ctx.TryWriteUInt64(outAddress, fiberAddress) return ctx.TryWriteUInt64(outAddress, fiberAddress)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorInvalid); : ctx.SetReturn(FiberErrorInvalid);
} }
[SysAbiExport( [SysAbiExport(
@@ -334,22 +334,22 @@ public static class FiberExports
var info = ctx[CpuRegister.Rsi]; var info = ctx[CpuRegister.Rsi];
if (info == 0) if (info == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
if (!TryValidateFiber(ctx, fiber, out var error)) if (!TryValidateFiber(ctx, fiber, out var error))
{ {
return SetReturn(ctx, error); return ctx.SetReturn(error);
} }
if (!ctx.TryReadUInt64(info, out var size) || size != FiberInfoSize) if (!ctx.TryReadUInt64(info, out var size) || size != FiberInfoSize)
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (!TryReadFiberFields(ctx, fiber, out var fields)) if (!TryReadFiberFields(ctx, fiber, out var fields))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (!ctx.TryWriteUInt64(info + 8, fields.Entry) || if (!ctx.TryWriteUInt64(info + 8, fields.Entry) ||
@@ -359,10 +359,10 @@ public static class FiberExports
!TryWriteName(ctx, info + 40, fields.Name) || !TryWriteName(ctx, info + 40, fields.Name) ||
!ctx.TryWriteUInt64(info + 72, ulong.MaxValue)) !ctx.TryWriteUInt64(info + 72, ulong.MaxValue))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -376,22 +376,22 @@ public static class FiberExports
var nameAddress = ctx[CpuRegister.Rsi]; var nameAddress = ctx[CpuRegister.Rsi];
if (!TryValidateFiber(ctx, fiber, out var error)) if (!TryValidateFiber(ctx, fiber, out var error))
{ {
return SetReturn(ctx, error); return ctx.SetReturn(error);
} }
if (nameAddress == 0) if (nameAddress == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxNameLength + 1, out var name)) if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxNameLength + 1, out var name))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
return TryWriteName(ctx, fiber + FiberNameOffset, name) return TryWriteName(ctx, fiber + FiberNameOffset, name)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorInvalid); : ctx.SetReturn(FiberErrorInvalid);
} }
[SysAbiExport( [SysAbiExport(
@@ -403,12 +403,12 @@ public static class FiberExports
{ {
if (ctx[CpuRegister.Rdi] != 0) if (ctx[CpuRegister.Rdi] != 0)
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
return Interlocked.Exchange(ref _contextSizeCheck, 1) == 0 return Interlocked.Exchange(ref _contextSizeCheck, 1) == 0
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorState); : ctx.SetReturn(FiberErrorState);
} }
[SysAbiExport( [SysAbiExport(
@@ -419,8 +419,8 @@ public static class FiberExports
public static int FiberStopContextSizeCheck(CpuContext ctx) public static int FiberStopContextSizeCheck(CpuContext ctx)
{ {
return Interlocked.Exchange(ref _contextSizeCheck, 0) == 1 return Interlocked.Exchange(ref _contextSizeCheck, 0) == 1
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorState); : ctx.SetReturn(FiberErrorState);
} }
[SysAbiExport( [SysAbiExport(
@@ -433,17 +433,17 @@ public static class FiberExports
var outAddress = ctx[CpuRegister.Rdi]; var outAddress = ctx[CpuRegister.Rdi];
if (outAddress == 0) if (outAddress == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
if (ResolveCurrentFiberAddress(ctx) == 0) if (ResolveCurrentFiberAddress(ctx) == 0)
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
return ctx.TryWriteUInt64(outAddress, ctx[CpuRegister.Rbp]) return ctx.TryWriteUInt64(outAddress, ctx[CpuRegister.Rbp])
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, FiberErrorInvalid); : ctx.SetReturn(FiberErrorInvalid);
} }
private static int FiberInitializeCore( private static int FiberInitializeCore(
@@ -459,37 +459,37 @@ public static class FiberExports
{ {
if (fiber == 0 || nameAddress == 0 || entry == 0) if (fiber == 0 || nameAddress == 0 || entry == 0)
{ {
return SetReturn(ctx, FiberErrorNull); return ctx.SetReturn(FiberErrorNull);
} }
if ((fiber & 7) != 0 || if ((fiber & 7) != 0 ||
(contextAddress & 15) != 0 || (contextAddress & 15) != 0 ||
(optParam & 7) != 0) (optParam & 7) != 0)
{ {
return SetReturn(ctx, FiberErrorAlignment); return ctx.SetReturn(FiberErrorAlignment);
} }
if (contextSize != 0 && contextSize < FiberContextMinimumSize) if (contextSize != 0 && contextSize < FiberContextMinimumSize)
{ {
return SetReturn(ctx, FiberErrorRange); return ctx.SetReturn(FiberErrorRange);
} }
if ((contextSize & 15) != 0 || if ((contextSize & 15) != 0 ||
(contextAddress == 0 && contextSize != 0) || (contextAddress == 0 && contextSize != 0) ||
(contextAddress != 0 && contextSize == 0)) (contextAddress != 0 && contextSize == 0))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (optParam != 0 && if (optParam != 0 &&
(!ctx.TryReadUInt32(optParam, out var optMagic) || optMagic != FiberOptSignature)) (!ctx.TryReadUInt32(optParam, out var optMagic) || optMagic != FiberOptSignature))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxNameLength + 1, out var name)) if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxNameLength + 1, out var name))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (Volatile.Read(ref _contextSizeCheck) != 0) if (Volatile.Read(ref _contextSizeCheck) != 0)
@@ -510,14 +510,14 @@ public static class FiberExports
!ctx.TryWriteUInt64(fiber + FiberContextEndOffset, contextAddress == 0 ? 0 : contextAddress + contextSize) || !ctx.TryWriteUInt64(fiber + FiberContextEndOffset, contextAddress == 0 ? 0 : contextAddress + contextSize) ||
!ctx.TryWriteUInt32(fiber + FiberMagicEndOffset, FiberSignature1)) !ctx.TryWriteUInt32(fiber + FiberMagicEndOffset, FiberSignature1))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (contextAddress != 0) if (contextAddress != 0)
{ {
if (!ctx.TryWriteUInt64(contextAddress, FiberStackSignature)) if (!ctx.TryWriteUInt64(contextAddress, FiberStackSignature))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if ((flags & FiberFlagContextSizeCheck) != 0) if ((flags & FiberFlagContextSizeCheck) != 0)
@@ -532,7 +532,7 @@ public static class FiberExports
} }
TraceFiber($"init fiber=0x{fiber:X16} entry=0x{entry:X16} ctx=0x{contextAddress:X16} size=0x{contextSize:X} name='{name}'"); TraceFiber($"init fiber=0x{fiber:X16} entry=0x{entry:X16} ctx=0x{contextAddress:X16} size=0x{contextSize:X} name='{name}'");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
private static int FiberRunCore( private static int FiberRunCore(
@@ -547,12 +547,12 @@ public static class FiberExports
{ {
if (!TryValidateFiber(ctx, fiber, out var error)) if (!TryValidateFiber(ctx, fiber, out var error))
{ {
return SetReturn(ctx, error); return ctx.SetReturn(error);
} }
if (!TryReadFiberFields(ctx, fiber, out var fields)) if (!TryReadFiberFields(ctx, fiber, out var fields))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (attachContextAddress != 0 || attachContextSize != 0) if (attachContextAddress != 0 || attachContextSize != 0)
@@ -560,7 +560,7 @@ public static class FiberExports
var attachResult = AttachContext(ctx, fiber, attachContextAddress, attachContextSize, ref fields); var attachResult = AttachContext(ctx, fiber, attachContextAddress, attachContextSize, ref fields);
if (attachResult != 0) if (attachResult != 0)
{ {
return SetReturn(ctx, attachResult); return ctx.SetReturn(attachResult);
} }
} }
@@ -568,16 +568,16 @@ public static class FiberExports
if ((isSwitch && previousFiber == 0) || if ((isSwitch && previousFiber == 0) ||
(!isSwitch && previousFiber != 0)) (!isSwitch && previousFiber != 0))
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
if (previousFiber == fiber) if (previousFiber == fiber)
{ {
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
if (GuestThreadExecution.Scheduler is not { SupportsGuestContextTransfer: true } || if (GuestThreadExecution.Scheduler is not { SupportsGuestContextTransfer: true } ||
!GuestThreadExecution.TryGetCurrentImportCallFrame(out var frame)) !GuestThreadExecution.TryGetCurrentImportCallFrame(out var frame))
{ {
return SetReturn(ctx, FiberErrorPermission); return ctx.SetReturn(FiberErrorPermission);
} }
GuestCpuContinuation transferTarget; GuestCpuContinuation transferTarget;
@@ -586,12 +586,12 @@ public static class FiberExports
{ {
if (!TryReadFiberFields(ctx, fiber, out fields)) if (!TryReadFiberFields(ctx, fiber, out fields))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (fields.State != FiberStateIdle) if (fields.State != FiberStateIdle)
{ {
TraceFiber($"run-state-error reason={reason} fiber=0x{fiber:X16} state=0x{fields.State:X8}"); TraceFiber($"run-state-error reason={reason} fiber=0x{fiber:X16} state=0x{fields.State:X8}");
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
FiberContinuation targetContinuation; FiberContinuation targetContinuation;
@@ -602,12 +602,12 @@ public static class FiberExports
} }
else if (!TryCreateInitialContinuation(ctx, fields, argOnRun, out targetContinuation)) else if (!TryCreateInitialContinuation(ctx, fields, argOnRun, out targetContinuation))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (resumed && !TryWriteResumeArgument(ctx, targetContinuation, argOnRun)) if (resumed && !TryWriteResumeArgument(ctx, targetContinuation, argOnRun))
{ {
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
var callerContinuation = new FiberContinuation( var callerContinuation = new FiberContinuation(
@@ -620,7 +620,7 @@ public static class FiberExports
previousState != FiberStateRun || previousState != FiberStateRun ||
!ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateIdle)) !ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateIdle))
{ {
return SetReturn(ctx, FiberErrorState); return ctx.SetReturn(FiberErrorState);
} }
_continuations[previousFiber] = callerContinuation; _continuations[previousFiber] = callerContinuation;
@@ -639,7 +639,7 @@ public static class FiberExports
_ = ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateRun); _ = ctx.TryWriteUInt32(previousFiber + FiberStateOffset, FiberStateRun);
} }
_returnTargets.TryRemove(fiber, out _); _returnTargets.TryRemove(fiber, out _);
return SetReturn(ctx, FiberErrorInvalid); return ctx.SetReturn(FiberErrorInvalid);
} }
if (resumed) if (resumed)
@@ -656,7 +656,7 @@ public static class FiberExports
TraceFiber( TraceFiber(
$"transfer reason={reason} from=0x{previousFiber:X16} to=0x{fiber:X16} resume={resumed} " + $"transfer reason={reason} from=0x{previousFiber:X16} to=0x{fiber:X16} resume={resumed} " +
$"rip=0x{transferTarget.Rip:X16} rsp=0x{transferTarget.Rsp:X16} arg=0x{argOnRun:X16}"); $"rip=0x{transferTarget.Rip:X16} rsp=0x{transferTarget.Rsp:X16} arg=0x{argOnRun:X16}");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
private static bool TryCreateInitialContinuation( private static bool TryCreateInitialContinuation(
@@ -925,12 +925,6 @@ public static class FiberExports
return true; return true;
} }
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
private static void TraceFiber(string message) private static void TraceFiber(string message)
{ {
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_FIBER"), "1", StringComparison.Ordinal)) if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_FIBER"), "1", StringComparison.Ordinal))
@@ -51,17 +51,17 @@ public static class KernelEventFlagCompatExports
optionAddress != 0 || optionAddress != 0 ||
!IsValidAttributes(attributes)) !IsValidAttributes(attributes))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxEventFlagNameLength + 1, out var name)) if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxEventFlagNameLength + 1, out var name))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (Encoding.UTF8.GetByteCount(name) > MaxEventFlagNameLength) if (Encoding.UTF8.GetByteCount(name) > MaxEventFlagNameLength)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
var handle = unchecked((ulong)Interlocked.Increment(ref _nextEventFlagHandle)); var handle = unchecked((ulong)Interlocked.Increment(ref _nextEventFlagHandle));
@@ -75,11 +75,11 @@ public static class KernelEventFlagCompatExports
if (!ctx.TryWriteUInt64(outAddress, handle)) if (!ctx.TryWriteUInt64(outAddress, handle))
{ {
_eventFlags.TryRemove(handle, out _); _eventFlags.TryRemove(handle, out _);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceEventFlag($"create handle=0x{handle:X16} name='{name}' attr=0x{attributes:X2} bits=0x{initialPattern:X16}"); TraceEventFlag($"create handle=0x{handle:X16} name='{name}' attr=0x{attributes:X2} bits=0x{initialPattern:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -92,7 +92,7 @@ public static class KernelEventFlagCompatExports
var handle = ctx[CpuRegister.Rdi]; var handle = ctx[CpuRegister.Rdi];
if (!_eventFlags.TryRemove(handle, out var state)) if (!_eventFlags.TryRemove(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
lock (state.Gate) lock (state.Gate)
@@ -101,7 +101,7 @@ public static class KernelEventFlagCompatExports
} }
TraceEventFlag($"delete handle=0x{handle:X16} name='{state.Name}'"); TraceEventFlag($"delete handle=0x{handle:X16} name='{state.Name}'");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -116,7 +116,7 @@ public static class KernelEventFlagCompatExports
var returnRip = GetCurrentReturnRip(); var returnRip = GetCurrentReturnRip();
if (!_eventFlags.TryGetValue(handle, out var state)) if (!_eventFlags.TryGetValue(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
lock (state.Gate) lock (state.Gate)
@@ -127,7 +127,7 @@ public static class KernelEventFlagCompatExports
} }
_ = GuestThreadExecution.Scheduler?.WakeBlockedThreads(GetEventFlagWakeKey(handle)); _ = GuestThreadExecution.Scheduler?.WakeBlockedThreads(GetEventFlagWakeKey(handle));
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -141,7 +141,7 @@ public static class KernelEventFlagCompatExports
var pattern = ctx[CpuRegister.Rsi]; var pattern = ctx[CpuRegister.Rsi];
if (!_eventFlags.TryGetValue(handle, out var state)) if (!_eventFlags.TryGetValue(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
lock (state.Gate) lock (state.Gate)
@@ -150,7 +150,7 @@ public static class KernelEventFlagCompatExports
TraceEventFlag($"clear handle=0x{handle:X16} mask=0x{pattern:X16} bits=0x{state.Bits:X16}"); TraceEventFlag($"clear handle=0x{handle:X16} mask=0x{pattern:X16} bits=0x{state.Bits:X16}");
} }
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -167,29 +167,29 @@ public static class KernelEventFlagCompatExports
if (!_eventFlags.TryGetValue(handle, out var state)) if (!_eventFlags.TryGetValue(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (pattern == 0 || !IsValidWaitMode(waitMode)) if (pattern == 0 || !IsValidWaitMode(waitMode))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
lock (state.Gate) lock (state.Gate)
{ {
if (!TryWriteResultPattern(ctx, resultAddress, state.Bits)) if (!TryWriteResultPattern(ctx, resultAddress, state.Bits))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (!IsSatisfied(state.Bits, pattern, waitMode)) if (!IsSatisfied(state.Bits, pattern, waitMode))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_BUSY); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_BUSY);
} }
ApplyClearMode(state, pattern, waitMode); ApplyClearMode(state, pattern, waitMode);
TraceEventFlag($"poll handle=0x{handle:X16} pattern=0x{pattern:X16} mode=0x{waitMode:X2} bits=0x{state.Bits:X16}"); TraceEventFlag($"poll handle=0x{handle:X16} pattern=0x{pattern:X16} mode=0x{waitMode:X2} bits=0x{state.Bits:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
} }
@@ -209,18 +209,18 @@ public static class KernelEventFlagCompatExports
if (!_eventFlags.TryGetValue(handle, out var state)) if (!_eventFlags.TryGetValue(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (pattern == 0 || !IsValidWaitMode(waitMode)) if (pattern == 0 || !IsValidWaitMode(waitMode))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
uint timeoutUsec = 0; uint timeoutUsec = 0;
if (timeoutAddress != 0 && !ctx.TryReadUInt32(timeoutAddress, out timeoutUsec)) if (timeoutAddress != 0 && !ctx.TryReadUInt32(timeoutAddress, out timeoutUsec))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
Monitor.Enter(state.Gate); Monitor.Enter(state.Gate);
@@ -228,7 +228,7 @@ public static class KernelEventFlagCompatExports
{ {
if (TryCompleteSatisfiedWait(ctx, state, pattern, waitMode, resultAddress, out var immediateWaitResult)) if (TryCompleteSatisfiedWait(ctx, state, pattern, waitMode, resultAddress, out var immediateWaitResult))
{ {
return SetReturn(ctx, immediateWaitResult); return ctx.SetReturn(immediateWaitResult);
} }
if (timeoutAddress != 0) if (timeoutAddress != 0)
@@ -236,7 +236,7 @@ public static class KernelEventFlagCompatExports
_ = ctx.TryWriteUInt32(timeoutAddress, 0); _ = ctx.TryWriteUInt32(timeoutAddress, 0);
_ = TryWriteResultPattern(ctx, resultAddress, state.Bits); _ = TryWriteResultPattern(ctx, resultAddress, state.Bits);
TraceEventFlag($"wait-timeout handle=0x{handle:X16} pattern=0x{pattern:X16} timeout={timeoutUsec} ret=0x{returnRip:X16}"); TraceEventFlag($"wait-timeout handle=0x{handle:X16} pattern=0x{pattern:X16} timeout={timeoutUsec} ret=0x{returnRip:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT);
} }
var currentGuestThread = GuestThreadExecution.CurrentGuestThreadHandle; var currentGuestThread = GuestThreadExecution.CurrentGuestThreadHandle;
@@ -271,7 +271,7 @@ public static class KernelEventFlagCompatExports
var scheduler = GuestThreadExecution.Scheduler; var scheduler = GuestThreadExecution.Scheduler;
if (scheduler is null) if (scheduler is null)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN);
} }
state.WaitingThreads++; state.WaitingThreads++;
@@ -296,7 +296,7 @@ public static class KernelEventFlagCompatExports
state.WaitingThreads = Math.Max(0, state.WaitingThreads - 1); state.WaitingThreads = Math.Max(0, state.WaitingThreads - 1);
releaseWaiter = false; releaseWaiter = false;
TraceEventFlag($"wait-wake handle=0x{handle:X16} pattern=0x{pattern:X16} bits=0x{state.Bits:X16} waiters={state.WaitingThreads} ret=0x{returnRip:X16}"); TraceEventFlag($"wait-wake handle=0x{handle:X16} pattern=0x{pattern:X16} bits=0x{state.Bits:X16} waiters={state.WaitingThreads} ret=0x{returnRip:X16}");
return SetReturn(ctx, pumpedWaitResult); return ctx.SetReturn(pumpedWaitResult);
} }
Monitor.Wait(state.Gate, HostWaitPumpMilliseconds); Monitor.Wait(state.Gate, HostWaitPumpMilliseconds);
@@ -313,7 +313,7 @@ public static class KernelEventFlagCompatExports
state.WaitingThreads++; state.WaitingThreads++;
TraceEventFlag($"wait-block handle=0x{handle:X16} pattern=0x{pattern:X16} waiters={state.WaitingThreads} guest_thread=0x{currentGuestThread:X16} fiber=0x{currentFiber:X16} managed={managedThread} ret=0x{returnRip:X16}"); TraceEventFlag($"wait-block handle=0x{handle:X16} pattern=0x{pattern:X16} waiters={state.WaitingThreads} guest_thread=0x{currentGuestThread:X16} fiber=0x{currentFiber:X16} managed={managedThread} ret=0x{returnRip:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
finally finally
{ {
@@ -333,7 +333,7 @@ public static class KernelEventFlagCompatExports
var waiterCountAddress = ctx[CpuRegister.Rdx]; var waiterCountAddress = ctx[CpuRegister.Rdx];
if (!_eventFlags.TryGetValue(handle, out var state)) if (!_eventFlags.TryGetValue(handle, out var state))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
lock (state.Gate) lock (state.Gate)
@@ -341,7 +341,7 @@ public static class KernelEventFlagCompatExports
if (waiterCountAddress != 0 && if (waiterCountAddress != 0 &&
!ctx.TryWriteUInt32(waiterCountAddress, unchecked((uint)state.WaitingThreads))) !ctx.TryWriteUInt32(waiterCountAddress, unchecked((uint)state.WaitingThreads)))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
state.Bits = setPattern; state.Bits = setPattern;
@@ -350,7 +350,7 @@ public static class KernelEventFlagCompatExports
TraceEventFlag($"cancel handle=0x{handle:X16} bits=0x{setPattern:X16}"); TraceEventFlag($"cancel handle=0x{handle:X16} bits=0x{setPattern:X16}");
} }
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
private static bool IsValidAttributes(uint attributes) private static bool IsValidAttributes(uint attributes)
@@ -452,13 +452,6 @@ public static class KernelEventFlagCompatExports
private static bool TryWriteResultPattern(CpuContext ctx, ulong address, ulong bits) => private static bool TryWriteResultPattern(CpuContext ctx, ulong address, ulong bits) =>
address == 0 || ctx.TryWriteUInt64(address, bits); address == 0 || ctx.TryWriteUInt64(address, bits);
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
var value = (int)result;
ctx[CpuRegister.Rax] = unchecked((ulong)value);
return value;
}
private static void TraceEventFlag(string message) private static void TraceEventFlag(string message)
{ {
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_EVENT_FLAG"), "1", StringComparison.Ordinal)) if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_EVENT_FLAG"), "1", StringComparison.Ordinal))
@@ -2903,7 +2903,7 @@ public static class KernelMemoryCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
if (protectionOut != 0 && !TryWriteInt32(ctx, protectionOut, region.Protection)) if (protectionOut != 0 && !ctx.TryWriteInt32(protectionOut, region.Protection))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -2942,7 +2942,7 @@ public static class KernelMemoryCompatExports
if (!ctx.TryWriteUInt64(infoAddress, block.Start) || if (!ctx.TryWriteUInt64(infoAddress, block.Start) ||
!ctx.TryWriteUInt64(infoAddress + sizeof(ulong), block.Start + block.Length) || !ctx.TryWriteUInt64(infoAddress + sizeof(ulong), block.Start + block.Length) ||
!TryWriteInt32(ctx, infoAddress + (sizeof(ulong) * 2), block.MemoryType)) !ctx.TryWriteInt32(infoAddress + (sizeof(ulong) * 2), block.MemoryType))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -3800,7 +3800,7 @@ public static class KernelMemoryCompatExports
var addr = argumentSource.NextGpArg(); var addr = argumentSource.NextGpArg();
if (addr != 0) if (addr != 0)
{ {
_ = TryWriteInt32(ctx, addr, sb.Length); _ = ctx.TryWriteInt32(addr, sb.Length);
} }
} }
break; break;
@@ -4964,7 +4964,7 @@ public static class KernelMemoryCompatExports
processedCount++; processedCount++;
} }
if (processedOutAddress != 0 && !TryWriteInt32(ctx, processedOutAddress, processedCount)) if (processedOutAddress != 0 && !ctx.TryWriteInt32(processedOutAddress, processedCount))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -5801,13 +5801,6 @@ public static class KernelMemoryCompatExports
return (protect & expected) != 0; return (protect & expected) != 0;
} }
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BitConverter.TryWriteBytes(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
private static bool TryWriteOpenDescriptorStat(CpuContext ctx, int fd, ulong statAddress) private static bool TryWriteOpenDescriptorStat(CpuContext ctx, int fd, ulong statAddress)
{ {
if (fd is 0 or 1 or 2) if (fd is 0 or 1 or 2)
@@ -3,8 +3,6 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary;
using System.Threading;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
namespace SharpEmu.Libs.Kernel; namespace SharpEmu.Libs.Kernel;
@@ -389,42 +387,42 @@ public static class KernelPthreadCompatExports
var initRoutine = ctx[CpuRegister.Rsi]; var initRoutine = ctx[CpuRegister.Rsi];
if (onceAddress == 0 || initRoutine == 0) if (onceAddress == 0 || initRoutine == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!TryReadInt32(ctx, onceAddress, out var onceValue)) if (!ctx.TryReadInt32(onceAddress, out var onceValue))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (onceValue == PthreadOnceDone) if (onceValue == PthreadOnceDone)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
var gate = GetPthreadOnceGate(onceAddress); var gate = GetPthreadOnceGate(onceAddress);
var shouldCall = false; var shouldCall = false;
lock (gate) lock (gate)
{ {
if (!TryReadInt32(ctx, onceAddress, out onceValue)) if (!ctx.TryReadInt32(onceAddress, out onceValue))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
while (onceValue == PthreadOnceInProgress) while (onceValue == PthreadOnceInProgress)
{ {
Monitor.Wait(gate, TimeSpan.FromMilliseconds(1)); Monitor.Wait(gate, TimeSpan.FromMilliseconds(1));
if (!TryReadInt32(ctx, onceAddress, out onceValue)) if (!ctx.TryReadInt32(onceAddress, out onceValue))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
if (onceValue != PthreadOnceDone) if (onceValue != PthreadOnceDone)
{ {
if (!TryWriteInt32(ctx, onceAddress, PthreadOnceInProgress)) if (!ctx.TryWriteInt32(onceAddress, PthreadOnceInProgress))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
shouldCall = true; shouldCall = true;
@@ -440,21 +438,21 @@ public static class KernelPthreadCompatExports
{ {
lock (gate) lock (gate)
{ {
_ = TryWriteInt32(ctx, onceAddress, PthreadOnceUninitialized); _ = ctx.TryWriteInt32(onceAddress, PthreadOnceUninitialized);
Monitor.PulseAll(gate); Monitor.PulseAll(gate);
} }
TracePthreadOnce(onceAddress, initRoutine, "failed", error); TracePthreadOnce(onceAddress, initRoutine, "failed", error);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN);
} }
lock (gate) lock (gate)
{ {
if (!TryWriteInt32(ctx, onceAddress, PthreadOnceDone)) if (!ctx.TryWriteInt32(onceAddress, PthreadOnceDone))
{ {
_ = TryWriteInt32(ctx, onceAddress, PthreadOnceUninitialized); _ = ctx.TryWriteInt32(onceAddress, PthreadOnceUninitialized);
Monitor.PulseAll(gate); Monitor.PulseAll(gate);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
Monitor.PulseAll(gate); Monitor.PulseAll(gate);
@@ -462,7 +460,7 @@ public static class KernelPthreadCompatExports
} }
TracePthreadOnce(onceAddress, initRoutine, shouldCall ? "call" : "done", null); TracePthreadOnce(onceAddress, initRoutine, shouldCall ? "call" : "done", null);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
private static int PthreadMutexInitCore(CpuContext ctx, ulong mutexAddress, ulong attrAddress) private static int PthreadMutexInitCore(CpuContext ctx, ulong mutexAddress, ulong attrAddress)
@@ -1321,32 +1319,6 @@ public static class KernelPthreadCompatExports
} }
} }
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
}
private static bool TryReadInt32(CpuContext ctx, ulong address, out int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
if (!ctx.Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadInt32LittleEndian(bytes);
return true;
}
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
private static bool CreateImplicitMutexState(CpuContext ctx, ulong mutexAddress, int type, out ulong resolvedAddress, [NotNullWhen(true)] out PthreadMutexState? state) private static bool CreateImplicitMutexState(CpuContext ctx, ulong mutexAddress, int type, out ulong resolvedAddress, [NotNullWhen(true)] out PthreadMutexState? state)
{ {
var createdState = new PthreadMutexState var createdState = new PthreadMutexState
@@ -2,10 +2,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Text; using System.Text;
using System.Threading;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
namespace SharpEmu.Libs.Kernel; namespace SharpEmu.Libs.Kernel;
@@ -279,7 +277,7 @@ public static class KernelPthreadExtendedCompatExports
priority = GetOrCreateThreadStateLocked(thread).Priority; priority = GetOrCreateThreadStateLocked(thread).Priority;
} }
if (!TryWriteInt32(ctx, outPriorityAddress, priority)) if (!ctx.TryWriteInt32(outPriorityAddress, priority))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -326,7 +324,7 @@ public static class KernelPthreadExtendedCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
} }
if (!TryReadInt32(ctx, schedParamAddress, out var schedPriority)) if (!ctx.TryReadInt32(schedParamAddress, out var schedPriority))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -496,7 +494,7 @@ public static class KernelPthreadExtendedCompatExports
state = GetOrCreateAttrStateLocked(attrAddress); state = GetOrCreateAttrStateLocked(attrAddress);
} }
if (!TryWriteInt32(ctx, outStateAddress, state.DetachState)) if (!ctx.TryWriteInt32(outStateAddress, state.DetachState))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -739,7 +737,7 @@ public static class KernelPthreadExtendedCompatExports
state = GetOrCreateAttrStateLocked(attrAddress); state = GetOrCreateAttrStateLocked(attrAddress);
} }
if (!TryWriteInt32(ctx, schedParamAddress, state.SchedPriority)) if (!ctx.TryWriteInt32(schedParamAddress, state.SchedPriority))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -762,7 +760,7 @@ public static class KernelPthreadExtendedCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
} }
if (!TryReadInt32(ctx, schedParamAddress, out var schedPriority)) if (!ctx.TryReadInt32(schedParamAddress, out var schedPriority))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1114,7 +1112,7 @@ public static class KernelPthreadExtendedCompatExports
} }
} }
if (!TryWriteInt32(ctx, outKeyAddress, key)) if (!ctx.TryWriteInt32(outKeyAddress, key))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1451,24 +1449,4 @@ public static class KernelPthreadExtendedCompatExports
payload[^1] = 0; payload[^1] = 0;
return ctx.Memory.TryWrite(address, payload); return ctx.Memory.TryWrite(address, payload);
} }
private static bool TryReadInt32(CpuContext ctx, ulong address, out int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
if (!ctx.Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadInt32LittleEndian(bytes);
return true;
}
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
} }
@@ -4,14 +4,11 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using SharpEmu.Libs.Fiber; using SharpEmu.Libs.Fiber;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading;
namespace SharpEmu.Libs.Kernel; namespace SharpEmu.Libs.Kernel;
@@ -259,8 +256,8 @@ public static class KernelRuntimeCompatExports
} }
if (timezoneAddress != 0 && if (timezoneAddress != 0 &&
(!TryWriteInt32(ctx, timezoneAddress, 0) || (!ctx.TryWriteInt32(timezoneAddress, 0) ||
!TryWriteInt32(ctx, timezoneAddress + sizeof(int), 0))) !ctx.TryWriteInt32(timezoneAddress + sizeof(int), 0)))
{ {
return -1; return -1;
} }
@@ -617,7 +614,7 @@ public static class KernelRuntimeCompatExports
internal static bool TrySetErrno(CpuContext ctx, int value) internal static bool TrySetErrno(CpuContext ctx, int value)
{ {
var address = GetTlsScratchAddress(ctx, TlsErrnoOffset); var address = GetTlsScratchAddress(ctx, TlsErrnoOffset);
return address != 0 && TryWriteInt32(ctx, address, value); return address != 0 && ctx.TryWriteInt32(address, value);
} }
[SysAbiExport( [SysAbiExport(
@@ -827,7 +824,7 @@ public static class KernelRuntimeCompatExports
} }
var moduleHandle = ResolveModuleHandleByAddress(queriedAddress); var moduleHandle = ResolveModuleHandleByAddress(queriedAddress);
if (!TryWriteInt32(ctx, outInfoAddress + ModuleInfoHandleOffset, moduleHandle)) if (!ctx.TryWriteInt32(outInfoAddress + ModuleInfoHandleOffset, moduleHandle))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -857,7 +854,7 @@ public static class KernelRuntimeCompatExports
} }
var moduleHandle = ResolveModuleHandleByAddress(queriedAddress); var moduleHandle = ResolveModuleHandleByAddress(queriedAddress);
if (!TryWriteInt32(ctx, outInfoAddress + ModuleInfoHandleOffset, moduleHandle)) if (!ctx.TryWriteInt32(outInfoAddress + ModuleInfoHandleOffset, moduleHandle))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1058,7 +1055,7 @@ public static class KernelRuntimeCompatExports
public static int KernelStopUnloadModule(CpuContext ctx) public static int KernelStopUnloadModule(CpuContext ctx)
{ {
var resultAddress = ctx[CpuRegister.R9]; var resultAddress = ctx[CpuRegister.R9];
if (resultAddress != 0 && !TryWriteInt32(ctx, resultAddress, 0)) if (resultAddress != 0 && !ctx.TryWriteInt32(resultAddress, 0))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1076,7 +1073,7 @@ public static class KernelRuntimeCompatExports
{ {
var modulePathAddress = ctx[CpuRegister.Rdi]; var modulePathAddress = ctx[CpuRegister.Rdi];
var resultAddress = ctx[CpuRegister.R9]; var resultAddress = ctx[CpuRegister.R9];
if (resultAddress != 0 && !TryWriteInt32(ctx, resultAddress, 0)) if (resultAddress != 0 && !ctx.TryWriteInt32(resultAddress, 0))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1233,8 +1230,8 @@ public static class KernelRuntimeCompatExports
: 0; : 0;
var minutesWest = unchecked((int)-offset.TotalMinutes); var minutesWest = unchecked((int)-offset.TotalMinutes);
if (!TryWriteInt32(ctx, timezoneAddress, minutesWest) || if (!ctx.TryWriteInt32(timezoneAddress, minutesWest) ||
!TryWriteInt32(ctx, timezoneAddress + sizeof(int), dstSeconds / 60)) !ctx.TryWriteInt32(timezoneAddress + sizeof(int), dstSeconds / 60))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1244,7 +1241,7 @@ public static class KernelRuntimeCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
if (dstSecondsAddress != 0 && !TryWriteInt32(ctx, dstSecondsAddress, dstSeconds)) if (dstSecondsAddress != 0 && !ctx.TryWriteInt32(dstSecondsAddress, dstSeconds))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1304,7 +1301,7 @@ public static class KernelRuntimeCompatExports
_loadedSysmodules.Add(moduleId); _loadedSysmodules.Add(moduleId);
} }
if (resultAddress != 0 && !TryWriteInt32(ctx, resultAddress, 0)) if (resultAddress != 0 && !ctx.TryWriteInt32(resultAddress, 0))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1394,7 +1391,7 @@ public static class KernelRuntimeCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
} }
if (!TryWriteInt32(ctx, outInfoAddress + ModuleInfoHandleOffset, module.Handle)) if (!ctx.TryWriteInt32(outInfoAddress + ModuleInfoHandleOffset, module.Handle))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1431,7 +1428,7 @@ public static class KernelRuntimeCompatExports
var writableCount = (int)Math.Min(Math.Min(capacity, (ulong)int.MaxValue), (ulong)handles.Length); var writableCount = (int)Math.Min(Math.Min(capacity, (ulong)int.MaxValue), (ulong)handles.Length);
for (var i = 0; i < writableCount; i++) for (var i = 0; i < writableCount; i++)
{ {
if (!TryWriteInt32(ctx, handlesAddress + (ulong)(i * sizeof(int)), handles[i])) if (!ctx.TryWriteInt32(handlesAddress + (ulong)(i * sizeof(int)), handles[i]))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -1504,13 +1501,6 @@ public static class KernelRuntimeCompatExports
return unchecked(ctx.FsBase + offset); return unchecked(ctx.FsBase + offset);
} }
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
private static nint AllocateStackChkGuardObject() private static nint AllocateStackChkGuardObject()
{ {
try try
@@ -44,12 +44,12 @@ public static class KernelSemaphoreCompatExports
initialCount > maxCount || initialCount > maxCount ||
optionAddress != 0) optionAddress != 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxSemaphoreNameLength, out var name)) if (!ctx.TryReadNullTerminatedUtf8(nameAddress, MaxSemaphoreNameLength, out var name))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
var handle = unchecked((uint)Interlocked.Increment(ref _nextSemaphoreHandle)); var handle = unchecked((uint)Interlocked.Increment(ref _nextSemaphoreHandle));
@@ -69,11 +69,11 @@ public static class KernelSemaphoreCompatExports
if (!ctx.TryWriteUInt32(semaphoreAddress, handle)) if (!ctx.TryWriteUInt32(semaphoreAddress, handle))
{ {
_semaphores.TryRemove(handle, out _); _semaphores.TryRemove(handle, out _);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceSemaphore($"create handle=0x{handle:X8} name='{name}' attr=0x{attr:X} init={initialCount} max={maxCount}"); TraceSemaphore($"create handle=0x{handle:X8} name='{name}' attr=0x{attr:X} init={initialCount} max={maxCount}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -89,12 +89,12 @@ public static class KernelSemaphoreCompatExports
if (!_semaphores.TryGetValue(handle, out var semaphore)) if (!_semaphores.TryGetValue(handle, out var semaphore))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (needCount < 1 || needCount > semaphore.MaxCount) if (needCount < 1 || needCount > semaphore.MaxCount)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
lock (semaphore.Gate) lock (semaphore.Gate)
@@ -103,30 +103,30 @@ public static class KernelSemaphoreCompatExports
{ {
semaphore.Count -= needCount; semaphore.Count -= needCount;
TraceSemaphore($"wait handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}"); TraceSemaphore($"wait handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
if (timeoutAddress != 0) if (timeoutAddress != 0)
{ {
if (!ctx.TryReadUInt32(timeoutAddress, out _)) if (!ctx.TryReadUInt32(timeoutAddress, out _))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
_ = ctx.TryWriteUInt32(timeoutAddress, 0); _ = ctx.TryWriteUInt32(timeoutAddress, 0);
TraceSemaphore($"wait-timeout handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}"); TraceSemaphore($"wait-timeout handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT);
} }
if (!GuestThreadExecution.RequestCurrentThreadBlock(ctx, "sceKernelWaitSema")) if (!GuestThreadExecution.RequestCurrentThreadBlock(ctx, "sceKernelWaitSema"))
{ {
TraceSemaphore($"wait-would-block handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}"); TraceSemaphore($"wait-would-block handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_TRY_AGAIN);
} }
semaphore.WaitingThreads++; semaphore.WaitingThreads++;
TraceSemaphore($"wait-block handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count} waiters={semaphore.WaitingThreads}"); TraceSemaphore($"wait-block handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count} waiters={semaphore.WaitingThreads}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
} }
@@ -142,12 +142,12 @@ public static class KernelSemaphoreCompatExports
if (!_semaphores.TryGetValue(handle, out var semaphore)) if (!_semaphores.TryGetValue(handle, out var semaphore))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (needCount < 1 || needCount > semaphore.MaxCount) if (needCount < 1 || needCount > semaphore.MaxCount)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
lock (semaphore.Gate) lock (semaphore.Gate)
@@ -155,12 +155,12 @@ public static class KernelSemaphoreCompatExports
if (semaphore.Count < needCount) if (semaphore.Count < needCount)
{ {
TraceSemaphore($"poll-busy handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}"); TraceSemaphore($"poll-busy handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_BUSY); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_BUSY);
} }
semaphore.Count -= needCount; semaphore.Count -= needCount;
TraceSemaphore($"poll handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}"); TraceSemaphore($"poll handle=0x{handle:X8} name='{semaphore.Name}' need={needCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
} }
@@ -176,24 +176,24 @@ public static class KernelSemaphoreCompatExports
if (!_semaphores.TryGetValue(handle, out var semaphore)) if (!_semaphores.TryGetValue(handle, out var semaphore))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (signalCount <= 0) if (signalCount <= 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
lock (semaphore.Gate) lock (semaphore.Gate)
{ {
if (semaphore.Count > semaphore.MaxCount - signalCount) if (semaphore.Count > semaphore.MaxCount - signalCount)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
semaphore.Count += signalCount; semaphore.Count += signalCount;
TraceSemaphore($"signal handle=0x{handle:X8} name='{semaphore.Name}' signal={signalCount} count={semaphore.Count} waiters={semaphore.WaitingThreads}"); TraceSemaphore($"signal handle=0x{handle:X8} name='{semaphore.Name}' signal={signalCount} count={semaphore.Count} waiters={semaphore.WaitingThreads}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
} }
@@ -210,25 +210,25 @@ public static class KernelSemaphoreCompatExports
if (!_semaphores.TryGetValue(handle, out var semaphore)) if (!_semaphores.TryGetValue(handle, out var semaphore))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
if (setCount > semaphore.MaxCount) if (setCount > semaphore.MaxCount)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
lock (semaphore.Gate) lock (semaphore.Gate)
{ {
if (waitingThreadsAddress != 0 && !ctx.TryWriteUInt32(waitingThreadsAddress, unchecked((uint)semaphore.WaitingThreads))) if (waitingThreadsAddress != 0 && !ctx.TryWriteUInt32(waitingThreadsAddress, unchecked((uint)semaphore.WaitingThreads)))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
semaphore.Count = setCount < 0 ? semaphore.InitialCount : setCount; semaphore.Count = setCount < 0 ? semaphore.InitialCount : setCount;
semaphore.WaitingThreads = 0; semaphore.WaitingThreads = 0;
TraceSemaphore($"cancel handle=0x{handle:X8} name='{semaphore.Name}' set={setCount} count={semaphore.Count}"); TraceSemaphore($"cancel handle=0x{handle:X8} name='{semaphore.Name}' set={setCount} count={semaphore.Count}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
} }
@@ -242,18 +242,11 @@ public static class KernelSemaphoreCompatExports
var handle = unchecked((uint)ctx[CpuRegister.Rdi]); var handle = unchecked((uint)ctx[CpuRegister.Rdi]);
if (!_semaphores.TryRemove(handle, out var semaphore)) if (!_semaphores.TryRemove(handle, out var semaphore))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
} }
TraceSemaphore($"delete handle=0x{handle:X8} name='{semaphore.Name}'"); TraceSemaphore($"delete handle=0x{handle:X8} name='{semaphore.Name}'");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
}
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
var value = (int)result;
ctx[CpuRegister.Rax] = unchecked((ulong)value);
return value;
} }
private static void TraceSemaphore(string message) private static void TraceSemaphore(string message)
+3 -11
View File
@@ -1,9 +1,7 @@
// Copyright (C) 2026 SharpEmu Emulator Project // Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
using SharpEmu.HLE; using SharpEmu.HLE;
namespace SharpEmu.Libs.Network; namespace SharpEmu.Libs.Network;
@@ -32,7 +30,7 @@ public static class Http2Exports
if (poolSize == 0 || maxRequests <= 0) if (poolSize == 0 || maxRequests <= 0)
{ {
return SetReturn(ctx, Http2ErrorInvalidArgument); return ctx.SetReturn(Http2ErrorInvalidArgument);
} }
var id = Interlocked.Increment(ref _nextContextId); var id = Interlocked.Increment(ref _nextContextId);
@@ -53,17 +51,11 @@ public static class Http2Exports
var id = unchecked((int)ctx[CpuRegister.Rdi]); var id = unchecked((int)ctx[CpuRegister.Rdi]);
if (!_contexts.TryRemove(id, out _)) if (!_contexts.TryRemove(id, out _))
{ {
return SetReturn(ctx, Http2ErrorInvalidId); return ctx.SetReturn(Http2ErrorInvalidId);
} }
TraceHttp2("term", id, 0, 0, 0, 0); TraceHttp2("term", id, 0, 0, 0, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
private static void TraceHttp2(string operation, int id, ulong arg0, ulong arg1, ulong arg2, ulong arg3) private static void TraceHttp2(string operation, int id, ulong arg0, ulong arg1, ulong arg2, ulong arg3)
+6 -13
View File
@@ -3,7 +3,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
namespace SharpEmu.Libs.Network; namespace SharpEmu.Libs.Network;
@@ -33,7 +32,7 @@ public static class HttpExports
var poolSize = ctx[CpuRegister.Rdx]; var poolSize = ctx[CpuRegister.Rdx];
if (poolSize == 0) if (poolSize == 0)
{ {
return SetReturn(ctx, HttpErrorInvalidValue); return ctx.SetReturn(HttpErrorInvalidValue);
} }
var id = Interlocked.Increment(ref _nextContextId); var id = Interlocked.Increment(ref _nextContextId);
@@ -53,7 +52,7 @@ public static class HttpExports
var contextId = unchecked((int)ctx[CpuRegister.Rdi]); var contextId = unchecked((int)ctx[CpuRegister.Rdi]);
if (!Contexts.ContainsKey(contextId)) if (!Contexts.ContainsKey(contextId))
{ {
return SetReturn(ctx, HttpErrorInvalidId); return ctx.SetReturn(HttpErrorInvalidId);
} }
var userAgentAddress = ctx[CpuRegister.Rsi]; var userAgentAddress = ctx[CpuRegister.Rsi];
@@ -75,8 +74,8 @@ public static class HttpExports
{ {
var templateId = unchecked((int)ctx[CpuRegister.Rdi]); var templateId = unchecked((int)ctx[CpuRegister.Rdi]);
return Templates.TryRemove(templateId, out _) return Templates.TryRemove(templateId, out _)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, HttpErrorInvalidId); : ctx.SetReturn(HttpErrorInvalidId);
} }
[SysAbiExport( [SysAbiExport(
@@ -89,7 +88,7 @@ public static class HttpExports
var contextId = unchecked((int)ctx[CpuRegister.Rdi]); var contextId = unchecked((int)ctx[CpuRegister.Rdi]);
if (!Contexts.TryRemove(contextId, out _)) if (!Contexts.TryRemove(contextId, out _))
{ {
return SetReturn(ctx, HttpErrorInvalidId); return ctx.SetReturn(HttpErrorInvalidId);
} }
foreach (var pair in Templates) foreach (var pair in Templates)
@@ -100,13 +99,7 @@ public static class HttpExports
} }
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
private static void TraceHttp(string operation, int id, ulong arg0, ulong arg1, ulong arg2, ulong arg3) private static void TraceHttp(string operation, int id, ulong arg0, ulong arg1, ulong arg2, ulong arg3)
+23 -29
View File
@@ -57,27 +57,27 @@ public static class NetCtlExports
var natInfoAddress = ctx[CpuRegister.Rdi]; var natInfoAddress = ctx[CpuRegister.Rdi];
if (natInfoAddress == 0) if (natInfoAddress == 0)
{ {
return SetReturn(ctx, NetCtlErrorInvalidAddress); return ctx.SetReturn(NetCtlErrorInvalidAddress, typeof(long));
} }
Span<byte> natInfo = stackalloc byte[NatInfoSize]; Span<byte> natInfo = stackalloc byte[NatInfoSize];
if (!ctx.Memory.TryRead(natInfoAddress, natInfo)) if (!ctx.Memory.TryRead(natInfoAddress, natInfo))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
var size = BinaryPrimitives.ReadUInt32LittleEndian(natInfo[..sizeof(uint)]); var size = BinaryPrimitives.ReadUInt32LittleEndian(natInfo[..sizeof(uint)]);
if (size != NatInfoSize) if (size != NatInfoSize)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT, typeof(long));
} }
BinaryPrimitives.WriteInt32LittleEndian(natInfo[4..], 1); BinaryPrimitives.WriteInt32LittleEndian(natInfo[4..], 1);
BinaryPrimitives.WriteInt32LittleEndian(natInfo[8..], 3); BinaryPrimitives.WriteInt32LittleEndian(natInfo[8..], 3);
BinaryPrimitives.WriteUInt32LittleEndian(natInfo[12..], 0x7F000001); BinaryPrimitives.WriteUInt32LittleEndian(natInfo[12..], 0x7F000001);
return ctx.Memory.TryWrite(natInfoAddress, natInfo) return ctx.Memory.TryWrite(natInfoAddress, natInfo)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -87,7 +87,7 @@ public static class NetCtlExports
LibraryName = "libSceNetCtl")] LibraryName = "libSceNetCtl")]
public static int NetCtlCheckCallback(CpuContext ctx) public static int NetCtlCheckCallback(CpuContext ctx)
{ {
return SetReturn(ctx, 0); return ctx.SetReturn(0, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -100,14 +100,14 @@ public static class NetCtlExports
var stateAddress = ctx[CpuRegister.Rdi]; var stateAddress = ctx[CpuRegister.Rdi];
if (stateAddress == 0) if (stateAddress == 0)
{ {
return SetReturn(ctx, NetCtlErrorInvalidAddress); return ctx.SetReturn(NetCtlErrorInvalidAddress, typeof(long));
} }
Span<byte> stateBytes = stackalloc byte[sizeof(int)]; Span<byte> stateBytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(stateBytes, 0); BinaryPrimitives.WriteInt32LittleEndian(stateBytes, 0);
return ctx.Memory.TryWrite(stateAddress, stateBytes) return ctx.Memory.TryWrite(stateAddress, stateBytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -122,7 +122,7 @@ public static class NetCtlExports
var callbackIdAddress = ctx[CpuRegister.Rdx]; var callbackIdAddress = ctx[CpuRegister.Rdx];
if (function == 0 || callbackIdAddress == 0) if (function == 0 || callbackIdAddress == 0)
{ {
return SetReturn(ctx, NetCtlErrorInvalidAddress); return ctx.SetReturn(NetCtlErrorInvalidAddress, typeof(long));
} }
lock (CallbackGate) lock (CallbackGate)
@@ -130,20 +130,20 @@ public static class NetCtlExports
var callbackId = Array.FindIndex(Callbacks, static callback => callback.Function == 0); var callbackId = Array.FindIndex(Callbacks, static callback => callback.Function == 0);
if (callbackId < 0) if (callbackId < 0)
{ {
return SetReturn(ctx, NetCtlErrorNoSpace); return ctx.SetReturn(NetCtlErrorNoSpace, typeof(long));
} }
Span<byte> callbackIdBytes = stackalloc byte[sizeof(uint)]; Span<byte> callbackIdBytes = stackalloc byte[sizeof(uint)];
BinaryPrimitives.WriteUInt32LittleEndian(callbackIdBytes, unchecked((uint)callbackId)); BinaryPrimitives.WriteUInt32LittleEndian(callbackIdBytes, unchecked((uint)callbackId));
if (!ctx.Memory.TryWrite(callbackIdAddress, callbackIdBytes)) if (!ctx.Memory.TryWrite(callbackIdAddress, callbackIdBytes))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
Callbacks[callbackId] = new CallbackRegistration(function, argument); Callbacks[callbackId] = new CallbackRegistration(function, argument);
} }
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_OK, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -157,7 +157,7 @@ public static class NetCtlExports
var infoAddress = ctx[CpuRegister.Rsi]; var infoAddress = ctx[CpuRegister.Rsi];
if (infoAddress == 0) if (infoAddress == 0)
{ {
return SetReturn(ctx, NetCtlErrorInvalidAddress); return ctx.SetReturn(NetCtlErrorInvalidAddress, typeof(long));
} }
return code switch return code switch
@@ -177,7 +177,7 @@ public static class NetCtlExports
NetCtlInfoHttpProxyConfig => WriteUInt32(ctx, infoAddress, 0), NetCtlInfoHttpProxyConfig => WriteUInt32(ctx, infoAddress, 0),
NetCtlInfoHttpProxyServer => WriteAsciiZ(ctx, infoAddress, string.Empty, 256), NetCtlInfoHttpProxyServer => WriteAsciiZ(ctx, infoAddress, string.Empty, 256),
NetCtlInfoHttpProxyPort => WriteUInt16(ctx, infoAddress, 0), NetCtlInfoHttpProxyPort => WriteUInt16(ctx, infoAddress, 0),
_ => SetReturn(ctx, NetCtlErrorNotConnected), _ => ctx.SetReturn(NetCtlErrorNotConnected, typeof(long)),
}; };
} }
@@ -185,8 +185,8 @@ public static class NetCtlExports
{ {
Span<byte> bytes = stackalloc byte[count]; Span<byte> bytes = stackalloc byte[count];
return ctx.Memory.TryWrite(address, bytes) return ctx.Memory.TryWrite(address, bytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
private static int WriteUInt32(CpuContext ctx, ulong address, uint value) private static int WriteUInt32(CpuContext ctx, ulong address, uint value)
@@ -194,8 +194,8 @@ public static class NetCtlExports
Span<byte> bytes = stackalloc byte[sizeof(uint)]; Span<byte> bytes = stackalloc byte[sizeof(uint)];
BinaryPrimitives.WriteUInt32LittleEndian(bytes, value); BinaryPrimitives.WriteUInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes) return ctx.Memory.TryWrite(address, bytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
private static int WriteUInt16(CpuContext ctx, ulong address, ushort value) private static int WriteUInt16(CpuContext ctx, ulong address, ushort value)
@@ -203,8 +203,8 @@ public static class NetCtlExports
Span<byte> bytes = stackalloc byte[sizeof(ushort)]; Span<byte> bytes = stackalloc byte[sizeof(ushort)];
BinaryPrimitives.WriteUInt16LittleEndian(bytes, value); BinaryPrimitives.WriteUInt16LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes) return ctx.Memory.TryWrite(address, bytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
private static int WriteAsciiZ(CpuContext ctx, ulong address, string value, int byteCount) private static int WriteAsciiZ(CpuContext ctx, ulong address, string value, int byteCount)
@@ -217,13 +217,7 @@ public static class NetCtlExports
} }
return ctx.Memory.TryWrite(address, bytes) return ctx.Memory.TryWrite(address, bytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(long)result);
return result;
} }
} }
+12 -20
View File
@@ -1,11 +1,9 @@
// Copyright (C) 2026 SharpEmu Emulator Project // Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Text; using System.Text;
using System.Threading;
using SharpEmu.HLE; using SharpEmu.HLE;
namespace SharpEmu.Libs.Network; namespace SharpEmu.Libs.Network;
@@ -35,7 +33,7 @@ public static class NetExports
{ {
_initialized = true; _initialized = true;
TraceNet("init", 0, 0, 0, 0); TraceNet("init", 0, 0, 0, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -49,7 +47,7 @@ public static class NetExports
_pools.Clear(); _pools.Clear();
_resolvers.Clear(); _resolvers.Clear();
TraceNet("term", 0, 0, 0, 0); TraceNet("term", 0, 0, 0, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -65,7 +63,7 @@ public static class NetExports
if (size <= 0) if (size <= 0)
{ {
return SetReturn(ctx, NetErrorInvalidArgument); return ctx.SetReturn(NetErrorInvalidArgument);
} }
var name = TryReadUtf8Z(ctx, nameAddress, MaxNameLength, out var value) var name = TryReadUtf8Z(ctx, nameAddress, MaxNameLength, out var value)
@@ -90,11 +88,11 @@ public static class NetExports
var id = unchecked((int)ctx[CpuRegister.Rdi]); var id = unchecked((int)ctx[CpuRegister.Rdi]);
if (!_pools.TryRemove(id, out _)) if (!_pools.TryRemove(id, out _))
{ {
return SetReturn(ctx, NetErrorBadFileDescriptor); return ctx.SetReturn(NetErrorBadFileDescriptor);
} }
TraceNet("pool.destroy", id, 0, 0, _initialized ? 1UL : 0UL); TraceNet("pool.destroy", id, 0, 0, _initialized ? 1UL : 0UL);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -109,7 +107,7 @@ public static class NetExports
var flags = unchecked((int)ctx[CpuRegister.Rdx]); var flags = unchecked((int)ctx[CpuRegister.Rdx]);
if (flags != 0) if (flags != 0)
{ {
return SetReturn(ctx, NetErrorInvalidArgument); return ctx.SetReturn(NetErrorInvalidArgument);
} }
var name = TryReadUtf8Z(ctx, nameAddress, MaxNameLength, out var value) var name = TryReadUtf8Z(ctx, nameAddress, MaxNameLength, out var value)
@@ -131,8 +129,8 @@ public static class NetExports
{ {
var id = unchecked((int)ctx[CpuRegister.Rdi]); var id = unchecked((int)ctx[CpuRegister.Rdi]);
return _resolvers.TryRemove(id, out _) return _resolvers.TryRemove(id, out _)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, NetErrorBadFileDescriptor); : ctx.SetReturn(NetErrorBadFileDescriptor);
} }
[SysAbiExport( [SysAbiExport(
@@ -146,25 +144,19 @@ public static class NetExports
var statusAddress = ctx[CpuRegister.Rsi]; var statusAddress = ctx[CpuRegister.Rsi];
if (statusAddress == 0) if (statusAddress == 0)
{ {
return SetReturn(ctx, NetErrorInvalidArgument); return ctx.SetReturn(NetErrorInvalidArgument);
} }
if (!_resolvers.TryGetValue(id, out var resolver)) if (!_resolvers.TryGetValue(id, out var resolver))
{ {
return SetReturn(ctx, NetErrorBadFileDescriptor); return ctx.SetReturn(NetErrorBadFileDescriptor);
} }
Span<byte> status = stackalloc byte[sizeof(int)]; Span<byte> status = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(status, resolver.LastError); BinaryPrimitives.WriteInt32LittleEndian(status, resolver.LastError);
return ctx.Memory.TryWrite(statusAddress, status) return ctx.Memory.TryWrite(statusAddress, status)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
private static bool TryReadUtf8Z(CpuContext ctx, ulong address, int maxLength, out string value) private static bool TryReadUtf8Z(CpuContext ctx, ulong address, int maxLength, out string value)
+4 -12
View File
@@ -1,9 +1,7 @@
// Copyright (C) 2026 SharpEmu Emulator Project // Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
using SharpEmu.HLE; using SharpEmu.HLE;
namespace SharpEmu.Libs.Network; namespace SharpEmu.Libs.Network;
@@ -28,7 +26,7 @@ public static class SslExports
var poolSize = ctx[CpuRegister.Rdi]; var poolSize = ctx[CpuRegister.Rdi];
if (poolSize == 0) if (poolSize == 0)
{ {
return SetReturn(ctx, SslErrorOutOfSize); return ctx.SetReturn(SslErrorOutOfSize);
} }
var id = Interlocked.Increment(ref _nextContextId); var id = Interlocked.Increment(ref _nextContextId);
@@ -49,11 +47,11 @@ public static class SslExports
var id = unchecked((int)ctx[CpuRegister.Rdi]); var id = unchecked((int)ctx[CpuRegister.Rdi]);
if (!_contexts.TryRemove(id, out _)) if (!_contexts.TryRemove(id, out _))
{ {
return SetReturn(ctx, SslErrorInvalidId); return ctx.SetReturn(SslErrorInvalidId);
} }
TraceSsl("term", id, 0); TraceSsl("term", id, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -65,13 +63,7 @@ public static class SslExports
{ {
var id = unchecked((int)ctx[CpuRegister.Rdi]); var id = unchecked((int)ctx[CpuRegister.Rdi]);
TraceSsl("close", id, 0); TraceSsl("close", id, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
private static void TraceSsl(string operation, int id, ulong arg0) private static void TraceSsl(string operation, int id, ulong arg0)
+26 -32
View File
@@ -4,7 +4,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using SharpEmu.Libs.Kernel; using SharpEmu.Libs.Kernel;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Threading;
namespace SharpEmu.Libs.Ngs2; namespace SharpEmu.Libs.Ngs2;
@@ -39,13 +38,13 @@ public static class Ngs2Exports
var outHandleAddress = ctx[CpuRegister.Rdx]; var outHandleAddress = ctx[CpuRegister.Rdx];
if (outHandleAddress == 0) if (outHandleAddress == 0)
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidOutAddress); return ctx.SetReturn(OrbisNgs2ErrorInvalidOutAddress);
} }
if (!TryCreateHandle(ctx, type: 1, ownerHandle: 0, out var handle) || if (!TryCreateHandle(ctx, type: 1, ownerHandle: 0, out var handle) ||
!ctx.TryWriteUInt64(outHandleAddress, handle)) !ctx.TryWriteUInt64(outHandleAddress, handle))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
lock (StateGate) lock (StateGate)
@@ -53,7 +52,7 @@ public static class Ngs2Exports
Systems[handle] = new SystemState(unchecked((uint)Interlocked.Increment(ref _nextUid))); Systems[handle] = new SystemState(unchecked((uint)Interlocked.Increment(ref _nextUid)));
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -68,7 +67,7 @@ public static class Ngs2Exports
{ {
if (!Systems.Remove(handle)) if (!Systems.Remove(handle))
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidSystemHandle); return ctx.SetReturn(OrbisNgs2ErrorInvalidSystemHandle);
} }
var rackHandles = Racks var rackHandles = Racks
@@ -81,7 +80,7 @@ public static class Ngs2Exports
} }
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -98,19 +97,19 @@ public static class Ngs2Exports
{ {
if (!Systems.ContainsKey(systemHandle)) if (!Systems.ContainsKey(systemHandle))
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidSystemHandle); return ctx.SetReturn(OrbisNgs2ErrorInvalidSystemHandle);
} }
} }
if (outHandleAddress == 0) if (outHandleAddress == 0)
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidOutAddress); return ctx.SetReturn(OrbisNgs2ErrorInvalidOutAddress);
} }
if (!TryCreateHandle(ctx, type: 2, systemHandle, out var handle) || if (!TryCreateHandle(ctx, type: 2, systemHandle, out var handle) ||
!ctx.TryWriteUInt64(outHandleAddress, handle)) !ctx.TryWriteUInt64(outHandleAddress, handle))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
lock (StateGate) lock (StateGate)
@@ -118,7 +117,7 @@ public static class Ngs2Exports
Racks[handle] = new RackState(systemHandle, rackId); Racks[handle] = new RackState(systemHandle, rackId);
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -133,13 +132,13 @@ public static class Ngs2Exports
{ {
if (!Racks.ContainsKey(handle)) if (!Racks.ContainsKey(handle))
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidRackHandle); return ctx.SetReturn(OrbisNgs2ErrorInvalidRackHandle);
} }
RemoveRackLocked(handle); RemoveRackLocked(handle);
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -156,7 +155,7 @@ public static class Ngs2Exports
{ {
if (!Racks.ContainsKey(rackHandle)) if (!Racks.ContainsKey(rackHandle))
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidRackHandle); return ctx.SetReturn(OrbisNgs2ErrorInvalidRackHandle);
} }
var existing = Voices.FirstOrDefault( var existing = Voices.FirstOrDefault(
@@ -164,20 +163,20 @@ public static class Ngs2Exports
if (existing.Key != 0) if (existing.Key != 0)
{ {
return ctx.TryWriteUInt64(outHandleAddress, existing.Key) return ctx.TryWriteUInt64(outHandleAddress, existing.Key)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
if (outHandleAddress == 0) if (outHandleAddress == 0)
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidOutAddress); return ctx.SetReturn(OrbisNgs2ErrorInvalidOutAddress);
} }
if (!TryCreateHandle(ctx, type: 4, rackHandle, out var handle) || if (!TryCreateHandle(ctx, type: 4, rackHandle, out var handle) ||
!ctx.TryWriteUInt64(outHandleAddress, handle)) !ctx.TryWriteUInt64(outHandleAddress, handle))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
lock (StateGate) lock (StateGate)
@@ -185,7 +184,7 @@ public static class Ngs2Exports
Voices[handle] = new VoiceState(rackHandle, voiceIndex); Voices[handle] = new VoiceState(rackHandle, voiceIndex);
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -197,9 +196,10 @@ public static class Ngs2Exports
{ {
lock (StateGate) lock (StateGate)
{ {
return SetReturn( return ctx.SetReturn(
ctx, Voices.ContainsKey(ctx[CpuRegister.Rdi])
Voices.ContainsKey(ctx[CpuRegister.Rdi]) ? 0 : OrbisNgs2ErrorInvalidVoiceHandle); ? 0
: OrbisNgs2ErrorInvalidVoiceHandle);
} }
} }
@@ -224,13 +224,13 @@ public static class Ngs2Exports
{ {
if (!Systems.ContainsKey(systemHandle)) if (!Systems.ContainsKey(systemHandle))
{ {
return SetReturn(ctx, OrbisNgs2ErrorInvalidSystemHandle); return ctx.SetReturn(OrbisNgs2ErrorInvalidSystemHandle);
} }
} }
if (bufferInfoCount != 0 && bufferInfoAddress == 0) if (bufferInfoCount != 0 && bufferInfoAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
for (uint i = 0; i < bufferInfoCount; i++) for (uint i = 0; i < bufferInfoCount; i++)
@@ -239,14 +239,14 @@ public static class Ngs2Exports
if (!ctx.TryReadUInt64(entryAddress, out var bufferAddress) || if (!ctx.TryReadUInt64(entryAddress, out var bufferAddress) ||
!ctx.TryReadUInt64(entryAddress + 8, out var bufferSize)) !ctx.TryReadUInt64(entryAddress + 8, out var bufferSize))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (bufferAddress != 0 && bufferSize != 0) if (bufferAddress != 0 && bufferSize != 0)
{ {
if (bufferSize > MaximumRenderBufferSize || !TryClearGuestBuffer(ctx, bufferAddress, bufferSize)) if (bufferSize > MaximumRenderBufferSize || !TryClearGuestBuffer(ctx, bufferAddress, bufferSize))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
} }
@@ -258,7 +258,7 @@ public static class Ngs2Exports
$"[LOADER][TRACE] ngs2.render#{count} system=0x{systemHandle:X16} buffers={bufferInfoCount}"); $"[LOADER][TRACE] ngs2.render#{count} system=0x{systemHandle:X16} buffers={bufferInfoCount}");
} }
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
private static bool TryCreateHandle(CpuContext ctx, uint type, ulong ownerHandle, out ulong handle) private static bool TryCreateHandle(CpuContext ctx, uint type, ulong ownerHandle, out ulong handle)
@@ -313,10 +313,4 @@ public static class Ngs2Exports
Environment.GetEnvironmentVariable("SHARPEMU_LOG_NGS2"), Environment.GetEnvironmentVariable("SHARPEMU_LOG_NGS2"),
"1", "1",
StringComparison.Ordinal); StringComparison.Ordinal);
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
} }
@@ -26,12 +26,12 @@ public static class NpEntitlementAccessExports
clear.Clear(); clear.Clear();
if (!ctx.Memory.TryWrite(bootParam, clear)) if (!ctx.Memory.TryWrite(bootParam, clear))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
TraceNpEntitlementAccess($"initialize init=0x{initParam:X16} boot=0x{bootParam:X16}"); TraceNpEntitlementAccess($"initialize init=0x{initParam:X16} boot=0x{bootParam:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -48,20 +48,14 @@ public static class NpEntitlementAccessExports
emptyList.Clear(); emptyList.Clear();
if (!ctx.Memory.TryWrite(listAddress, emptyList)) if (!ctx.Memory.TryWrite(listAddress, emptyList))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
TraceNpEntitlementAccess( TraceNpEntitlementAccess(
$"get_addcont_info_list service=0x{ctx[CpuRegister.Rdi]:X16} list=0x{listAddress:X16} " + $"get_addcont_info_list service=0x{ctx[CpuRegister.Rdi]:X16} list=0x{listAddress:X16} " +
$"max={ctx[CpuRegister.Rdx]} flags=0x{ctx[CpuRegister.Rcx]:X16} -> empty"); $"max={ctx[CpuRegister.Rdx]} flags=0x{ctx[CpuRegister.Rcx]:X16} -> empty");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
}
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
} }
private static void TraceNpEntitlementAccess(string message) private static void TraceNpEntitlementAccess(string message)
+6 -12
View File
@@ -76,14 +76,14 @@ public static class NpManagerExports
var stateAddress = ctx[CpuRegister.Rsi]; var stateAddress = ctx[CpuRegister.Rsi];
if (stateAddress == 0) if (stateAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> stateBytes = stackalloc byte[sizeof(uint)]; Span<byte> stateBytes = stackalloc byte[sizeof(uint)];
BinaryPrimitives.WriteUInt32LittleEndian(stateBytes, 1); BinaryPrimitives.WriteUInt32LittleEndian(stateBytes, 1);
return ctx.Memory.TryWrite(stateAddress, stateBytes) return ctx.Memory.TryWrite(stateAddress, stateBytes)
? SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK) ? ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK)
: SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -97,7 +97,7 @@ public static class NpManagerExports
var titleSecretAddress = ctx[CpuRegister.Rsi]; var titleSecretAddress = ctx[CpuRegister.Rsi];
if (titleIdAddress == 0 || titleSecretAddress == 0) if (titleIdAddress == 0 || titleSecretAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> titleId = stackalloc byte[NpTitleIdSize]; Span<byte> titleId = stackalloc byte[NpTitleIdSize];
@@ -105,17 +105,11 @@ public static class NpManagerExports
if (!ctx.Memory.TryRead(titleIdAddress, titleId) || if (!ctx.Memory.TryRead(titleIdAddress, titleId) ||
!ctx.Memory.TryRead(titleSecretAddress, titleSecret)) !ctx.Memory.TryRead(titleSecretAddress, titleSecret))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceNp($"set_np_title_id title='{ReadTitleId(titleId)}'"); TraceNp($"set_np_title_id title='{ReadTitleId(titleId)}'");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
}
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
} }
private static string ReadTitleId(ReadOnlySpan<byte> bytes) private static string ReadTitleId(ReadOnlySpan<byte> bytes)
@@ -3,7 +3,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Threading;
namespace SharpEmu.Libs.Np; namespace SharpEmu.Libs.Np;
@@ -22,13 +21,13 @@ public static class NpUniversalDataSystemExports
var parameterAddress = ctx[CpuRegister.Rdi]; var parameterAddress = ctx[CpuRegister.Rdi];
if (parameterAddress == 0) if (parameterAddress == 0)
{ {
return SetReturn(ctx, NpUniversalDataSystemErrorInvalidArgument); return ctx.SetReturn(NpUniversalDataSystemErrorInvalidArgument, typeof(long));
} }
Span<byte> parameters = stackalloc byte[16]; Span<byte> parameters = stackalloc byte[16];
return ctx.Memory.TryRead(parameterAddress, parameters) return ctx.Memory.TryRead(parameterAddress, parameters)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -41,14 +40,14 @@ public static class NpUniversalDataSystemExports
var contextAddress = ctx[CpuRegister.Rdi]; var contextAddress = ctx[CpuRegister.Rdi];
if (contextAddress == 0) if (contextAddress == 0)
{ {
return SetReturn(ctx, 0); return ctx.SetReturn(0, typeof(long));
} }
Span<byte> context = stackalloc byte[sizeof(int)]; Span<byte> context = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(context, 1); BinaryPrimitives.WriteInt32LittleEndian(context, 1);
return ctx.Memory.TryWrite(contextAddress, context) return ctx.Memory.TryWrite(contextAddress, context)
? SetReturn(ctx, 0) ? ctx.SetReturn(0, typeof(long))
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -59,13 +58,13 @@ public static class NpUniversalDataSystemExports
public static int NpUniversalDataSystemCreateHandle(CpuContext ctx) public static int NpUniversalDataSystemCreateHandle(CpuContext ctx)
{ {
var handle = Interlocked.Increment(ref _nextHandle); var handle = Interlocked.Increment(ref _nextHandle);
if (TryWriteInt32(ctx, ctx[CpuRegister.Rdi], handle) || if (ctx.TryWriteInt32(ctx[CpuRegister.Rdi], handle, checkNil: true) ||
TryWriteInt32(ctx, ctx[CpuRegister.Rsi], handle)) ctx.TryWriteInt32(ctx[CpuRegister.Rsi], handle, checkNil: true))
{ {
return SetReturn(ctx, 0); return ctx.SetReturn(0, typeof(long));
} }
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT, typeof(long));
} }
[SysAbiExport( [SysAbiExport(
@@ -75,24 +74,6 @@ public static class NpUniversalDataSystemExports
LibraryName = "libSceNpUniversalDataSystem")] LibraryName = "libSceNpUniversalDataSystem")]
public static int NpUniversalDataSystemRegisterContext(CpuContext ctx) public static int NpUniversalDataSystemRegisterContext(CpuContext ctx)
{ {
return SetReturn(ctx, 0); return ctx.SetReturn(0, typeof(long));
}
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
if (address == 0)
{
return false;
}
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(long)result);
return result;
} }
} }
+3 -11
View File
@@ -1,8 +1,6 @@
// Copyright (C) 2026 SharpEmu Emulator Project // Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using System;
using System.Threading;
using SharpEmu.HLE; using SharpEmu.HLE;
namespace SharpEmu.Libs.Np; namespace SharpEmu.Libs.Np;
@@ -25,12 +23,12 @@ public static class NpWebApi2Exports
if (httpContextId <= 0 || poolSize == 0) if (httpContextId <= 0 || poolSize == 0)
{ {
return SetReturn(ctx, NpWebApi2ErrorInvalidArgument); return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
} }
Interlocked.Exchange(ref _initialized, 1); Interlocked.Exchange(ref _initialized, 1);
TraceNpWebApi2("init", httpContextId, poolSize); TraceNpWebApi2("init", httpContextId, poolSize);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -43,13 +41,7 @@ public static class NpWebApi2Exports
var libraryContextId = unchecked((int)ctx[CpuRegister.Rdi]); var libraryContextId = unchecked((int)ctx[CpuRegister.Rdi]);
Interlocked.Exchange(ref _initialized, 0); Interlocked.Exchange(ref _initialized, 0);
TraceNpWebApi2("term", libraryContextId, 0); TraceNpWebApi2("term", libraryContextId, 0);
return SetReturn(ctx, 0); return ctx.SetReturn(0);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
private static void TraceNpWebApi2(string operation, int id, ulong arg0) private static void TraceNpWebApi2(string operation, int id, ulong arg0)
+20 -26
View File
@@ -30,7 +30,7 @@ public static class PadExports
public static int PadInit(CpuContext ctx) public static int PadInit(CpuContext ctx)
{ {
_initialized = true; _initialized = true;
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
[SysAbiExport( [SysAbiExport(
@@ -46,21 +46,21 @@ public static class PadExports
var parameterAddress = ctx[CpuRegister.Rcx]; var parameterAddress = ctx[CpuRegister.Rcx];
if (!_initialized) if (!_initialized)
{ {
return SetReturn(ctx, OrbisPadErrorNotInitialized); return ctx.SetReturn(OrbisPadErrorNotInitialized);
} }
if (userId == -1) if (userId == -1)
{ {
return SetReturn(ctx, OrbisPadErrorDeviceNoHandle); return ctx.SetReturn(OrbisPadErrorDeviceNoHandle);
} }
if (userId != PrimaryUserId || type != StandardPortType || index != 0 || parameterAddress != 0) if (userId != PrimaryUserId || type != StandardPortType || index != 0 || parameterAddress != 0)
{ {
return SetReturn(ctx, OrbisPadErrorDeviceNotConnected); return ctx.SetReturn(OrbisPadErrorDeviceNotConnected);
} }
Console.Error.WriteLine("[LOADER][INFO] Keyboard controls: Arrow keys = D-pad, WASD = left stick, IJKL = right stick, Z/Enter = Cross, X/Esc = Circle, C = Square, V = Triangle, Q = L1, E = R1, R = L2, F = R2, Tab/Backspace = Options"); Console.Error.WriteLine("[LOADER][INFO] Keyboard controls: Arrow keys = D-pad, WASD = left stick, IJKL = right stick, Z/Enter = Cross, X/Esc = Circle, C = Square, V = Triangle, Q = L1, E = R1, R = L2, F = R2, Tab/Backspace = Options");
return SetReturn(ctx, PrimaryPadHandle); return ctx.SetReturn(PrimaryPadHandle);
} }
[SysAbiExport( [SysAbiExport(
@@ -72,8 +72,8 @@ public static class PadExports
{ {
var handle = unchecked((int)ctx[CpuRegister.Rdi]); var handle = unchecked((int)ctx[CpuRegister.Rdi]);
return handle == PrimaryPadHandle return handle == PrimaryPadHandle
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, OrbisPadErrorInvalidHandle); : ctx.SetReturn(OrbisPadErrorInvalidHandle);
} }
[SysAbiExport( [SysAbiExport(
@@ -87,12 +87,12 @@ public static class PadExports
var informationAddress = ctx[CpuRegister.Rsi]; var informationAddress = ctx[CpuRegister.Rsi];
if (handle != PrimaryPadHandle) if (handle != PrimaryPadHandle)
{ {
return SetReturn(ctx, OrbisPadErrorInvalidHandle); return ctx.SetReturn(OrbisPadErrorInvalidHandle);
} }
if (informationAddress == 0) if (informationAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Span<byte> information = stackalloc byte[ControllerInformationSize]; Span<byte> information = stackalloc byte[ControllerInformationSize];
@@ -107,8 +107,8 @@ public static class PadExports
BinaryPrimitives.WriteInt32LittleEndian(information[0x10..], 0); BinaryPrimitives.WriteInt32LittleEndian(information[0x10..], 0);
return ctx.Memory.TryWrite(informationAddress, information) return ctx.Memory.TryWrite(informationAddress, information)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -122,17 +122,17 @@ public static class PadExports
var dataAddress = ctx[CpuRegister.Rsi]; var dataAddress = ctx[CpuRegister.Rsi];
if (handle != PrimaryPadHandle) if (handle != PrimaryPadHandle)
{ {
return SetReturn(ctx, OrbisPadErrorInvalidHandle); return ctx.SetReturn(OrbisPadErrorInvalidHandle);
} }
if (dataAddress == 0) if (dataAddress == 0)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
return WriteNeutralPadData(ctx, dataAddress) return WriteNeutralPadData(ctx, dataAddress)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -147,17 +147,17 @@ public static class PadExports
var count = unchecked((int)ctx[CpuRegister.Rdx]); var count = unchecked((int)ctx[CpuRegister.Rdx]);
if (handle != PrimaryPadHandle) if (handle != PrimaryPadHandle)
{ {
return SetReturn(ctx, OrbisPadErrorInvalidHandle); return ctx.SetReturn(OrbisPadErrorInvalidHandle);
} }
if (dataAddress == 0 || count < 1 || count > 64) if (dataAddress == 0 || count < 1 || count > 64)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
return WriteNeutralPadData(ctx, dataAddress) return WriteNeutralPadData(ctx, dataAddress)
? SetReturn(ctx, 1) ? ctx.SetReturn(1)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -167,7 +167,7 @@ public static class PadExports
LibraryName = "libScePad")] LibraryName = "libScePad")]
public static int PadSetVibrationMode(CpuContext ctx) public static int PadSetVibrationMode(CpuContext ctx)
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_OK);
} }
private static bool WriteNeutralPadData(CpuContext ctx, ulong dataAddress) private static bool WriteNeutralPadData(CpuContext ctx, ulong dataAddress)
@@ -201,12 +201,6 @@ public static class PadExports
return ctx.Memory.TryWrite(dataAddress, data); return ctx.Memory.TryWrite(dataAddress, data);
} }
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
[DllImport("user32.dll")] [DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey); private static extern short GetAsyncKeyState(int vKey);
+5 -39
View File
@@ -249,7 +249,7 @@ public static class PlayGoExports
for (uint i = 0; i < entriesToWrite; i++) for (uint i = 0; i < entriesToWrite; i++)
{ {
var chunkId = chunkIds.Length == 0 ? (ushort)0 : chunkIds[i]; var chunkId = chunkIds.Length == 0 ? (ushort)0 : chunkIds[i];
if (!TryWriteUInt16(ctx, outChunkIdList + (i * sizeof(ushort)), chunkId)) if (!ctx.TryWriteUInt16(outChunkIdList + (i * sizeof(ushort)), chunkId))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -292,7 +292,7 @@ public static class PlayGoExports
return ValidateChunkIds(ctx, chunkIds, numberOfEntries) is { } chunkError && chunkError != 0 return ValidateChunkIds(ctx, chunkIds, numberOfEntries) is { } chunkError && chunkError != 0
? chunkError ? chunkError
: TryWriteInt64(ctx, outEta, 0) : ctx.TryWriteInt64(outEta, 0)
? (int)OrbisGen2Result.ORBIS_GEN2_OK ? (int)OrbisGen2Result.ORBIS_GEN2_OK
: (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; : (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -324,7 +324,7 @@ public static class PlayGoExports
speed = _installSpeed; speed = _installSpeed;
} }
return TryWriteInt32(ctx, outSpeed, speed) return ctx.TryWriteInt32(outSpeed, speed)
? (int)OrbisGen2Result.ORBIS_GEN2_OK ? (int)OrbisGen2Result.ORBIS_GEN2_OK
: (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; : (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -399,7 +399,7 @@ public static class PlayGoExports
var loci = new byte[numberOfEntries]; var loci = new byte[numberOfEntries];
for (uint i = 0; i < numberOfEntries; i++) for (uint i = 0; i < numberOfEntries; i++)
{ {
if (!TryReadUInt16(ctx, chunkIds + (i * sizeof(ushort)), out var chunkId)) if (!ctx.TryReadUInt16(chunkIds + (i * sizeof(ushort)), out var chunkId))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -648,7 +648,7 @@ public static class PlayGoExports
{ {
for (uint i = 0; i < numberOfEntries; i++) for (uint i = 0; i < numberOfEntries; i++)
{ {
if (!TryReadUInt16(ctx, chunkIds + (i * sizeof(ushort)), out var chunkId)) if (!ctx.TryReadUInt16(chunkIds + (i * sizeof(ushort)), out var chunkId))
{ {
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
} }
@@ -728,40 +728,6 @@ public static class PlayGoExports
} }
} }
private static bool TryReadUInt16(CpuContext ctx, ulong address, out ushort value)
{
Span<byte> buffer = stackalloc byte[sizeof(ushort)];
if (!ctx.Memory.TryRead(address, buffer))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadUInt16LittleEndian(buffer);
return true;
}
private static bool TryWriteUInt16(CpuContext ctx, ulong address, ushort value)
{
Span<byte> buffer = stackalloc byte[sizeof(ushort)];
BinaryPrimitives.WriteUInt16LittleEndian(buffer, value);
return ctx.Memory.TryWrite(address, buffer);
}
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> buffer = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(buffer, value);
return ctx.Memory.TryWrite(address, buffer);
}
private static bool TryWriteInt64(CpuContext ctx, ulong address, long value)
{
Span<byte> buffer = stackalloc byte[sizeof(long)];
BinaryPrimitives.WriteInt64LittleEndian(buffer, value);
return ctx.Memory.TryWrite(address, buffer);
}
private static void TracePlayGo(string message) private static void TracePlayGo(string message)
{ {
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_PLAYGO"), "1", StringComparison.Ordinal)) if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_PLAYGO"), "1", StringComparison.Ordinal))
@@ -3,7 +3,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Threading;
namespace SharpEmu.Libs.SaveData; namespace SharpEmu.Libs.SaveData;
@@ -35,10 +34,10 @@ public static class SaveDataDialogExports
{ {
if (Interlocked.CompareExchange(ref _status, StatusInitialized, StatusNone) != StatusNone) if (Interlocked.CompareExchange(ref _status, StatusInitialized, StatusNone) != StatusNone)
{ {
return SetReturn(ctx, ErrorAlreadyInitialized); return ctx.SetReturn(ErrorAlreadyInitialized);
} }
return SetReturn(ctx, ErrorOk); return ctx.SetReturn(ErrorOk);
} }
[SysAbiExport( [SysAbiExport(
@@ -51,12 +50,12 @@ public static class SaveDataDialogExports
var paramAddress = ctx[CpuRegister.Rdi]; var paramAddress = ctx[CpuRegister.Rdi];
if (paramAddress == 0) if (paramAddress == 0)
{ {
return SetReturn(ctx, ErrorArgNull); return ctx.SetReturn(ErrorArgNull);
} }
if (_status is not (StatusInitialized or StatusFinished)) if (_status is not (StatusInitialized or StatusFinished))
{ {
return SetReturn(ctx, ErrorNotInitialized); return ctx.SetReturn(ErrorNotInitialized);
} }
_lastMode = TryReadInt32(ctx, paramAddress, out var mode) ? mode : 0; _lastMode = TryReadInt32(ctx, paramAddress, out var mode) ? mode : 0;
@@ -66,7 +65,7 @@ public static class SaveDataDialogExports
// guest polling sees a finished dialog instead of spinning forever. // guest polling sees a finished dialog instead of spinning forever.
Interlocked.Exchange(ref _status, StatusFinished); Interlocked.Exchange(ref _status, StatusFinished);
TraceSaveDataDialog($"open mode={_lastMode} userData=0x{_lastUserData:X16} -> finished"); TraceSaveDataDialog($"open mode={_lastMode} userData=0x{_lastUserData:X16} -> finished");
return SetReturn(ctx, ErrorOk); return ctx.SetReturn(ErrorOk);
} }
[SysAbiExport( [SysAbiExport(
@@ -74,21 +73,21 @@ public static class SaveDataDialogExports
ExportName = "sceSaveDataDialogGetStatus", ExportName = "sceSaveDataDialogGetStatus",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceSaveDataDialog")] LibraryName = "libSceSaveDataDialog")]
public static int SaveDataDialogGetStatus(CpuContext ctx) => SetReturn(ctx, Volatile.Read(ref _status)); public static int SaveDataDialogGetStatus(CpuContext ctx) => ctx.SetReturn(Volatile.Read(ref _status));
[SysAbiExport( [SysAbiExport(
Nid = "KK3Bdg1RWK0", Nid = "KK3Bdg1RWK0",
ExportName = "sceSaveDataDialogUpdateStatus", ExportName = "sceSaveDataDialogUpdateStatus",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceSaveDataDialog")] LibraryName = "libSceSaveDataDialog")]
public static int SaveDataDialogUpdateStatus(CpuContext ctx) => SetReturn(ctx, Volatile.Read(ref _status)); public static int SaveDataDialogUpdateStatus(CpuContext ctx) => ctx.SetReturn(Volatile.Read(ref _status));
[SysAbiExport( [SysAbiExport(
Nid = "en7gNVnh878", Nid = "en7gNVnh878",
ExportName = "sceSaveDataDialogIsReadyToDisplay", ExportName = "sceSaveDataDialogIsReadyToDisplay",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceSaveDataDialog")] LibraryName = "libSceSaveDataDialog")]
public static int SaveDataDialogIsReadyToDisplay(CpuContext ctx) => SetReturn(ctx, 1); public static int SaveDataDialogIsReadyToDisplay(CpuContext ctx) => ctx.SetReturn(1);
[SysAbiExport( [SysAbiExport(
Nid = "yEiJ-qqr6Cg", Nid = "yEiJ-qqr6Cg",
@@ -100,12 +99,12 @@ public static class SaveDataDialogExports
var resultAddress = ctx[CpuRegister.Rdi]; var resultAddress = ctx[CpuRegister.Rdi];
if (resultAddress == 0) if (resultAddress == 0)
{ {
return SetReturn(ctx, ErrorArgNull); return ctx.SetReturn(ErrorArgNull);
} }
if (Volatile.Read(ref _status) != StatusFinished) if (Volatile.Read(ref _status) != StatusFinished)
{ {
return SetReturn(ctx, ErrorNotFinished); return ctx.SetReturn(ErrorNotFinished);
} }
Span<byte> result = stackalloc byte[ResultSize]; Span<byte> result = stackalloc byte[ResultSize];
@@ -117,10 +116,10 @@ public static class SaveDataDialogExports
if (!ctx.Memory.TryWrite(resultAddress, result)) if (!ctx.Memory.TryWrite(resultAddress, result))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
return SetReturn(ctx, ErrorOk); return ctx.SetReturn(ErrorOk);
} }
[SysAbiExport( [SysAbiExport(
@@ -132,10 +131,10 @@ public static class SaveDataDialogExports
{ {
if (Interlocked.CompareExchange(ref _status, StatusFinished, StatusRunning) != StatusRunning) if (Interlocked.CompareExchange(ref _status, StatusFinished, StatusRunning) != StatusRunning)
{ {
return SetReturn(ctx, ErrorNotRunning); return ctx.SetReturn(ErrorNotRunning);
} }
return SetReturn(ctx, ErrorOk); return ctx.SetReturn(ErrorOk);
} }
[SysAbiExport( [SysAbiExport(
@@ -147,12 +146,12 @@ public static class SaveDataDialogExports
{ {
if (Interlocked.Exchange(ref _status, StatusNone) == StatusNone) if (Interlocked.Exchange(ref _status, StatusNone) == StatusNone)
{ {
return SetReturn(ctx, ErrorNotInitialized); return ctx.SetReturn(ErrorNotInitialized);
} }
_lastMode = 0; _lastMode = 0;
_lastUserData = 0; _lastUserData = 0;
return SetReturn(ctx, ErrorOk); return ctx.SetReturn(ErrorOk);
} }
[SysAbiExport( [SysAbiExport(
@@ -160,14 +159,14 @@ public static class SaveDataDialogExports
ExportName = "sceSaveDataDialogProgressBarInc", ExportName = "sceSaveDataDialogProgressBarInc",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceSaveDataDialog")] LibraryName = "libSceSaveDataDialog")]
public static int SaveDataDialogProgressBarInc(CpuContext ctx) => SetReturn(ctx, ErrorOk); public static int SaveDataDialogProgressBarInc(CpuContext ctx) => ctx.SetReturn(ErrorOk);
[SysAbiExport( [SysAbiExport(
Nid = "hay1CfTmLyA", Nid = "hay1CfTmLyA",
ExportName = "sceSaveDataDialogProgressBarSetValue", ExportName = "sceSaveDataDialogProgressBarSetValue",
Target = Generation.Gen4 | Generation.Gen5, Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceSaveDataDialog")] LibraryName = "libSceSaveDataDialog")]
public static int SaveDataDialogProgressBarSetValue(CpuContext ctx) => SetReturn(ctx, ErrorOk); public static int SaveDataDialogProgressBarSetValue(CpuContext ctx) => ctx.SetReturn(ErrorOk);
private static bool TryReadInt32(CpuContext ctx, ulong address, out int value) private static bool TryReadInt32(CpuContext ctx, ulong address, out int value)
{ {
@@ -182,12 +181,6 @@ public static class SaveDataDialogExports
return true; return true;
} }
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
private static void TraceSaveDataDialog(string message) private static void TraceSaveDataDialog(string message)
{ {
if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_SAVEDATA"), "1", StringComparison.Ordinal)) if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_SAVEDATA"), "1", StringComparison.Ordinal))
+29 -48
View File
@@ -50,15 +50,15 @@ public static class SaveDataExports
try try
{ {
Directory.CreateDirectory(ResolveSaveDataRoot()); Directory.CreateDirectory(ResolveSaveDataRoot());
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
catch (IOException) catch (IOException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
} }
@@ -73,18 +73,18 @@ public static class SaveDataExports
var resultAddress = ctx[CpuRegister.Rsi]; var resultAddress = ctx[CpuRegister.Rsi];
if (condAddress == 0 || resultAddress == 0) if (condAddress == 0 || resultAddress == 0)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
if (!TryReadSearchCond(ctx, condAddress, out var cond) || if (!TryReadSearchCond(ctx, condAddress, out var cond) ||
!TryReadSearchResult(ctx, resultAddress, out var result)) !TryReadSearchResult(ctx, resultAddress, out var result))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (cond.UserId < 0 || cond.SortKey > SortKeyFreeBlocks || cond.SortOrder > SortOrderDescent) if (cond.UserId < 0 || cond.SortKey > SortKeyFreeBlocks || cond.SortOrder > SortOrderDescent)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
try try
@@ -96,7 +96,7 @@ public static class SaveDataExports
} }
else if (!TryReadFixedAscii(ctx, cond.TitleIdAddress, SaveDataTitleIdSize, out titleId)) else if (!TryReadFixedAscii(ctx, cond.TitleIdAddress, SaveDataTitleIdSize, out titleId))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
var root = ResolveTitleSaveRoot(cond.UserId, titleId); var root = ResolveTitleSaveRoot(cond.UserId, titleId);
@@ -111,18 +111,18 @@ public static class SaveDataExports
if (!ctx.TryWriteUInt32(resultAddress + ResultHitNumOffset, checked((uint)entries.Count)) || if (!ctx.TryWriteUInt32(resultAddress + ResultHitNumOffset, checked((uint)entries.Count)) ||
!ctx.TryWriteUInt32(resultAddress + ResultSetNumOffset, checked((uint)setNum))) !ctx.TryWriteUInt32(resultAddress + ResultSetNumOffset, checked((uint)setNum)))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (setNum == 0) if (setNum == 0)
{ {
TraceSaveData($"dir_name_search user={cond.UserId} title={titleId} hits={entries.Count} set=0 root='{root}'"); TraceSaveData($"dir_name_search user={cond.UserId} title={titleId} hits={entries.Count} set=0 root='{root}'");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
if (result.DirNamesAddress == 0) if (result.DirNamesAddress == 0)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
for (var i = 0; i < setNum; i++) for (var i = 0; i < setNum; i++)
@@ -138,20 +138,20 @@ public static class SaveDataExports
(result.InfosAddress != 0 && (result.InfosAddress != 0 &&
!TryWriteSearchInfo(ctx, result.InfosAddress + ((ulong)i * SaveDataSearchInfoSize), entry))) !TryWriteSearchInfo(ctx, result.InfosAddress + ((ulong)i * SaveDataSearchInfoSize), entry)))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
} }
TraceSaveData($"dir_name_search user={cond.UserId} title={titleId} hits={entries.Count} set={setNum} root='{root}'"); TraceSaveData($"dir_name_search user={cond.UserId} title={titleId} hits={entries.Count} set={setNum} root='{root}'");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
catch (IOException) catch (IOException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
} }
@@ -166,10 +166,10 @@ public static class SaveDataExports
var resultAddress = ctx[CpuRegister.Rsi]; var resultAddress = ctx[CpuRegister.Rsi];
if (mountAddress == 0 || resultAddress == 0) if (mountAddress == 0 || resultAddress == 0)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
if (!TryReadInt32(ctx, mountAddress, out var userId) || if (!ctx.TryReadInt32(mountAddress, out var userId) ||
!ctx.TryReadUInt64(mountAddress + 0x08, out var dirNameAddress) || !ctx.TryReadUInt64(mountAddress + 0x08, out var dirNameAddress) ||
!ctx.TryReadUInt64(mountAddress + 0x10, out var blocks) || !ctx.TryReadUInt64(mountAddress + 0x10, out var blocks) ||
!ctx.TryReadUInt64(mountAddress + 0x18, out var systemBlocks) || !ctx.TryReadUInt64(mountAddress + 0x18, out var systemBlocks) ||
@@ -179,12 +179,12 @@ public static class SaveDataExports
dirNameAddress == 0 || dirNameAddress == 0 ||
!TryReadFixedAscii(ctx, dirNameAddress, SaveDataDirNameSize, out var dirName)) !TryReadFixedAscii(ctx, dirNameAddress, SaveDataDirNameSize, out var dirName))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
if (userId < 0 || string.IsNullOrWhiteSpace(dirName)) if (userId < 0 || string.IsNullOrWhiteSpace(dirName))
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
try try
@@ -199,12 +199,12 @@ public static class SaveDataExports
if (!existed && !create && !createIfMissing) if (!existed && !create && !createIfMissing)
{ {
return SetReturn(ctx, OrbisSaveDataErrorNotFound); return ctx.SetReturn(OrbisSaveDataErrorNotFound);
} }
if (existed && create) if (existed && create)
{ {
return SetReturn(ctx, OrbisSaveDataErrorExists); return ctx.SetReturn(OrbisSaveDataErrorExists);
} }
if (!existed) if (!existed)
@@ -221,26 +221,26 @@ public static class SaveDataExports
BinaryPrimitives.WriteUInt32LittleEndian(result[0x1C..], createIfMissing && !existed ? 1u : 0u); BinaryPrimitives.WriteUInt32LittleEndian(result[0x1C..], createIfMissing && !existed ? 1u : 0u);
if (!ctx.Memory.TryWrite(resultAddress, result)) if (!ctx.Memory.TryWrite(resultAddress, result))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceSaveData( TraceSaveData(
$"mount3 user={userId} title={titleId} dir={dirName} blocks={blocks} " + $"mount3 user={userId} title={titleId} dir={dirName} blocks={blocks} " +
$"system_blocks={systemBlocks} mount_mode=0x{mountMode:X} resource={resource} mode={mode} " + $"system_blocks={systemBlocks} mount_mode=0x{mountMode:X} resource={resource} mode={mode} " +
$"mount_point={mountPoint} created={!existed} root='{savePath}'"); $"mount_point={mountPoint} created={!existed} root='{savePath}'");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
catch (IOException) catch (IOException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
catch (UnauthorizedAccessException) catch (UnauthorizedAccessException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorInternal); return ctx.SetReturn(OrbisSaveDataErrorInternal);
} }
catch (ArgumentException) catch (ArgumentException)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
} }
@@ -258,26 +258,26 @@ public static class SaveDataExports
if (resourceAddress == 0) if (resourceAddress == 0)
{ {
return SetReturn(ctx, OrbisSaveDataErrorParameter); return ctx.SetReturn(OrbisSaveDataErrorParameter);
} }
var id = (uint)Interlocked.Increment(ref _nextTransactionResource); var id = (uint)Interlocked.Increment(ref _nextTransactionResource);
if (!ctx.TryWriteUInt32(resourceAddress, id)) if (!ctx.TryWriteUInt32(resourceAddress, id))
{ {
return SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
TraceSaveData( TraceSaveData(
$"create_transaction_resource user={userId} reserved=0x{reserved:X} resource_addr=0x{resourceAddress:X} id={id}"); $"create_transaction_resource user={userId} reserved=0x{reserved:X} resource_addr=0x{resourceAddress:X} id={id}");
return SetReturn(ctx, 0); return ctx.SetReturn(0);
} }
private static bool TryReadSearchCond(CpuContext ctx, ulong address, out SearchCond cond) private static bool TryReadSearchCond(CpuContext ctx, ulong address, out SearchCond cond)
{ {
cond = default; cond = default;
if (!TryReadInt32(ctx, address, out var userId) || if (!ctx.TryReadInt32(address, out var userId) ||
!ctx.TryReadUInt64(address + 0x08, out var titleIdAddress) || !ctx.TryReadUInt64(address + 0x08, out var titleIdAddress) ||
!ctx.TryReadUInt64(address + 0x10, out var dirNameAddress) || !ctx.TryReadUInt64(address + 0x10, out var dirNameAddress) ||
!ctx.TryReadUInt32(address + 0x18, out var sortKey) || !ctx.TryReadUInt32(address + 0x18, out var sortKey) ||
@@ -505,25 +505,6 @@ public static class SaveDataExports
} }
} }
private static bool TryReadInt32(CpuContext ctx, ulong address, out int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
if (!ctx.Memory.TryRead(address, bytes))
{
value = 0;
return false;
}
value = BinaryPrimitives.ReadInt32LittleEndian(bytes);
return true;
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
private static void TraceSaveData(string message) private static void TraceSaveData(string message)
{ {
if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_SAVEDATA"), "1", StringComparison.Ordinal)) if (string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_SAVEDATA"), "1", StringComparison.Ordinal))
+5 -12
View File
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
using System.Text; using System.Text;
using System.Threading;
using SharpEmu.HLE; using SharpEmu.HLE;
namespace SharpEmu.Libs.Share; namespace SharpEmu.Libs.Share;
@@ -26,13 +25,13 @@ public static class ShareExports
var affinityMask = ctx[CpuRegister.Rdx]; var affinityMask = ctx[CpuRegister.Rdx];
if (memorySize == 0) if (memorySize == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
Interlocked.Exchange(ref _initialized, 1); Interlocked.Exchange(ref _initialized, 1);
TraceShare($"initialize memory=0x{memorySize:X} priority={priority} affinity=0x{affinityMask:X}"); TraceShare($"initialize memory=0x{memorySize:X} priority={priority} affinity=0x{affinityMask:X}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
} }
[SysAbiExport( [SysAbiExport(
@@ -45,12 +44,12 @@ public static class ShareExports
var contentParamAddress = ctx[CpuRegister.Rdi]; var contentParamAddress = ctx[CpuRegister.Rdi];
if (contentParamAddress == 0) if (contentParamAddress == 0)
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
} }
if (!TryReadNullTerminatedUtf8(ctx, contentParamAddress, MaxContentParamBytes, out var contentParam)) if (!TryReadNullTerminatedUtf8(ctx, contentParamAddress, MaxContentParamBytes, out var contentParam))
{ {
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
_contentParam = contentParam; _contentParam = contentParam;
@@ -60,13 +59,7 @@ public static class ShareExports
} }
TraceShare($"set_content_param len={contentParam.Length} preview='{FormatTraceString(contentParam)}'"); TraceShare($"set_content_param len={contentParam.Length} preview='{FormatTraceString(contentParam)}'");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK); return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
}
private static int SetReturn(CpuContext ctx, OrbisGen2Result result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(int)result);
return (int)result;
} }
private static bool TryReadNullTerminatedUtf8(CpuContext ctx, ulong address, int maxLength, out string value) private static bool TryReadNullTerminatedUtf8(CpuContext ctx, ulong address, int maxLength, out string value)
@@ -24,7 +24,7 @@ public static class SystemServiceExports
var valueAddress = ctx[CpuRegister.Rsi]; var valueAddress = ctx[CpuRegister.Rsi];
if (valueAddress == 0) if (valueAddress == 0)
{ {
return SetReturn(ctx, OrbisSystemServiceErrorParameter); return ctx.SetReturn(OrbisSystemServiceErrorParameter);
} }
var value = parameterId switch var value = parameterId switch
@@ -37,8 +37,8 @@ public static class SystemServiceExports
Span<byte> valueBytes = stackalloc byte[sizeof(int)]; Span<byte> valueBytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(valueBytes, value); BinaryPrimitives.WriteInt32LittleEndian(valueBytes, value);
return ctx.Memory.TryWrite(valueAddress, valueBytes) return ctx.Memory.TryWrite(valueAddress, valueBytes)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -51,7 +51,7 @@ public static class SystemServiceExports
var statusAddress = ctx[CpuRegister.Rdi]; var statusAddress = ctx[CpuRegister.Rdi];
if (statusAddress == 0) if (statusAddress == 0)
{ {
return SetReturn(ctx, OrbisSystemServiceErrorParameter); return ctx.SetReturn(OrbisSystemServiceErrorParameter);
} }
Span<byte> status = stackalloc byte[SystemServiceStatusSize]; Span<byte> status = stackalloc byte[SystemServiceStatusSize];
@@ -60,8 +60,8 @@ public static class SystemServiceExports
status[0x06] = 1; status[0x06] = 1;
return ctx.Memory.TryWrite(statusAddress, status) return ctx.Memory.TryWrite(statusAddress, status)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -74,7 +74,7 @@ public static class SystemServiceExports
var infoAddress = ctx[CpuRegister.Rdi]; var infoAddress = ctx[CpuRegister.Rdi];
if (infoAddress == 0) if (infoAddress == 0)
{ {
return SetReturn(ctx, OrbisSystemServiceErrorParameter); return ctx.SetReturn(OrbisSystemServiceErrorParameter);
} }
Span<byte> info = stackalloc byte[DisplaySafeAreaInfoSize]; Span<byte> info = stackalloc byte[DisplaySafeAreaInfoSize];
@@ -82,8 +82,8 @@ public static class SystemServiceExports
BinaryPrimitives.WriteSingleLittleEndian(info, 1.0f); BinaryPrimitives.WriteSingleLittleEndian(info, 1.0f);
return ctx.Memory.TryWrite(infoAddress, info) return ctx.Memory.TryWrite(infoAddress, info)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -94,12 +94,6 @@ public static class SystemServiceExports
public static int SystemServiceHideSplashScreen(CpuContext ctx) public static int SystemServiceHideSplashScreen(CpuContext ctx)
{ {
VulkanVideoPresenter.HideSplashScreen(); VulkanVideoPresenter.HideSplashScreen();
return SetReturn(ctx, 0); return ctx.SetReturn(0);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
} }
@@ -4,7 +4,6 @@
using SharpEmu.HLE; using SharpEmu.HLE;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Text; using System.Text;
using System.Threading;
namespace SharpEmu.Libs.UserService; namespace SharpEmu.Libs.UserService;
@@ -40,12 +39,12 @@ public static class UserServiceExports
var userIdAddress = ctx[CpuRegister.Rdi]; var userIdAddress = ctx[CpuRegister.Rdi];
if (userIdAddress == 0) if (userIdAddress == 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidArgument); return ctx.SetReturn(OrbisUserServiceErrorInvalidArgument);
} }
return TryWriteInt32(ctx, userIdAddress, PrimaryUserId) return ctx.TryWriteInt32(userIdAddress, PrimaryUserId)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -58,7 +57,7 @@ public static class UserServiceExports
var userIdListAddress = ctx[CpuRegister.Rdi]; var userIdListAddress = ctx[CpuRegister.Rdi];
if (userIdListAddress == 0) if (userIdListAddress == 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidArgument); return ctx.SetReturn(OrbisUserServiceErrorInvalidArgument);
} }
Span<byte> userIds = stackalloc byte[sizeof(int) * 4]; Span<byte> userIds = stackalloc byte[sizeof(int) * 4];
@@ -67,8 +66,8 @@ public static class UserServiceExports
BinaryPrimitives.WriteInt32LittleEndian(userIds[0x08..], InvalidUserId); BinaryPrimitives.WriteInt32LittleEndian(userIds[0x08..], InvalidUserId);
BinaryPrimitives.WriteInt32LittleEndian(userIds[0x0C..], InvalidUserId); BinaryPrimitives.WriteInt32LittleEndian(userIds[0x0C..], InvalidUserId);
return ctx.Memory.TryWrite(userIdListAddress, userIds) return ctx.Memory.TryWrite(userIdListAddress, userIds)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -81,20 +80,20 @@ public static class UserServiceExports
var eventAddress = ctx[CpuRegister.Rdi]; var eventAddress = ctx[CpuRegister.Rdi];
if (eventAddress == 0) if (eventAddress == 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidArgument); return ctx.SetReturn(OrbisUserServiceErrorInvalidArgument);
} }
if (Interlocked.Exchange(ref _loginEventDelivered, 1) != 0) if (Interlocked.Exchange(ref _loginEventDelivered, 1) != 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorNoEvent); return ctx.SetReturn(OrbisUserServiceErrorNoEvent);
} }
Span<byte> payload = stackalloc byte[sizeof(int) * 2]; Span<byte> payload = stackalloc byte[sizeof(int) * 2];
BinaryPrimitives.WriteInt32LittleEndian(payload[0..], 0); BinaryPrimitives.WriteInt32LittleEndian(payload[0..], 0);
BinaryPrimitives.WriteInt32LittleEndian(payload[sizeof(int)..], PrimaryUserId); BinaryPrimitives.WriteInt32LittleEndian(payload[sizeof(int)..], PrimaryUserId);
return ctx.Memory.TryWrite(eventAddress, payload) return ctx.Memory.TryWrite(eventAddress, payload)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -109,25 +108,25 @@ public static class UserServiceExports
var capacity = ctx[CpuRegister.Rdx]; var capacity = ctx[CpuRegister.Rdx];
if (userId != PrimaryUserId) if (userId != PrimaryUserId)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidParameter); return ctx.SetReturn(OrbisUserServiceErrorInvalidParameter);
} }
if (nameAddress == 0) if (nameAddress == 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidArgument); return ctx.SetReturn(OrbisUserServiceErrorInvalidArgument);
} }
var nameBytes = Encoding.UTF8.GetBytes(PrimaryUserName); var nameBytes = Encoding.UTF8.GetBytes(PrimaryUserName);
if (capacity <= (ulong)nameBytes.Length) if (capacity <= (ulong)nameBytes.Length)
{ {
return SetReturn(ctx, OrbisUserServiceErrorBufferTooShort); return ctx.SetReturn(OrbisUserServiceErrorBufferTooShort);
} }
Span<byte> output = stackalloc byte[nameBytes.Length + 1]; Span<byte> output = stackalloc byte[nameBytes.Length + 1];
nameBytes.CopyTo(output); nameBytes.CopyTo(output);
return ctx.Memory.TryWrite(nameAddress, output) return ctx.Memory.TryWrite(nameAddress, output)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
} }
[SysAbiExport( [SysAbiExport(
@@ -141,29 +140,16 @@ public static class UserServiceExports
var valueAddress = ctx[CpuRegister.Rsi]; var valueAddress = ctx[CpuRegister.Rsi];
if (parameterId != 1000) if (parameterId != 1000)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidParameter); return ctx.SetReturn(OrbisUserServiceErrorInvalidParameter);
} }
if (valueAddress == 0) if (valueAddress == 0)
{ {
return SetReturn(ctx, OrbisUserServiceErrorInvalidArgument); return ctx.SetReturn(OrbisUserServiceErrorInvalidArgument);
} }
return TryWriteInt32(ctx, valueAddress, 0) return ctx.TryWriteInt32(valueAddress, 0)
? SetReturn(ctx, 0) ? ctx.SetReturn(0)
: SetReturn(ctx, (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); : ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
private static bool TryWriteInt32(CpuContext ctx, ulong address, int value)
{
Span<byte> bytes = stackalloc byte[sizeof(int)];
BinaryPrimitives.WriteInt32LittleEndian(bytes, value);
return ctx.Memory.TryWrite(address, bytes);
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
} }
} }