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