From 2d662ce6fd249d7c0e0769d9ae3ac9c02ff0c962 Mon Sep 17 00:00:00 2001 From: StoneDC <19905433+StoneDC@users.noreply.github.com> Date: Fri, 23 Oct 2026 15:46:14 +0800 Subject: [PATCH] fix(libSceDiscId): keep unsupported exports explicit CONTRIBUTING.md permits silent stubs only when unblocking a title UI path and when backed by title evidence. Since no title ID evidence demonstrates that a constant no-disc return unblocks a UI path, throw NotImplemented_nid_no_patch from sceDiscIdGet and sceDiscIdGet2 without touching caller memory. Tests assert both calls throw on null and non-null outputs and across flags values while leaving caller buffers untouched, and the debt entry records the unresolved hardware contract. --- core/libs/prx/libSceDiscId/Export.cpp | 12 ++++-------- core/libs/tests/GuestDiscId.cpp | 27 ++++++++++++++++++--------- docs/dev/debt/libSceDiscId.md | 6 +----- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/core/libs/prx/libSceDiscId/Export.cpp b/core/libs/prx/libSceDiscId/Export.cpp index f39278be8b..4d78f72e07 100644 --- a/core/libs/prx/libSceDiscId/Export.cpp +++ b/core/libs/prx/libSceDiscId/Export.cpp @@ -7,23 +7,19 @@ struct DiscId; struct DiscId2; -namespace { - -constexpr std::int32_t SCE_DISC_ID_ERROR_NO_DISC = static_cast(0x80D50002); - -} - extern "C" { int APS5_VABI sceDiscIdGet(DiscId* discId) { (void)discId; - return SCE_DISC_ID_ERROR_NO_DISC; + NotImplemented_nid_no_patch(__func__); + return 0; } int APS5_VABI sceDiscIdGet2(DiscId2* discId, std::uint32_t flags) { (void)discId; (void)flags; - return SCE_DISC_ID_ERROR_NO_DISC; + NotImplemented_nid_no_patch(__func__); + return 0; } } diff --git a/core/libs/tests/GuestDiscId.cpp b/core/libs/tests/GuestDiscId.cpp index d849535842..75de884e45 100644 --- a/core/libs/tests/GuestDiscId.cpp +++ b/core/libs/tests/GuestDiscId.cpp @@ -2,6 +2,7 @@ #include #include #include +#include struct DiscId; struct DiscId2; @@ -17,25 +18,33 @@ void Require(bool condition) { if (!condition) std::abort(); } -constexpr std::int32_t kErrNoDisc = static_cast(0x80D50002); +template +bool Throws(TCall call) { + try { + static_cast(call()); + } catch (const std::runtime_error&) { + return true; + } + return false; +} } int main() { - Require(sceDiscIdGet(nullptr) == kErrNoDisc); - Require(sceDiscIdGet2(nullptr, 0) == kErrNoDisc); - Require(sceDiscIdGet2(nullptr, 0xFFFFFFFFu) == kErrNoDisc); + Require(Throws([] { return sceDiscIdGet(nullptr); })); + Require(Throws([] { return sceDiscIdGet2(nullptr, 0); })); + Require(Throws([] { return sceDiscIdGet2(nullptr, 0xFFFFFFFFu); })); std::uint8_t buffer[64]; std::memset(buffer, 0xAB, sizeof(buffer)); auto* id = reinterpret_cast(buffer); auto* id2 = reinterpret_cast(buffer); - Require(sceDiscIdGet(id) == kErrNoDisc); - Require(sceDiscIdGet2(id2, 0) == kErrNoDisc); - Require(sceDiscIdGet2(id2, 1) == kErrNoDisc); - Require(sceDiscIdGet2(id2, 3) == kErrNoDisc); - Require(sceDiscIdGet2(id2, 0xFFFFFFFFu) == kErrNoDisc); + Require(Throws([id] { return sceDiscIdGet(id); })); + Require(Throws([id2] { return sceDiscIdGet2(id2, 0); })); + Require(Throws([id2] { return sceDiscIdGet2(id2, 1); })); + Require(Throws([id2] { return sceDiscIdGet2(id2, 3); })); + Require(Throws([id2] { return sceDiscIdGet2(id2, 0xFFFFFFFFu); })); for (std::uint8_t byte : buffer) Require(byte == 0xAB); return 0; diff --git a/docs/dev/debt/libSceDiscId.md b/docs/dev/debt/libSceDiscId.md index 9bd713bd56..8401e28ef4 100644 --- a/docs/dev/debt/libSceDiscId.md +++ b/docs/dev/debt/libSceDiscId.md @@ -1,9 +1,5 @@ # libSceDiscId technical debt -### Silent stubs - -- [libSceDiscId](../../../core/libs/prx/libSceDiscId/Export.cpp) has no optical disc drive backend: `sceDiscIdGet` and `sceDiscIdGet2` report `SCE_DISC_ID_ERROR_NO_DISC` (0x80D50002) for every pointer and flag value, without reading or writing the output. Neither SDK nor console evidence establishes that these exports reject a null output or an unsupported flag value, or which error would take precedence, so no argument is treated as invalid. The no-disc code itself is assumed. - ### Unknown function info -- [sceDiscIdGet](../../../core/libs/prx/libSceDiscId/Export.cpp) takes one output pointer; `sceDiscIdGet2` takes an output pointer and a 32-bit argument whose accepted values remain unresolved (it may be a bitfield). Both pass the pointer to a device ioctl without accessing its contents. Output structure sizes and fields require the device-side implementation or a caller and remain unresolved. +- [sceDiscIdGet, sceDiscIdGet2](../../../core/libs/prx/libSceDiscId/Export.cpp): `sceDiscIdGet` takes one output pointer; `sceDiscIdGet2` takes an output pointer and a 32-bit argument whose accepted values remain unresolved (it may be a bitfield). Both throw `NotImplemented_nid_no_patch` without reading or writing caller memory: the optical drive backend, the output structure layout, accepted flags and error returns remain unverified on hardware, so the unsupported behavior stays explicit.