From 5aadb7495a37cf1a8d1e7aa0e4cad8b8e59ab454 Mon Sep 17 00:00:00 2001 From: j92580498-max Date: Sun, 12 Jul 2026 18:24:11 +0300 Subject: [PATCH] Libs: add libSceDiscMap HLE exports (ported from Kyty) (#79) Port the libSceDiscMap stubs from Kyty (InoriRus/Kyty, MIT) into the SysAbiExport model. Disc-installed titles probe these NIDs on most file accesses to decide whether a read must be redirected to the disc drive; answering that every request is already resident on internal storage keeps I/O on the regular file system path instead of failing with unresolved-import errors. - sceDiscMapIsRequestOnHDD (lbQKqsERhtE): validates args, writes 1 to the result pointer, returns 0 - fJgP+wqifno / ioKMruft1ek: zero-fill the three output pointers, return 0 (names not present in ps5_names.txt; kept as descriptive Unknown exports like the existing sceKernelUnknown* convention) - DISC_MAP_ERROR_INVALID_ARGUMENT (0x81100001) on null pointers, matching the documented libSceDiscMap error range - optional tracing via SHARPEMU_LOG_DISCMAP=1 Co-authored-by: j92580498-max <252151737+j92580498-max@users.noreply.github.com> --- src/SharpEmu.Libs/DiscMap/DiscMapExports.cs | 104 ++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/SharpEmu.Libs/DiscMap/DiscMapExports.cs diff --git a/src/SharpEmu.Libs/DiscMap/DiscMapExports.cs b/src/SharpEmu.Libs/DiscMap/DiscMapExports.cs new file mode 100644 index 0000000..7363aa1 --- /dev/null +++ b/src/SharpEmu.Libs/DiscMap/DiscMapExports.cs @@ -0,0 +1,104 @@ +// Copyright (C) 2026 SharpEmu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +using SharpEmu.HLE; + +namespace SharpEmu.Libs.DiscMap; + +/// +/// HLE implementation of libSceDiscMap, ported from Kyty's LibDiscMap.cpp +/// (https://github.com/InoriRus/Kyty, MIT). Titles installed to internal +/// storage query these entry points on nearly every file access to decide +/// whether a read must be redirected to the Blu-ray drive. Reporting every +/// request as already resident on HDD lets the regular file system path +/// service the read. +/// +public static class DiscMapExports +{ + private const int DiscMapErrorInvalidArgument = unchecked((int)0x81100001); + private const int DiscMapErrorLocationNotMapped = unchecked((int)0x81100002); + private const int DiscMapErrorFileNotFound = unchecked((int)0x81100003); + private const int DiscMapErrorNoBitmapInfo = unchecked((int)0x81100004); + + [SysAbiExport( + Nid = "lbQKqsERhtE", + ExportName = "sceDiscMapIsRequestOnHDD", + Target = Generation.Gen4 | Generation.Gen5, + LibraryName = "libSceDiscMap")] + public static int DiscMapIsRequestOnHDD(CpuContext ctx) + { + var pathAddress = ctx[CpuRegister.Rdi]; + var offset = ctx[CpuRegister.Rsi]; + var size = ctx[CpuRegister.Rdx]; + var resultAddress = ctx[CpuRegister.Rcx]; + + if (pathAddress == 0 || resultAddress == 0) + { + return DiscMapErrorInvalidArgument; + } + + if (!ctx.TryWriteInt32(resultAddress, 1)) + { + return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; + } + + TraceDiscMap(ctx, "sceDiscMapIsRequestOnHDD", pathAddress, offset, size); + + ctx[CpuRegister.Rax] = 0; + return (int)OrbisGen2Result.ORBIS_GEN2_OK; + } + + [SysAbiExport( + Nid = "fJgP+wqifno", + ExportName = "sceDiscMapUnknownFJgP", + Target = Generation.Gen4 | Generation.Gen5, + LibraryName = "libSceDiscMap")] + public static int DiscMapUnknownFJgP(CpuContext ctx) => WriteMappingTriple(ctx, "sceDiscMapUnknownFJgP"); + + [SysAbiExport( + Nid = "ioKMruft1ek", + ExportName = "sceDiscMapUnknownIoKM", + Target = Generation.Gen4 | Generation.Gen5, + LibraryName = "libSceDiscMap")] + public static int DiscMapUnknownIoKM(CpuContext ctx) => WriteMappingTriple(ctx, "sceDiscMapUnknownIoKM"); + + private static int WriteMappingTriple(CpuContext ctx, string exportName) + { + var pathAddress = ctx[CpuRegister.Rdi]; + var offset = ctx[CpuRegister.Rsi]; + var size = ctx[CpuRegister.Rdx]; + var flagsAddress = ctx[CpuRegister.Rcx]; + var outAddress1 = ctx[CpuRegister.R8]; + var outAddress2 = ctx[CpuRegister.R9]; + + if (pathAddress == 0 || flagsAddress == 0 || outAddress1 == 0 || outAddress2 == 0) + { + return DiscMapErrorInvalidArgument; + } + + if (!ctx.TryWriteUInt64(flagsAddress, 0) || + !ctx.TryWriteUInt64(outAddress1, 0) || + !ctx.TryWriteUInt64(outAddress2, 0)) + { + return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT; + } + + TraceDiscMap(ctx, exportName, pathAddress, offset, size); + + ctx[CpuRegister.Rax] = 0; + return (int)OrbisGen2Result.ORBIS_GEN2_OK; + } + + private static void TraceDiscMap(CpuContext ctx, string exportName, ulong pathAddress, ulong offset, ulong size) + { + if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_DISCMAP"), "1", StringComparison.Ordinal)) + { + return; + } + + var path = ctx.TryReadNullTerminatedUtf8(pathAddress, 1024, out var value) + ? value + : $""; + Console.Error.WriteLine($"[HLE][DISCMAP] {exportName} path={path} offset=0x{offset:X} size=0x{size:X}"); + } +}