mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 15:09:42 +08:00
[Ampr] Implement the FW 4.00 write-address command exports (#510)
This commit is contained in:
@@ -1404,11 +1404,13 @@ public sealed partial class DirectExecutionBackend
|
|||||||
"vWU-odnS+fU" or // sceAmprMeasureCommandSizeReadFile
|
"vWU-odnS+fU" or // sceAmprMeasureCommandSizeReadFile
|
||||||
"sSAUCCU1dv4" or // sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00
|
"sSAUCCU1dv4" or // sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00
|
||||||
"C+IEj+BsAFM" or // sceAmprMeasureCommandSizeWriteAddressOnCompletion
|
"C+IEj+BsAFM" or // sceAmprMeasureCommandSizeWriteAddressOnCompletion
|
||||||
|
"4fgtGfXDrFc" or // sceAmprMeasureCommandSizeWriteAddress_04_00
|
||||||
"tZDDEo2tE5k" or // sceAmprCommandBufferGetSize
|
"tZDDEo2tE5k" or // sceAmprCommandBufferGetSize
|
||||||
"GnxKOHEawhk" or // sceAmprCommandBufferGetCurrentOffset
|
"GnxKOHEawhk" or // sceAmprCommandBufferGetCurrentOffset
|
||||||
"gzndltBEzWc" or // sceAmprCommandBufferGetNumCommands
|
"gzndltBEzWc" or // sceAmprCommandBufferGetNumCommands
|
||||||
"H896Pt-yB4I" or // sceAmprCommandBufferWriteKernelEventQueue_04_00
|
"H896Pt-yB4I" or // sceAmprCommandBufferWriteKernelEventQueue_04_00
|
||||||
"sJXyWHjP-F8" or // sceAmprCommandBufferWriteAddressOnCompletion
|
"sJXyWHjP-F8" or // sceAmprCommandBufferWriteAddressOnCompletion
|
||||||
|
"j0+3uJMxYJY" or // sceAmprCommandBufferWriteAddress_04_00
|
||||||
"mPpPxv5CZt4" or // sceSystemServiceGetHdrToneMapLuminance
|
"mPpPxv5CZt4" or // sceSystemServiceGetHdrToneMapLuminance
|
||||||
"1FZBKy8HeNU" or // sceVideoOutGetVblankStatus
|
"1FZBKy8HeNU" or // sceVideoOutGetVblankStatus
|
||||||
"ASoW5WE-UPo" or // sceKernelAprSubmitCommandBufferAndGetResult
|
"ASoW5WE-UPo" or // sceKernelAprSubmitCommandBufferAndGetResult
|
||||||
@@ -1554,11 +1556,13 @@ public sealed partial class DirectExecutionBackend
|
|||||||
"vWU-odnS+fU" or
|
"vWU-odnS+fU" or
|
||||||
"sSAUCCU1dv4" or
|
"sSAUCCU1dv4" or
|
||||||
"C+IEj+BsAFM" or
|
"C+IEj+BsAFM" or
|
||||||
|
"4fgtGfXDrFc" or
|
||||||
"tZDDEo2tE5k" or
|
"tZDDEo2tE5k" or
|
||||||
"GnxKOHEawhk" or
|
"GnxKOHEawhk" or
|
||||||
"gzndltBEzWc" or
|
"gzndltBEzWc" or
|
||||||
"H896Pt-yB4I" or
|
"H896Pt-yB4I" or
|
||||||
"sJXyWHjP-F8" or
|
"sJXyWHjP-F8" or
|
||||||
|
"j0+3uJMxYJY" or
|
||||||
"mPpPxv5CZt4" or
|
"mPpPxv5CZt4" or
|
||||||
"1FZBKy8HeNU" or
|
"1FZBKy8HeNU" or
|
||||||
"ASoW5WE-UPo" or
|
"ASoW5WE-UPo" or
|
||||||
|
|||||||
@@ -340,6 +340,18 @@ public static class AmprExports
|
|||||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SysAbiExport(
|
||||||
|
Nid = "4fgtGfXDrFc",
|
||||||
|
ExportName = "sceAmprMeasureCommandSizeWriteAddress_04_00",
|
||||||
|
Target = Generation.Gen5,
|
||||||
|
LibraryName = "libSceAmpr")]
|
||||||
|
public static int MeasureCommandSizeWriteAddress0400(CpuContext ctx)
|
||||||
|
{
|
||||||
|
TraceAmpr(ctx, "measure_write_address", 0, WriteAddressRecordSize, 0);
|
||||||
|
ctx[CpuRegister.Rax] = WriteAddressRecordSize;
|
||||||
|
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
|
}
|
||||||
|
|
||||||
[SysAbiExport(
|
[SysAbiExport(
|
||||||
Nid = "tZDDEo2tE5k",
|
Nid = "tZDDEo2tE5k",
|
||||||
ExportName = "sceAmprCommandBufferGetSize",
|
ExportName = "sceAmprCommandBufferGetSize",
|
||||||
@@ -509,6 +521,32 @@ public static class AmprExports
|
|||||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SysAbiExport(
|
||||||
|
Nid = "j0+3uJMxYJY",
|
||||||
|
ExportName = "sceAmprCommandBufferWriteAddress_04_00",
|
||||||
|
Target = Generation.Gen5,
|
||||||
|
LibraryName = "libSceAmpr")]
|
||||||
|
public static int CommandBufferWriteAddress0400(CpuContext ctx)
|
||||||
|
{
|
||||||
|
var commandBuffer = ctx[CpuRegister.Rdi];
|
||||||
|
var address = ctx[CpuRegister.Rsi];
|
||||||
|
var value = ctx[CpuRegister.Rdx];
|
||||||
|
|
||||||
|
if (commandBuffer == 0 || address == 0)
|
||||||
|
{
|
||||||
|
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AppendWriteAddressRecord(ctx, commandBuffer, address, value))
|
||||||
|
{
|
||||||
|
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceAmpr(ctx, "write_address", commandBuffer, address, value);
|
||||||
|
ctx[CpuRegister.Rax] = 0;
|
||||||
|
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||||
|
}
|
||||||
|
|
||||||
public static int CompleteCommandBuffer(CpuContext ctx, ulong commandBuffer)
|
public static int CompleteCommandBuffer(CpuContext ctx, ulong commandBuffer)
|
||||||
{
|
{
|
||||||
if (commandBuffer == 0)
|
if (commandBuffer == 0)
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
using SharpEmu.HLE;
|
||||||
|
using SharpEmu.Libs.Ampr;
|
||||||
|
using System.Buffers.Binary;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharpEmu.Libs.Tests.Ampr;
|
||||||
|
|
||||||
|
public sealed class AmprWriteAddressTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void MeasureCommandSizeWriteAddress0400_MatchesOnCompletionVariant()
|
||||||
|
{
|
||||||
|
const string nid = "4fgtGfXDrFc";
|
||||||
|
const ulong memoryBase = 0x1_0000_0000;
|
||||||
|
var memory = new FakeCpuMemory(memoryBase, 0x1000);
|
||||||
|
var context = new CpuContext(memory, Generation.Gen5);
|
||||||
|
var manager = CreateManagerWithExport(
|
||||||
|
nid,
|
||||||
|
"sceAmprMeasureCommandSizeWriteAddress_04_00");
|
||||||
|
|
||||||
|
Assert.Equal(OrbisGen2Result.ORBIS_GEN2_OK, manager.Dispatch(nid, context));
|
||||||
|
var measured = context[CpuRegister.Rax];
|
||||||
|
|
||||||
|
Assert.Equal(0, AmprExports.MeasureCommandSizeWriteAddressOnCompletion(context));
|
||||||
|
Assert.Equal(context[CpuRegister.Rax], measured);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CommandBufferWriteAddress0400_WritesValueOnCompletion()
|
||||||
|
{
|
||||||
|
const string nid = "j0+3uJMxYJY";
|
||||||
|
const ulong memoryBase = 0x1_0000_0000;
|
||||||
|
const ulong commandBufferAddress = memoryBase + 0x100;
|
||||||
|
const ulong recordBufferAddress = memoryBase + 0x200;
|
||||||
|
const ulong watcherAddress = memoryBase + 0x800;
|
||||||
|
const ulong watcherValue = 1;
|
||||||
|
var memory = new FakeCpuMemory(memoryBase, 0x1000);
|
||||||
|
var context = new CpuContext(memory, Generation.Gen5);
|
||||||
|
var manager = CreateManagerWithExport(
|
||||||
|
nid,
|
||||||
|
"sceAmprCommandBufferWriteAddress_04_00");
|
||||||
|
|
||||||
|
context[CpuRegister.Rdi] = commandBufferAddress;
|
||||||
|
context[CpuRegister.Rsi] = recordBufferAddress;
|
||||||
|
context[CpuRegister.Rdx] = 0x100;
|
||||||
|
|
||||||
|
Assert.Equal(0, AmprExports.CommandBufferConstructor(context));
|
||||||
|
|
||||||
|
context[CpuRegister.Rdi] = commandBufferAddress;
|
||||||
|
context[CpuRegister.Rsi] = watcherAddress;
|
||||||
|
context[CpuRegister.Rdx] = watcherValue;
|
||||||
|
|
||||||
|
Assert.Equal(OrbisGen2Result.ORBIS_GEN2_OK, manager.Dispatch(nid, context));
|
||||||
|
|
||||||
|
Span<byte> watcher = stackalloc byte[sizeof(ulong)];
|
||||||
|
Assert.True(memory.TryRead(watcherAddress, watcher));
|
||||||
|
Assert.Equal(0UL, BinaryPrimitives.ReadUInt64LittleEndian(watcher));
|
||||||
|
|
||||||
|
Assert.Equal(0, AmprExports.CompleteCommandBuffer(context, commandBufferAddress));
|
||||||
|
|
||||||
|
Assert.True(memory.TryRead(watcherAddress, watcher));
|
||||||
|
Assert.Equal(watcherValue, BinaryPrimitives.ReadUInt64LittleEndian(watcher));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ModuleManager CreateManagerWithExport(string nid, string exportName)
|
||||||
|
{
|
||||||
|
var manager = new ModuleManager();
|
||||||
|
manager.RegisterExports(
|
||||||
|
SharpEmu.Generated.SysAbiExportRegistry.CreateExports(Generation.Gen5));
|
||||||
|
|
||||||
|
Assert.True(manager.TryGetExport(nid, out var export), $"NID {nid} did not register.");
|
||||||
|
Assert.Equal(exportName, export.Name);
|
||||||
|
Assert.Equal("libSceAmpr", export.LibraryName);
|
||||||
|
Assert.Equal(Generation.Gen5, export.Target);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user