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.
This commit is contained in:
StoneDC authored and Adrià Franch committed 2026-10-26 14:35:14 +01:00
1 parent 3fee9d12ac
commit 2d662ce6fd
3 files changed
+23 -22

No files matched your search

+4 -8
View File
@@ -7,23 +7,19 @@
struct DiscId; struct DiscId;
struct DiscId2; struct DiscId2;
namespace {
constexpr std::int32_t SCE_DISC_ID_ERROR_NO_DISC = static_cast<std::int32_t>(0x80D50002);
}
extern "C" { extern "C" {
int APS5_VABI sceDiscIdGet(DiscId* discId) { int APS5_VABI sceDiscIdGet(DiscId* discId) {
(void)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) { int APS5_VABI sceDiscIdGet2(DiscId2* discId, std::uint32_t flags) {
(void)discId; (void)discId;
(void)flags; (void)flags;
return SCE_DISC_ID_ERROR_NO_DISC; NotImplemented_nid_no_patch(__func__);
return 0;
} }
} }
+18 -9
View File
@@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <stdexcept>
struct DiscId; struct DiscId;
struct DiscId2; struct DiscId2;
@@ -17,25 +18,33 @@ void Require(bool condition) {
if (!condition) std::abort(); if (!condition) std::abort();
} }
constexpr std::int32_t kErrNoDisc = static_cast<std::int32_t>(0x80D50002); template<typename TCall>
bool Throws(TCall call) {
try {
static_cast<void>(call());
} catch (const std::runtime_error&) {
return true;
}
return false;
}
} }
int main() { int main() {
Require(sceDiscIdGet(nullptr) == kErrNoDisc); Require(Throws([] { return sceDiscIdGet(nullptr); }));
Require(sceDiscIdGet2(nullptr, 0) == kErrNoDisc); Require(Throws([] { return sceDiscIdGet2(nullptr, 0); }));
Require(sceDiscIdGet2(nullptr, 0xFFFFFFFFu) == kErrNoDisc); Require(Throws([] { return sceDiscIdGet2(nullptr, 0xFFFFFFFFu); }));
std::uint8_t buffer[64]; std::uint8_t buffer[64];
std::memset(buffer, 0xAB, sizeof(buffer)); std::memset(buffer, 0xAB, sizeof(buffer));
auto* id = reinterpret_cast<DiscId*>(buffer); auto* id = reinterpret_cast<DiscId*>(buffer);
auto* id2 = reinterpret_cast<DiscId2*>(buffer); auto* id2 = reinterpret_cast<DiscId2*>(buffer);
Require(sceDiscIdGet(id) == kErrNoDisc); Require(Throws([id] { return sceDiscIdGet(id); }));
Require(sceDiscIdGet2(id2, 0) == kErrNoDisc); Require(Throws([id2] { return sceDiscIdGet2(id2, 0); }));
Require(sceDiscIdGet2(id2, 1) == kErrNoDisc); Require(Throws([id2] { return sceDiscIdGet2(id2, 1); }));
Require(sceDiscIdGet2(id2, 3) == kErrNoDisc); Require(Throws([id2] { return sceDiscIdGet2(id2, 3); }));
Require(sceDiscIdGet2(id2, 0xFFFFFFFFu) == kErrNoDisc); Require(Throws([id2] { return sceDiscIdGet2(id2, 0xFFFFFFFFu); }));
for (std::uint8_t byte : buffer) Require(byte == 0xAB); for (std::uint8_t byte : buffer) Require(byte == 0xAB);
return 0; return 0;
+1 -5
View File
@@ -1,9 +1,5 @@
# libSceDiscId technical debt # 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 ### 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.