[Font] Implement sceFontTextSourceInit
Fills the 0x60-byte text source with the text range, the cursor, the parser callback and its object, and the text size, and leaves the memory after it untouched.
This commit is contained in:
parent
67f11e78ea
commit
20e8a18009
|
|
@ -21,6 +21,35 @@ public static class FontExports
|
|||
private static readonly ConcurrentDictionary<ulong, float> FontHeights = new();
|
||||
private static readonly Lazy<byte[]?> BitmapFont = new(LoadBitmapFont);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "oaJ1BpN2FQk",
|
||||
ExportName = "sceFontTextSourceInit",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int TextSourceInit(CpuContext ctx)
|
||||
{
|
||||
var sourceAddress = ctx[CpuRegister.Rdi];
|
||||
var textAddress = ctx[CpuRegister.Rsi];
|
||||
var textSize = (uint)ctx[CpuRegister.Rdx];
|
||||
if (sourceAddress == 0 || textAddress > ulong.MaxValue - textSize)
|
||||
{
|
||||
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
Span<byte> source = stackalloc byte[0x60];
|
||||
source.Clear();
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x08..], textAddress);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x10..], textAddress == 0 ? 0 : textAddress + textSize);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x18..], textAddress);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x20..], ctx[CpuRegister.Rcx]);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x28..], ctx[CpuRegister.R8]);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x38..], 0x10);
|
||||
BinaryPrimitives.WriteUInt64LittleEndian(source[0x40..], textSize);
|
||||
return ctx.Memory.TryWrite(sourceAddress, source)
|
||||
? SetSuccess(ctx)
|
||||
: SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "whrS4oksXc4",
|
||||
ExportName = "sceFontMemoryInit",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,36 @@ public sealed class FontExportsTests
|
|||
_ctx = new CpuContext(_memory, Generation.Gen5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TextSourceInit_WritesParserAndTextRangeWithoutOverwritingNextObject()
|
||||
{
|
||||
const ulong text = Base + 0x300;
|
||||
const ulong parser = Base + 0x400;
|
||||
const ulong parserObject = Base + 0x500;
|
||||
var bytes = new byte[0x68];
|
||||
Array.Fill(bytes, (byte)0xcc);
|
||||
Assert.True(_memory.TryWrite(LayoutAddress, bytes));
|
||||
_ctx[CpuRegister.Rdi] = LayoutAddress;
|
||||
_ctx[CpuRegister.Rsi] = text;
|
||||
_ctx[CpuRegister.Rdx] = 9;
|
||||
_ctx[CpuRegister.Rcx] = parser;
|
||||
_ctx[CpuRegister.R8] = parserObject;
|
||||
|
||||
Assert.Equal(0, FontExports.TextSourceInit(_ctx));
|
||||
Assert.True(_memory.TryRead(LayoutAddress, bytes));
|
||||
Assert.Equal(0UL, BinaryPrimitives.ReadUInt64LittleEndian(bytes));
|
||||
Assert.Equal(text, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x08)));
|
||||
Assert.Equal(text + 9, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x10)));
|
||||
Assert.Equal(text, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x18)));
|
||||
Assert.Equal(parser, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x20)));
|
||||
Assert.Equal(parserObject, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x28)));
|
||||
Assert.Equal(0UL, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x30)));
|
||||
Assert.Equal(0x10UL, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x38)));
|
||||
Assert.Equal(9UL, BinaryPrimitives.ReadUInt64LittleEndian(bytes.AsSpan(0x40)));
|
||||
Assert.All(bytes[0x48..0x60], value => Assert.Equal((byte)0, value));
|
||||
Assert.All(bytes[0x60..], value => Assert.Equal((byte)0xcc, value));
|
||||
}
|
||||
|
||||
// SceFontHorizontalLayout is three floats; the sentinel directly after
|
||||
// them must survive the call.
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in New Issue