// 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 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 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 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); }