mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 10:56:20 +08:00
[HLE] Stub ContentExport, Font, and Pad calls Astro Bot needs to boot (#298)
Astro Bot asserts and null-writes when a subsystem init call fails, so each missing import surfaces as a named crash. This stubs the blockers observed during bring-up: content export init, eight font calls, and pad tilt correction. sceFontGetHorizontalLayout writes the same invented geometry as sceFontGetRenderCharGlyphMetrics and the rest report success. Together with save data memory2 these take the title to its splash image and font glyph rendering path.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using SharpEmu.HLE;
|
||||
|
||||
namespace SharpEmu.Libs.ContentExport;
|
||||
|
||||
// No host media library exists to export captures into, so initialization
|
||||
// reports success.
|
||||
public static class ContentExportExports
|
||||
{
|
||||
[SysAbiExport(
|
||||
Nid = "0GnN4QCgIfs",
|
||||
ExportName = "sceContentExportInit2",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceContentExport")]
|
||||
public static int ContentExportInit2(CpuContext ctx) => ctx.SetReturn(0);
|
||||
}
|
||||
@@ -74,6 +74,85 @@ public static class FontExports
|
||||
public static int CreateRendererWithEdition(CpuContext ctx) =>
|
||||
CreateOpaqueHandle(ctx, ctx[CpuRegister.Rcx], 0x100, magic: 0x0F07);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "3OdRkSjOcog",
|
||||
ExportName = "sceFontBindRenderer",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int BindRenderer(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "N1EBMeGhf7E",
|
||||
ExportName = "sceFontSetScalePixel",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetScalePixel(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "TMtqoFQjjbA",
|
||||
ExportName = "sceFontSetEffectSlant",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetEffectSlant(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "v0phZwa4R5o",
|
||||
ExportName = "sceFontSetEffectWeight",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetEffectWeight(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "6vGCkkQJOcI",
|
||||
ExportName = "sceFontSetupRenderScalePixel",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetupRenderScalePixel(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "lz9y9UFO2UU",
|
||||
ExportName = "sceFontSetupRenderEffectSlant",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetupRenderEffectSlant(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "XIGorvLusDQ",
|
||||
ExportName = "sceFontSetupRenderEffectWeight",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int SetupRenderEffectWeight(CpuContext ctx) => SetSuccess(ctx);
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "imxVx8lm+KM",
|
||||
ExportName = "sceFontGetHorizontalLayout",
|
||||
Target = Generation.Gen5,
|
||||
LibraryName = "libSceFont")]
|
||||
public static int GetHorizontalLayout(CpuContext ctx)
|
||||
{
|
||||
var layoutAddress = ctx[CpuRegister.Rsi];
|
||||
if (layoutAddress == 0)
|
||||
{
|
||||
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
// Baseline, line advance, decoration extent: the same invented geometry
|
||||
// as GetRenderCharGlyphMetrics.
|
||||
var values = new[] { 12.0f, 16.0f, 0.0f };
|
||||
for (var index = 0; index < values.Length; index++)
|
||||
{
|
||||
if (!TryWriteUInt32(
|
||||
ctx,
|
||||
layoutAddress + (ulong)(index * sizeof(float)),
|
||||
BitConverter.SingleToUInt32Bits(values[index])))
|
||||
{
|
||||
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
||||
}
|
||||
}
|
||||
|
||||
return SetSuccess(ctx);
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "cKYtVmeSTcw",
|
||||
ExportName = "sceFontOpenFontSet",
|
||||
|
||||
@@ -127,6 +127,19 @@ public static class PadExports
|
||||
: ctx.SetReturn(OrbisPadErrorInvalidHandle);
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "vDLMoJLde8I",
|
||||
ExportName = "scePadSetTiltCorrectionState",
|
||||
Target = Generation.Gen4 | Generation.Gen5,
|
||||
LibraryName = "libScePad")]
|
||||
public static int PadSetTiltCorrectionState(CpuContext ctx)
|
||||
{
|
||||
var handle = unchecked((int)ctx[CpuRegister.Rdi]);
|
||||
return IsPrimaryPadHandle(handle)
|
||||
? ctx.SetReturn(0)
|
||||
: ctx.SetReturn(OrbisPadErrorInvalidHandle);
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "gjP9-KQzoUk",
|
||||
ExportName = "scePadGetControllerInformation",
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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..]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using SharpEmu.HLE;
|
||||
using SharpEmu.Libs.Pad;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpEmu.Libs.Tests.Pad;
|
||||
|
||||
public sealed class PadExportsTests
|
||||
{
|
||||
private const ulong Base = 0x1_0000_0000;
|
||||
private const int InvalidHandle = unchecked((int)0x80920003);
|
||||
|
||||
private readonly FakeCpuMemory _memory = new(Base, 0x1000);
|
||||
private readonly CpuContext _ctx;
|
||||
|
||||
public PadExportsTests()
|
||||
{
|
||||
_ctx = new CpuContext(_memory, Generation.Gen5);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0)]
|
||||
[InlineData(1, 0)]
|
||||
[InlineData(2, InvalidHandle)]
|
||||
[InlineData(-1, InvalidHandle)]
|
||||
public void SetTiltCorrectionState_ValidatesHandle(int handle, int expected)
|
||||
{
|
||||
_ctx[CpuRegister.Rdi] = unchecked((ulong)handle);
|
||||
Assert.Equal(expected, PadExports.PadSetTiltCorrectionState(_ctx));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user