From c1fefdb2bc27d1f7a43eb6928d1995e1ca41c596 Mon Sep 17 00:00:00 2001 From: Omar Elmahy Date: Sun, 1 Nov 2026 05:32:15 +0000 Subject: [PATCH] feat(libSceInvitationDialog): return not-initialized error before dialog initialization --- core/libs/prx/libSceInvitationDialog/Export.cpp | 6 ++++++ core/libs/tests/GuestInvitationDialog.cpp | 17 ++++------------- docs/dev/debt/libSceInvitationDialog.md | 3 ++- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/core/libs/prx/libSceInvitationDialog/Export.cpp b/core/libs/prx/libSceInvitationDialog/Export.cpp index 5b10dbd0fa..d52fc3e037 100644 --- a/core/libs/prx/libSceInvitationDialog/Export.cpp +++ b/core/libs/prx/libSceInvitationDialog/Export.cpp @@ -120,11 +120,17 @@ int APS5_VABI sceInvitationDialogGetStatus_nid_postfix(void) { } int APS5_VABI sceInvitationDialogOpenA_nid_postfix(void) { + DialogState& dialog = Dialog(); + std::lock_guard lock(dialog.mutex); + if (dialog.status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED; NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceInvitationDialogGetResultA_nid_postfix(void) { + DialogState& dialog = Dialog(); + std::lock_guard lock(dialog.mutex); + if (dialog.status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED; NotImplemented_nid_no_patch(__func__); return 0; } diff --git a/core/libs/tests/GuestInvitationDialog.cpp b/core/libs/tests/GuestInvitationDialog.cpp index f7caafb0fc..adf66b5e27 100644 --- a/core/libs/tests/GuestInvitationDialog.cpp +++ b/core/libs/tests/GuestInvitationDialog.cpp @@ -150,22 +150,11 @@ void TestCanceled() { Require(sceInvitationDialogTerminate() == 0, "terminate again"); } -template -void RequireNotImplemented(TCall call, const char* message) { - bool threw = false; - try { - call(); - } catch (const std::runtime_error& error) { - threw = std::string(error.what()).find("not implemented") != std::string::npos; - } - Require(threw, message); -} - void TestStatusAndPending() { int callbackArg = 0; Require(sceInvitationDialogGetStatus_nid_postfix() == StatusNone, "get status before initialization"); - RequireNotImplemented([] { sceInvitationDialogOpenA_nid_postfix(); }, "openA is not implemented"); - RequireNotImplemented([] { sceInvitationDialogGetResultA_nid_postfix(); }, "getResultA is not implemented"); + Require(sceInvitationDialogOpenA_nid_postfix() == NotInitialized, "openA before initialization"); + Require(sceInvitationDialogGetResultA_nid_postfix() == NotInitialized, "getResultA before initialization"); Require(sceInvitationDialogInitialize() == 0, "initialize for status check"); Require(sceInvitationDialogGetStatus_nid_postfix() == StatusInitialized, "status after initialize"); const InvitationDialogParam send = MakeParam(ModeSend, &callbackArg); @@ -173,6 +162,8 @@ void TestStatusAndPending() { Require(sceInvitationDialogGetStatus_nid_postfix() == StatusFinished, "status after open"); Require(sceInvitationDialogTerminate() == 0, "terminate after status check"); Require(sceInvitationDialogGetStatus_nid_postfix() == StatusNone, "status after terminate"); + Require(sceInvitationDialogOpenA_nid_postfix() == NotInitialized, "openA after termination"); + Require(sceInvitationDialogGetResultA_nid_postfix() == NotInitialized, "getResultA after termination"); } diff --git a/docs/dev/debt/libSceInvitationDialog.md b/docs/dev/debt/libSceInvitationDialog.md index e8ed9744c1..351c106a41 100644 --- a/docs/dev/debt/libSceInvitationDialog.md +++ b/docs/dev/debt/libSceInvitationDialog.md @@ -8,10 +8,11 @@ ### Unknown function info - [sceInvitationDialogGetStatus](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS5) - the name and NID (`EiF92YDNHRA`) appear in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceInvitationDialog.c). It returns the current dialog status (`NONE`, `INITIALIZED`, `RUNNING` or `FINISHED`) like `sceInvitationDialogUpdateStatus`; console behaviour is not measured. -- [sceInvitationDialogOpenA, sceInvitationDialogGetResultA](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS5) - the names and NIDs (`sAxbHhAWMXM`, `WuuUhuKOxwQ`) appear in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceInvitationDialog.c); their parameter and result layouts and behaviour are unverified. The declarations use the no-parameter unknown-signature convention and throw through `NotImplemented_nid_no_patch`. +- [sceInvitationDialogOpenA, sceInvitationDialogGetResultA](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS5) - the names and NIDs (`sAxbHhAWMXM`, `WuuUhuKOxwQ`) appear in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceInvitationDialog.c); their parameter and result layouts and behaviour are unverified. The declarations use the no-parameter unknown-signature convention and initialized calls throw through `NotImplemented_nid_no_patch`. - [sceInvitationDialogOpen, sceInvitationDialogGetResult](../../../core/libs/prx/libSceInvitationDialog/include/Api.hpp) (libSceInvitationDialog, PS4) - the field names and the 144-byte `InvitationDialogParam` come from the [shadPS4 header](https://github.com/shadps4-emu/shadPS4/blob/2cdefaa1298c6e4ece6c74bd84e90f3906282d51/src/core/libraries/invitation_dialog/invitation_dialog.h). They match the supplied `libSceInvitationDialog.sprx`: export `8XKR6wa64iQ` at 0xFF0 checks the reserved bytes 0x18..0x37 of the result and writes its status at 0x08, and the helper at 0x410 copies eight bytes of the saved open parameter to 0x00, the eight result bytes to 0x08 and up to 16 20-byte online ids through the pointer at 0x10, after a four-byte count. A param whose `size` is not 144, or whose `mode` is neither 1 (send) nor 2 (receive), throws, and so does a result with a non-zero reserved byte. `baseParam`, `userId` and `dataParam`, with its 1 to 16 recipients, are not checked. - [sceInvitationDialogOpen, sceInvitationDialogClose, sceInvitationDialogGetResult](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS4) - two paths throw because shadPS4 and the other common dialogs here return different errors: `Open` before `Initialize` (shadPS4 `INVALID_STATE`, the Signin family `NOT_INITIALIZED`) and `Close` on a dialog that is not running, which is every `Close` after `Initialize` here (shadPS4 `NOT_RUNNING`, the Signin family 0). `GetResult` before the dialog finishes returns `NOT_FINISHED` even for a null result, as in shadPS4. shadPS4 returns the `result` value from `GetResult`; this returns 0, which the module writes at 0x08 as `errorCode`. ### Functional - [sceInvitationDialogInitialize, sceInvitationDialogTerminate](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS4) - `Initialize` returns `NOT_SYSTEM_INITIALIZED` before `sceCommonDialogInitialize`, then `ALREADY_INITIALIZED`, then `BUSY` while another dialog holds the common dialog system, in [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/2cdefaa1298c6e4ece6c74bd84e90f3906282d51/src/core/libraries/invitation_dialog/invitation_dialog.cpp)'s order, and `Terminate` frees the system. Only this library takes the system through [libSceCommonDialog](libSceCommonDialog.md) so far, so the other common dialogs neither return `BUSY` because of it nor make it return `BUSY`. Not measured on a console. +- [sceInvitationDialogOpenA, sceInvitationDialogGetResultA](../../../core/libs/prx/libSceInvitationDialog/Export.cpp) (libSceInvitationDialog, PS5) - return `COMMON_DIALOG_ERROR_NOT_INITIALIZED` (`0x80B80003`) before initialization and after termination, inferred from the existing dialog lifecycle model rather than export-specific evidence. Parameter and result layouts, argument validation, error precedence and initialized behavior remain unverified; initialized calls throw through `NotImplemented_nid_no_patch`. Not measured on a console.