mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-20 01:46:22 +08:00
e1cf5b13ef
* [agc] WAIT_REG_MEM suspend/resume, draw packet fixes, new HLE exports, debug cleanup
Rebased onto upstream 79a7437 (par274/sharpemu, rewritten history).
- GpuWaitRegistry: DCBs suspended on unsatisfied WAIT_REG_MEM are re-polled
against guest memory on every submit; fixed 64-bit and standard packet parse
offsets, apply the mask, treat PM4 compare function 0 as "always".
- TryReadSubmittedDrawCount: accept the 5-dword ItDrawIndex2 form emitted by
DcbDrawIndex (count at +4); menu draws were silently discarded before.
- sceAgcDriverSubmitMultiDcbs: reversed ABI (rdi=address array, rsi=dword
sizes, rdx=count).
- VideoOut: vblank events, sceVideoOutGetFlipStatus, buffers registered via
sceVideoOutRegisterBuffers are valid flip targets.
- New HLE: libc stdio (fopen/fread/fseek/ftell/fclose/fgets), Dinkumware
_Getpctype ctype table, NpTrophy2 stubs, AMPR PAK sequential-read tracker,
MsgDialog lifecycle, NGS2 alt NIDs + dummy vtable for handle objects,
guarded memset intrinsic, abort()/strcasecmp null-arg recovery.
- Removed investigation-only code (INT3 breakpoints, qfont/mcpp dumps,
error-candidate printf traces, unconditional debug logs).
First rendered frame: Quake (PPSA01880) presents a 1920x1080 guest frame.
* Implemented a guarded native intrinsic (rep movsb) in DirectExecutionBackend to bypass HLE dispatch overhead, while preserving memory safety checks.
107 lines
3.6 KiB
C#
107 lines
3.6 KiB
C#
// Copyright (C) 2026 SharpEmu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
using SharpEmu.HLE;
|
|
using SharpEmu.Libs.VideoOut;
|
|
using System.Buffers.Binary;
|
|
|
|
namespace SharpEmu.Libs.SystemService;
|
|
|
|
public static class SystemServiceExports
|
|
{
|
|
private const int OrbisSystemServiceErrorParameter = unchecked((int)0x80A10003);
|
|
private const int SystemServiceStatusSize = 0x0C;
|
|
private const int DisplaySafeAreaInfoSize = sizeof(float) + 128;
|
|
|
|
[SysAbiExport(
|
|
Nid = "fZo48un7LK4",
|
|
ExportName = "sceSystemServiceParamGetInt",
|
|
Target = Generation.Gen4 | Generation.Gen5,
|
|
LibraryName = "libSceSystemService")]
|
|
public static int SystemServiceParamGetInt(CpuContext ctx)
|
|
{
|
|
var parameterId = unchecked((int)ctx[CpuRegister.Rdi]);
|
|
var valueAddress = ctx[CpuRegister.Rsi];
|
|
if (valueAddress == 0)
|
|
{
|
|
return ctx.SetReturn(OrbisSystemServiceErrorParameter);
|
|
}
|
|
|
|
var value = parameterId switch
|
|
{
|
|
1 or 2 or 3 or 1000 => 1,
|
|
4 => 180,
|
|
_ => 0,
|
|
};
|
|
|
|
Span<byte> valueBytes = stackalloc byte[sizeof(int)];
|
|
BinaryPrimitives.WriteInt32LittleEndian(valueBytes, value);
|
|
return ctx.Memory.TryWrite(valueAddress, valueBytes)
|
|
? ctx.SetReturn(0)
|
|
: ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
|
}
|
|
|
|
[SysAbiExport(
|
|
Nid = "rPo6tV8D9bM",
|
|
ExportName = "sceSystemServiceGetStatus",
|
|
Target = Generation.Gen4 | Generation.Gen5,
|
|
LibraryName = "libSceSystemService")]
|
|
public static int SystemServiceGetStatus(CpuContext ctx)
|
|
{
|
|
var statusAddress = ctx[CpuRegister.Rdi];
|
|
if (statusAddress == 0)
|
|
{
|
|
return ctx.SetReturn(OrbisSystemServiceErrorParameter);
|
|
}
|
|
|
|
Span<byte> status = stackalloc byte[SystemServiceStatusSize];
|
|
status.Clear();
|
|
BinaryPrimitives.WriteInt32LittleEndian(status, 0);
|
|
status[0x06] = 1;
|
|
|
|
return ctx.Memory.TryWrite(statusAddress, status)
|
|
? ctx.SetReturn(0)
|
|
: ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
|
}
|
|
|
|
[SysAbiExport(
|
|
Nid = "1n37q1Bvc5Y",
|
|
ExportName = "sceSystemServiceGetDisplaySafeAreaInfo",
|
|
Target = Generation.Gen4 | Generation.Gen5,
|
|
LibraryName = "libSceSystemService")]
|
|
public static int SystemServiceGetDisplaySafeAreaInfo(CpuContext ctx)
|
|
{
|
|
var infoAddress = ctx[CpuRegister.Rdi];
|
|
if (infoAddress == 0)
|
|
{
|
|
return ctx.SetReturn(OrbisSystemServiceErrorParameter);
|
|
}
|
|
|
|
Span<byte> info = stackalloc byte[DisplaySafeAreaInfoSize];
|
|
info.Clear();
|
|
BinaryPrimitives.WriteSingleLittleEndian(info, 1.0f);
|
|
|
|
return ctx.Memory.TryWrite(infoAddress, info)
|
|
? ctx.SetReturn(0)
|
|
: ctx.SetReturn((int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
|
|
}
|
|
|
|
[SysAbiExport(
|
|
Nid = "Vo5V8KAwCmk",
|
|
ExportName = "sceSystemServiceHideSplashScreen",
|
|
Target = Generation.Gen4 | Generation.Gen5,
|
|
LibraryName = "libSceSystemService")]
|
|
public static int SystemServiceHideSplashScreen(CpuContext ctx)
|
|
{
|
|
VulkanVideoPresenter.HideSplashScreen();
|
|
return ctx.SetReturn(0);
|
|
}
|
|
|
|
[SysAbiExport(
|
|
Nid = "3s8cHiCBKBE",
|
|
ExportName = "sceSystemServiceReportAbnormalTermination",
|
|
Target = Generation.Gen4 | Generation.Gen5,
|
|
LibraryName = "libSceSystemService")]
|
|
public static int SystemServiceReportAbnormalTermination(CpuContext ctx) => ctx.SetReturn(0);
|
|
}
|