feat(libSceHmd): refuse the field of view, eye offset and sensor queries without a headset

No handle is ever open, as sceHmdOpen reports the headset disconnected, so they return HANDLE_INVALID after initialization and NOT_INITIALIZED before it, without writing their outputs.
This commit is contained in:
Yossi Yadgar committed 2026-10-20 10:13:11 +03:00
1 parent fa916ae7bc
commit fe6aba89a8
3 files changed
+41 -9

No files matched your search

+14 -9
View File
@@ -262,9 +262,11 @@ int APS5_VABI sceHmdReprojectionInitializeCapture(void) {
return 0;
}
int APS5_VABI sceHmdGet2DEyeOffset(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceHmdGet2DEyeOffset(std::int32_t handle, void* leftOffset, void* rightOffset) {
(void)handle;
(void)leftOffset;
(void)rightOffset;
return initialized.load() ? Hmd::InvalidHandle : Hmd::NotInitialized;
}
int APS5_VABI sceHmdInternalSetDebugSocialScreenMode(void) {
@@ -376,9 +378,10 @@ int APS5_VABI sceHmdInternalSetM2LedOn(void) {
return 0;
}
int APS5_VABI sceHmdGetFieldOfView(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceHmdGetFieldOfView(std::int32_t handle, void* fieldOfView) {
(void)handle;
if (!fieldOfView) return Hmd::ParameterNull;
return initialized.load() ? Hmd::InvalidHandle : Hmd::NotInitialized;
}
int APS5_VABI sceHmdReprojectionAddDisplayBuffer(void) {
@@ -764,9 +767,11 @@ int APS5_VABI sceHmdInternalSetDefaultLedData(void) {
return 0;
}
int APS5_VABI sceHmdGetInertialSensorData(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceHmdGetInertialSensorData(std::int32_t handle, void* data, std::int32_t count) {
(void)handle;
(void)data;
(void)count;
return initialized.load() ? Hmd::InvalidHandle : Hmd::NotInitialized;
}
int APS5_VABI sceHmdInternal3dAudioClose(void) {
+3
View File
@@ -69,6 +69,9 @@ int APS5_VABI sceHmdReprojectionQueryGarlicBuffAlign(void);
int APS5_VABI sceHmdReprojectionQueryGarlicBuffSize(void);
int APS5_VABI sceHmdReprojectionQueryOnionBuffAlign(void);
int APS5_VABI sceHmdReprojectionQueryOnionBuffSize(void);
int APS5_VABI sceHmdGetFieldOfView(std::int32_t handle, void* fieldOfView);
int APS5_VABI sceHmdGet2DEyeOffset(std::int32_t handle, void* leftOffset, void* rightOffset);
int APS5_VABI sceHmdGetInertialSensorData(std::int32_t handle, void* data, std::int32_t count);
}
#endif
+24
View File
@@ -31,6 +31,28 @@ void CheckBufferQueries() {
Require(sceHmdReprojectionQueryOnionBuffSize() == 0x810, "reprojection onion buffer size");
}
void CheckHandleQueries(std::int32_t expected) {
unsigned char left[16];
unsigned char right[16];
unsigned char fieldOfView[16];
unsigned char sensor[64];
std::memset(left, 0x5a, sizeof(left));
std::memset(right, 0x5a, sizeof(right));
std::memset(fieldOfView, 0x5a, sizeof(fieldOfView));
std::memset(sensor, 0x5a, sizeof(sensor));
for (const auto handle : {0, -1, 1, 0x0f000000}) {
Require(sceHmdGetFieldOfView(handle, nullptr) == Hmd::ParameterNull, "null field of view accepted");
Require(sceHmdGetFieldOfView(handle, fieldOfView) == expected, "field of view without a headset");
Require(sceHmdGet2DEyeOffset(handle, left, right) == expected, "eye offset without a headset");
Require(sceHmdGet2DEyeOffset(handle, nullptr, nullptr) == expected, "eye offset with null outputs");
Require(sceHmdGetInertialSensorData(handle, sensor, 1) == expected, "sensor data without a headset");
}
for (const auto* bytes : {left, right, fieldOfView}) {
for (std::size_t index = 0; index < 16; ++index) Require(bytes[index] == 0x5a, "a refused query wrote its output");
}
for (const auto byte : sensor) Require(byte == 0x5a, "a refused sensor query wrote its output");
}
}
int main() {
@@ -47,6 +69,7 @@ int main() {
Require(sceHmdGetDeviceInformation(nullptr) == Hmd::ParameterNull, "null information");
Require(sceHmdGetDeviceInformation(&info) == Hmd::NotInitialized, "query before initialize");
Require(std::memcmp(&info, &untouched, sizeof(info)) == 0, "failed query modified output");
CheckHandleQueries(Hmd::NotInitialized);
Require(sceHmdGetDeviceInformationByHandle(0, &info) == Hmd::NotInitialized,
"handle query before initialize");
Require(sceHmdInitialize(nullptr) == Hmd::ParameterNull, "null initialize");
@@ -83,6 +106,7 @@ int main() {
"query accepted invalid handle");
Require(std::memcmp(&info, &expected, sizeof(info)) == 0, "invalid handle modified output");
}
CheckHandleQueries(Hmd::InvalidHandle);
Require(sceHmdGetDeviceInformationByHandle(0, nullptr) == Hmd::InvalidHandle,
"null query accepted invalid handle");
Require(sceHmdTerminate() == 0, "terminate failed");