Compare commits

..

2 Commits

Author SHA1 Message Date
ParantezTech dfe2b70b38 [pthread] Implemented pthread functions for AVPlayer compatibility 2026-07-05 19:00:24 +03:00
ParantezTech 9b3a73b4bf [sceAvPlayer] implement AvPlayer HLE's 2026-07-05 18:56:08 +03:00
5 changed files with 215 additions and 132 deletions
-127
View File
@@ -1204,51 +1204,6 @@ public static class AgcExports
return ReturnPointer(ctx, commandAddress);
}
[SysAbiExport(
Nid = "q88lQ+GP5Yk",
ExportName = "sceAgcDcbDrawIndex",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DcbDrawIndex(CpuContext ctx)
{
var commandBufferAddress = ctx[CpuRegister.Rdi];
var indexCount = (uint)ctx[CpuRegister.Rsi];
var indexAddress = ctx[CpuRegister.Rdx];
var modifier = (uint)ctx[CpuRegister.Rcx];
if (commandBufferAddress == 0 || modifier != 0x4000_0000)
{
return ReturnPointer(ctx, 0);
}
if (!TryAllocateCommandDwords(ctx, commandBufferAddress, 5, out var baseCommand) ||
!TryWriteUInt32(ctx, baseCommand, Pm4(3, ItIndexBase, 0)) ||
!TryWriteUInt32(ctx, baseCommand + 4, (uint)indexAddress) ||
!TryWriteUInt32(ctx, baseCommand + 8, (uint)(indexAddress >> 32)) ||
!TryWriteUInt32(ctx, baseCommand + 12, Pm4(2, ItIndexBufferSize, 0)) ||
!TryWriteUInt32(ctx, baseCommand + 16, indexCount))
{
return ReturnPointer(ctx, 0);
}
if (!TryAllocateCommandDwords(ctx, commandBufferAddress, 5, out var drawCommand) ||
!TryWriteUInt32(ctx, drawCommand, Pm4(5, ItDrawIndex2, 0)) ||
!TryWriteUInt32(ctx, drawCommand + 4, indexCount) ||
!TryWriteUInt32(ctx, drawCommand + 8, 0) ||
!TryWriteUInt32(ctx, drawCommand + 12, 0) ||
!TryWriteUInt32(ctx, drawCommand + 16, 0))
{
return ReturnPointer(ctx, 0);
}
TraceAgc(
$"agc.dcb_draw_index buf=0x{commandBufferAddress:X16} " +
$"base=0x{baseCommand:X16} draw=0x{drawCommand:X16} " +
$"count={indexCount} index=0x{indexAddress:X16}");
return ReturnPointer(ctx, drawCommand);
}
[SysAbiExport(
Nid = "Yw0jKSqop+E",
ExportName = "sceAgcDcbDrawIndexAuto",
@@ -2051,88 +2006,6 @@ public static class AgcExports
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "uJziRsODk1c",
ExportName = "sceAgcDriverGetResourceRegistrationMaxNameLength",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DriverGetResourceRegistrationMaxNameLength(CpuContext ctx)
{
var outAddress = ctx[CpuRegister.Rdi];
if (outAddress == 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
}
if (!TryWriteUInt32(ctx, outAddress, 256))
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
TraceAgc($"agc.driver_get_resource_registration_max_name_length out=0x{outAddress:X16} value=256");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
}
private const uint DefaultAgcOwner = 1;
[SysAbiExport(
Nid = "F0ZXt5q0ZTA",
ExportName = "sceAgcDriverGetDefaultOwner",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DriverGetDefaultOwner(CpuContext ctx)
{
var ownerAddress = ctx[CpuRegister.Rdi];
if (ownerAddress == 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
}
if (!TryWriteUInt32(ctx, ownerAddress, DefaultAgcOwner))
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
TraceAgc($"agc.driver_get_default_owner out=0x{ownerAddress:X16} owner={DefaultAgcOwner}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
}
[SysAbiExport(
Nid = "W5z4eZrjEas",
ExportName = "sceAgcDriverRegisterResource",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DriverRegisterResource(CpuContext ctx)
{
var resourceAddress = ctx[CpuRegister.Rdi];
var owner = (uint)ctx[CpuRegister.Rsi];
var nameAddress = ctx[CpuRegister.Rdx];
var type = (uint)ctx[CpuRegister.R8];
var flags = (uint)ctx[CpuRegister.R9];
TraceAgc(
$"agc.driver_register_resource resource=0x{resourceAddress:X16} owner={owner} " +
$"name=0x{nameAddress:X16} type={type} flags={flags}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
}
[SysAbiExport(
Nid = "-KRzWekV120",
ExportName = "sceAgcDriverUnknown_KRzWekV120",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DriverUnknownKRzWekV120(CpuContext ctx)
{
TraceAgc(
$"agc.driver_unknown_krz rdi=0x{ctx[CpuRegister.Rdi]:X16} " +
$"rsi=0x{ctx[CpuRegister.Rsi]:X16} rdx=0x{ctx[CpuRegister.Rdx]:X16} " +
$"rcx=0x{ctx[CpuRegister.Rcx]:X16} r8=0x{ctx[CpuRegister.R8]:X16} r9=0x{ctx[CpuRegister.R9]:X16}");
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
}
[SysAbiExport(
Nid = "h9z6+0hEydk",
ExportName = "sceAgcSuspendPoint",
@@ -0,0 +1,77 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using SharpEmu.HLE;
using SharpEmu.Libs.Kernel;
namespace SharpEmu.Libs.AvPlayer;
public static class AvPlayerExports
{
private const int InvalidParameters = unchecked((int)0x806A0001);
private static readonly object StateGate = new();
private static readonly HashSet<ulong> Players = new();
[SysAbiExport(
Nid = "aS66RI0gGgo",
ExportName = "sceAvPlayerInit",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceAvPlayer")]
public static int AvPlayerInit(CpuContext ctx)
{
if (ctx[CpuRegister.Rdi] == 0 ||
!KernelMemoryCompatExports.TryAllocateHleData(ctx, 0x40, 16, out var handle))
{
ctx[CpuRegister.Rax] = 0;
return 0;
}
lock (StateGate)
{
Players.Add(handle);
}
ctx[CpuRegister.Rax] = handle;
return unchecked((int)handle);
}
[SysAbiExport(
Nid = "HD1YKVU26-M",
ExportName = "sceAvPlayerPostInit",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceAvPlayer")]
public static int AvPlayerPostInit(CpuContext ctx)
{
var handle = ctx[CpuRegister.Rdi];
var dataAddress = ctx[CpuRegister.Rsi];
lock (StateGate)
{
return SetReturn(
ctx,
handle != 0 && dataAddress != 0 && Players.Contains(handle)
? 0
: InvalidParameters);
}
}
[SysAbiExport(
Nid = "NkJwDzKmIlw",
ExportName = "sceAvPlayerClose",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceAvPlayer")]
public static int AvPlayerClose(CpuContext ctx)
{
lock (StateGate)
{
return SetReturn(
ctx,
Players.Remove(ctx[CpuRegister.Rdi]) ? 0 : InvalidParameters);
}
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)result);
return result;
}
}
@@ -103,6 +103,7 @@ public static class KernelMemoryCompatExports
private static readonly Dictionary<ulong, DirectAllocation> _directAllocations = new();
private static readonly Dictionary<ulong, LibcHeapAllocation> _libcAllocations = new();
private static readonly Dictionary<ulong, MappedRegion> _mappedRegions = new();
private static readonly Dictionary<ulong, string> _mappedRegionNames = new();
private static readonly Dictionary<ulong, ulong> _tlsModuleBlocks = new();
private static readonly Dictionary<string, string> _guestMounts = new(StringComparer.OrdinalIgnoreCase);
private static readonly HashSet<string> _tracedStatResults = new(StringComparer.Ordinal);
@@ -231,6 +232,25 @@ public static class KernelMemoryCompatExports
return true;
}
internal static void RegisterReservedVirtualRange(ulong address, ulong length)
{
if (address == 0 || length == 0)
{
return;
}
lock (_memoryGate)
{
_mappedRegions[address] = new MappedRegion(
address,
length,
Protection: 0,
IsFlexible: false,
IsDirect: false,
DirectStart: 0);
}
}
[SysAbiExport(
Nid = "8zTFvBIAIN8",
ExportName = "memset",
@@ -2435,6 +2455,36 @@ public static class KernelMemoryCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "hwVSPCmp5tM",
ExportName = "sceKernelCheckedReleaseDirectMemory",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libKernel")]
public static int KernelCheckedReleaseDirectMemory(CpuContext ctx)
{
var start = ctx[CpuRegister.Rdi];
var length = ctx[CpuRegister.Rsi];
if (length == 0)
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
}
lock (_memoryGate)
{
if (!_directAllocations.TryGetValue(start, out var allocation) ||
allocation.Length != length)
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
}
_directAllocations.Remove(start);
_nextPhysicalAddress = GetDirectMemoryHighWaterMarkLocked();
}
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "L-Q3LEjIbgA",
ExportName = "sceKernelMapDirectMemory",
@@ -2614,6 +2664,16 @@ public static class KernelMemoryCompatExports
return KernelMapNamedFlexibleMemory(ctx);
}
[SysAbiExport(
Nid = "4h6F1LLbTiw",
ExportName = "sceKernelMapFlexibleMemoryInternal",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libKernel")]
public static int KernelMapFlexibleMemoryInternal(CpuContext ctx)
{
return KernelMapNamedFlexibleMemory(ctx);
}
[SysAbiExport(
Nid = "2SKEx6bSq-4",
ExportName = "sceKernelBatchMap",
@@ -2667,6 +2727,44 @@ public static class KernelMemoryCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "DGMG3JshrZU",
ExportName = "sceKernelSetVirtualRangeName",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libKernel")]
public static int KernelSetVirtualRangeName(CpuContext ctx)
{
var address = ctx[CpuRegister.Rdi];
var length = ctx[CpuRegister.Rsi];
var nameAddress = ctx[CpuRegister.Rdx];
if (nameAddress == 0)
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}
if (!TryReadCString(ctx, nameAddress, OrbisKernelMaximumNameLength, out var nameBytes))
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
}
var name = Encoding.UTF8.GetString(nameBytes);
lock (_memoryGate)
{
if (!TryFindVirtualQueryRegionLocked(address, findNext: false, out var region) ||
length > region.Length ||
address < region.Address ||
length > region.Address + region.Length - address)
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
}
_mappedRegionNames[region.Address] = name;
}
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "rVjRvHJ0X6c",
ExportName = "sceKernelVirtualQuery",
@@ -2724,11 +2822,16 @@ public static class KernelMemoryCompatExports
BinaryPrimitives.WriteInt32LittleEndian(payload[28..32], memoryType);
payload[32] = unchecked((byte)stateFlags);
var name = region.IsDirect
? "direct"
: region.IsFlexible
? "flexible"
: string.Empty;
string name;
lock (_memoryGate)
{
name = _mappedRegionNames.GetValueOrDefault(region.Address)
?? (region.IsDirect
? "direct"
: region.IsFlexible
? "flexible"
: string.Empty);
}
if (!string.IsNullOrEmpty(name))
{
var nameBytes = Encoding.ASCII.GetBytes(name);
@@ -717,6 +717,35 @@ public static class KernelPthreadExtendedCompatExports
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "FXPWHNk8Of0",
ExportName = "scePthreadAttrGetschedparam",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libKernel")]
public static int PthreadAttrGetschedparam(CpuContext ctx)
{
var attrAddress = ctx[CpuRegister.Rdi];
var schedParamAddress = ctx[CpuRegister.Rsi];
if (attrAddress == 0 || schedParamAddress == 0)
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT;
}
PthreadAttrState state;
lock (_stateGate)
{
state = GetOrCreateAttrStateLocked(attrAddress);
}
if (!TryWriteInt32(ctx, schedParamAddress, state.SchedPriority))
{
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
}
ctx[CpuRegister.Rax] = 0;
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}
[SysAbiExport(
Nid = "DzES9hQF4f4",
ExportName = "scePthreadAttrSetschedparam",
@@ -752,6 +752,7 @@ public static class KernelRuntimeCompatExports
_nextReservedVirtualBase = Math.Max(_nextReservedVirtualBase, mappedAddress + length);
}
KernelMemoryCompatExports.RegisterReservedVirtualRange(mappedAddress, length);
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
}