mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 19:06:15 +08:00
[HLE] Add RandomExports HLE (#413)
This commit is contained in:
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using SharpEmu.HLE;
|
||||||
|
|
||||||
|
namespace SharpEmu.Libs.Random;
|
||||||
|
|
||||||
|
public static class RandomExports
|
||||||
|
{
|
||||||
|
private const int RandomErrorInvalid = unchecked((int)0x817C0016);
|
||||||
|
private const int MaxRandomBytes = 64;
|
||||||
|
|
||||||
|
[SysAbiExport(
|
||||||
|
Nid = "PI7jIZj4pcE",
|
||||||
|
ExportName = "sceRandomGetRandomNumber",
|
||||||
|
Target = Generation.Gen4 | Generation.Gen5,
|
||||||
|
LibraryName = "libSceRandom")]
|
||||||
|
public static int RandomGetRandomNumber(CpuContext ctx)
|
||||||
|
{
|
||||||
|
var destination = ctx[CpuRegister.Rdi];
|
||||||
|
var size = ctx[CpuRegister.Rsi];
|
||||||
|
if ((destination == 0 && size != 0) || size > MaxRandomBytes)
|
||||||
|
{
|
||||||
|
return ctx.SetReturn(RandomErrorInvalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
return ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<byte> bytes = stackalloc byte[(int)size];
|
||||||
|
RandomNumberGenerator.Fill(bytes);
|
||||||
|
return ctx.Memory.TryWrite(destination, bytes)
|
||||||
|
? ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_OK)
|
||||||
|
: ctx.SetReturn(OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
using SharpEmu.HLE;
|
||||||
|
using SharpEmu.Libs.Random;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharpEmu.Libs.Tests.Random;
|
||||||
|
|
||||||
|
public sealed class RandomExportsTests
|
||||||
|
{
|
||||||
|
private const ulong BaseAddress = 0x1000;
|
||||||
|
private const int RandomErrorInvalid = unchecked((int)0x817C0016);
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetRandomNumberWritesRequestedBytes()
|
||||||
|
{
|
||||||
|
var memory = new FakeCpuMemory(BaseAddress, 64);
|
||||||
|
var ctx = CreateContext(memory, BaseAddress, 64);
|
||||||
|
|
||||||
|
Assert.Equal(0, RandomExports.RandomGetRandomNumber(ctx));
|
||||||
|
|
||||||
|
var bytes = new byte[64];
|
||||||
|
Assert.True(memory.TryRead(BaseAddress, bytes));
|
||||||
|
Assert.NotEqual(new byte[64], bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0, 1)]
|
||||||
|
[InlineData(BaseAddress, 65)]
|
||||||
|
public void GetRandomNumberRejectsInvalidArguments(ulong address, ulong size)
|
||||||
|
{
|
||||||
|
var memory = new FakeCpuMemory(BaseAddress, 64);
|
||||||
|
var ctx = CreateContext(memory, address, size);
|
||||||
|
|
||||||
|
Assert.Equal(RandomErrorInvalid, RandomExports.RandomGetRandomNumber(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetRandomNumberAcceptsEmptyRequest()
|
||||||
|
{
|
||||||
|
var memory = new FakeCpuMemory(BaseAddress, 64);
|
||||||
|
var ctx = CreateContext(memory, 0, 0);
|
||||||
|
|
||||||
|
Assert.Equal(0, RandomExports.RandomGetRandomNumber(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetRandomNumberReportsUnmappedDestination()
|
||||||
|
{
|
||||||
|
var memory = new FakeCpuMemory(BaseAddress, 64);
|
||||||
|
var ctx = CreateContext(memory, BaseAddress + 64, 1);
|
||||||
|
|
||||||
|
Assert.Equal(
|
||||||
|
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT,
|
||||||
|
RandomExports.RandomGetRandomNumber(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CpuContext CreateContext(
|
||||||
|
ICpuMemory memory,
|
||||||
|
ulong destination,
|
||||||
|
ulong size)
|
||||||
|
{
|
||||||
|
var ctx = new CpuContext(memory, Generation.Gen5);
|
||||||
|
ctx[CpuRegister.Rdi] = destination;
|
||||||
|
ctx[CpuRegister.Rsi] = size;
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user