mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-30 14:39:42 +08:00
9be6f85ef0
Add sceFontGetVerticalLayout (NID: 3BrWWFU+4ts) to the Font module, completing the vertical-text counterpart to the existing GetHorizontalLayout. The SceFontVerticalLayout structure is three floats (baseline, lineAdvance, decorationExtent) interpreted for vertical writing such as CJK text rendered top-to-bottom. - Write baseline=8.0f, lineAdvance=16.0f, decorationExtent=0.0f - Validate output pointer and return INVALID_ARGUMENT on null - Return MEMORY_FAULT when guest writes fail Tests: - GetVerticalLayout_WritesExactlyThreeFloats with sentinel guard - GetVerticalLayout_NullBuffer_ReturnsInvalidArgument NID sourced via: python scripts/aerolib_catalog.py lookup sceFontGetVerticalLayout Co-authored-by: tru3 <tru3@tru3.com>
73 lines
2.7 KiB
C#
73 lines
2.7 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using System.Buffers.Binary;
|
|
using SharpEmu.HLE;
|
|
using SharpEmu.Libs.Font;
|
|
using Xunit;
|
|
|
|
namespace SharpEmu.Libs.Tests.Font;
|
|
|
|
public sealed class FontExportsTests
|
|
{
|
|
private const ulong Base = 0x1_0000_0000;
|
|
private const ulong LayoutAddress = Base + 0x100;
|
|
|
|
private readonly FakeCpuMemory _memory = new(Base, 0x1000);
|
|
private readonly CpuContext _ctx;
|
|
|
|
public FontExportsTests()
|
|
{
|
|
_ctx = new CpuContext(_memory, Generation.Gen5);
|
|
}
|
|
|
|
// SceFontHorizontalLayout is three floats; the sentinel directly after
|
|
// them must survive the call.
|
|
[Fact]
|
|
public void GetHorizontalLayout_WritesExactlyThreeFloats()
|
|
{
|
|
const uint Sentinel = 0xDEADBEEF;
|
|
Span<byte> sentinelBytes = stackalloc byte[sizeof(uint)];
|
|
BinaryPrimitives.WriteUInt32LittleEndian(sentinelBytes, Sentinel);
|
|
Assert.True(_ctx.Memory.TryWrite(LayoutAddress + 12, sentinelBytes));
|
|
|
|
_ctx[CpuRegister.Rsi] = LayoutAddress;
|
|
Assert.Equal(0, FontExports.GetHorizontalLayout(_ctx));
|
|
|
|
Span<byte> layout = stackalloc byte[16];
|
|
Assert.True(_ctx.Memory.TryRead(LayoutAddress, layout));
|
|
Assert.Equal(12.0f, BinaryPrimitives.ReadSingleLittleEndian(layout));
|
|
Assert.Equal(16.0f, BinaryPrimitives.ReadSingleLittleEndian(layout[4..]));
|
|
Assert.Equal(0.0f, BinaryPrimitives.ReadSingleLittleEndian(layout[8..]));
|
|
Assert.Equal(Sentinel, BinaryPrimitives.ReadUInt32LittleEndian(layout[12..]));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVerticalLayout_WritesExactlyThreeFloats()
|
|
{
|
|
const uint Sentinel = 0xDEADBEEF;
|
|
Span<byte> sentinelBytes = stackalloc byte[sizeof(uint)];
|
|
BinaryPrimitives.WriteUInt32LittleEndian(sentinelBytes, Sentinel);
|
|
Assert.True(_ctx.Memory.TryWrite(LayoutAddress + 12, sentinelBytes));
|
|
|
|
_ctx[CpuRegister.Rsi] = LayoutAddress;
|
|
Assert.Equal(0, FontExports.GetVerticalLayout(_ctx));
|
|
|
|
Span<byte> layout = stackalloc byte[16];
|
|
Assert.True(_ctx.Memory.TryRead(LayoutAddress, layout));
|
|
Assert.Equal(8.0f, BinaryPrimitives.ReadSingleLittleEndian(layout));
|
|
Assert.Equal(16.0f, BinaryPrimitives.ReadSingleLittleEndian(layout[4..]));
|
|
Assert.Equal(0.0f, BinaryPrimitives.ReadSingleLittleEndian(layout[8..]));
|
|
Assert.Equal(Sentinel, BinaryPrimitives.ReadUInt32LittleEndian(layout[12..]));
|
|
}
|
|
|
|
[Fact]
|
|
public void GetVerticalLayout_NullBuffer_ReturnsInvalidArgument()
|
|
{
|
|
_ctx[CpuRegister.Rsi] = 0;
|
|
Assert.Equal(
|
|
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT,
|
|
FontExports.GetVerticalLayout(_ctx));
|
|
}
|
|
}
|