fix(npcommerce): restore dialog result data and return value

This commit is contained in:
boykopovar committed 2026-10-21 21:53:51 +03:00
1 parent 4e67d2380d
commit cb8ad7c777
4 files changed
+42 -23

No files matched your search

@@ -29,6 +29,17 @@ struct PlayerReviewDialogParam {
std::uint8_t reserved[64];
};
struct NpCommerceDialogResult {
std::int32_t result;
std::uint8_t authorized;
std::uint8_t padding[3];
std::uint64_t userData;
std::uint8_t reserved[32];
};
static_assert(sizeof(NpCommerceDialogResult) == 48);
static_assert(offsetof(NpCommerceDialogResult, userData) == 8);
struct NpCommerceDialogParam {
CommonDialogBaseParam base;
std::uint32_t size;
+10 -7
View File
@@ -24,6 +24,7 @@ constexpr int COMMON_DIALOG_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80B8000A
constexpr int COMMON_DIALOG_ERROR_NOT_RUNNING = static_cast<int>(0x80B8000Bu);
int g_status = COMMON_DIALOG_STATUS_NONE;
std::uint64_t g_userData = 0;
std::uint32_t compiledSdkVersion() {
const auto* process = static_cast<const std::byte*>(ApplicationProcessParameters_nid_no_patch());
@@ -106,6 +107,7 @@ int APS5_VABI sceNpCommerceDialogOpen(const NpCommerceDialogParam* param) {
if (!ValidateCommonDialogBaseParam(param->base)) return COMMON_DIALOG_ERROR_INVALID_ARGUMENT;
if (g_status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (!validateParam(*param)) return COMMON_DIALOG_ERROR_INVALID_ARGUMENT;
g_userData = param->userData;
g_status = COMMON_DIALOG_STATUS_FINISHED;
return 0;
}
@@ -118,16 +120,16 @@ int APS5_VABI sceNpCommerceDialogGetStatus(void) {
return g_status;
}
int APS5_VABI sceNpCommerceDialogGetResult(void* result) {
int APS5_VABI sceNpCommerceDialogGetResult(NpCommerceDialogResult* result) {
if (result == nullptr) return COMMON_DIALOG_ERROR_ARG_NULL;
if (g_status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (g_status != COMMON_DIALOG_STATUS_FINISHED) return COMMON_DIALOG_ERROR_NOT_FINISHED;
// SceNpCommerceDialogResult: int32 result, bool authorized, then reserved bytes.
std::int32_t value = COMMON_DIALOG_RESULT_USER_CANCELED;
std::memcpy(result, &value, sizeof(value));
std::uint8_t authorized = 0;
std::memcpy(static_cast<std::uint8_t*>(result) + sizeof(value), &authorized, sizeof(authorized));
return 0;
const auto sdkVersion = compiledSdkVersion();
result->result = COMMON_DIALOG_RESULT_USER_CANCELED;
result->authorized = 0;
result->userData = g_userData;
if (sdkVersion >= 0x01700000) std::fill(std::begin(result->reserved), std::end(result->reserved), 0);
return COMMON_DIALOG_RESULT_USER_CANCELED;
}
int APS5_VABI sceNpCommerceDialogClose(void) {
@@ -162,6 +164,7 @@ int APS5_VABI sceNpCommerceDialogOpen2(const NpCommerceDialogParam2* param) {
if (!ValidateCommonDialogBaseParam(param->base)) return COMMON_DIALOG_ERROR_INVALID_ARGUMENT;
if (g_status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (!validateParam2(*param)) return COMMON_DIALOG_ERROR_INVALID_ARGUMENT;
g_userData = param->userData;
g_status = COMMON_DIALOG_STATUS_FINISHED;
return 0;
}
+20 -15
View File
@@ -17,7 +17,7 @@ int APS5_VABI sceNpCommerceDialogOpen(const NpCommerceDialogParam* param);
int APS5_VABI sceNpCommerceDialogOpen2(const NpCommerceDialogParam2* param);
int APS5_VABI sceNpCommerceDialogUpdateStatus(void);
int APS5_VABI sceNpCommerceDialogGetStatus(void);
int APS5_VABI sceNpCommerceDialogGetResult(void* result);
int APS5_VABI sceNpCommerceDialogGetResult(NpCommerceDialogResult* result);
int APS5_VABI sceNpCommerceDialogClose(void);
int APS5_VABI sceNpCommerceDialogTerminate();
}
@@ -33,15 +33,15 @@ constexpr int statusInitialized = 1;
constexpr int statusFinished = 3;
constexpr std::int32_t resultUserCanceled = 1;
void RequireCanceledResult() {
std::uint8_t result[0x20];
std::memset(result, 0x33, sizeof(result));
Require(sceNpCommerceDialogGetResult(result) == 0);
std::int32_t value = 0;
std::memcpy(&value, result, sizeof(value));
Require(value == resultUserCanceled);
Require(result[4] == 0);
Require(result[5] == 0x33);
void RequireCanceledResult(std::uint64_t userData, bool clearsReserved) {
NpCommerceDialogResult result;
std::memset(&result, 0x33, sizeof(result));
Require(sceNpCommerceDialogGetResult(&result) == resultUserCanceled);
Require(result.result == resultUserCanceled);
Require(result.authorized == 0);
Require(result.userData == userData);
for (const auto value : result.padding) Require(value == 0x33);
for (const auto value : result.reserved) Require(value == (clearsReserved ? 0 : 0x33));
}
}
@@ -56,6 +56,7 @@ int main() {
param2.base.magic = static_cast<std::uint32_t>(reinterpret_cast<std::uintptr_t>(&param2)) - 1060003575u;
param2.size = sizeof(param2);
param2.userId = USER_SERVICE_INITIAL_USER_ID;
param2.userData = 0x123456789abcdef0;
Require(sceNpCommerceDialogGetStatus() == statusNone);
Require(sceNpCommerceDialogOpen(nullptr) == static_cast<int>(0x80B8000Du));
Require(sceNpCommerceDialogOpen2(nullptr) == static_cast<int>(0x80B8000Du));
@@ -69,18 +70,18 @@ int main() {
Require(sceNpCommerceDialogTerminate() == static_cast<int>(0x80B80003u));
Require(sceNpCommerceDialogClose() == static_cast<int>(0x80B80003u));
Require(sceNpCommerceDialogGetResult(nullptr) == static_cast<int>(0x80B8000Du));
std::uint8_t result[48]{};
Require(sceNpCommerceDialogGetResult(result) == static_cast<int>(0x80B80003u));
NpCommerceDialogResult result{};
Require(sceNpCommerceDialogGetResult(&result) == static_cast<int>(0x80B80003u));
Require(sceNpCommerceDialogInitialize() == 0);
Require(sceNpCommerceDialogClose() == static_cast<int>(0x80B8000Bu));
Require(sceNpCommerceDialogGetResult(result) == static_cast<int>(0x80B80005u));
Require(sceNpCommerceDialogGetResult(&result) == static_cast<int>(0x80B80005u));
Require(sceNpCommerceDialogGetResult(nullptr) == static_cast<int>(0x80B8000Du));
Require(sceNpCommerceDialogGetStatus() == statusInitialized);
Require(sceNpCommerceDialogOpen2(&param2) == 0);
Require(sceNpCommerceDialogUpdateStatus() == statusFinished);
Require(sceNpCommerceDialogGetStatus() == statusFinished);
RequireCanceledResult();
RequireCanceledResult(param2.userData, true);
Require(sceNpCommerceDialogClose() == static_cast<int>(0x80B8000Bu));
Require(sceNpCommerceDialogGetStatus() == statusFinished);
@@ -158,6 +159,7 @@ int main() {
param2.userId = -1;
Require(sceNpCommerceDialogOpen2(&param2) == static_cast<int>(0x80B8000Au));
param2.userId = USER_SERVICE_INITIAL_USER_ID;
param2.userData = 0x123456789abcdef0;
for (std::uint32_t mode : {1000u, 1001u}) {
param.mode = mode;
param.productCount = 0;
@@ -174,7 +176,9 @@ int main() {
sdkVersion = 0x01700000;
std::memcpy(process.data() + 16, &sdkVersion, sizeof(sdkVersion));
param.argument = 3;
param.userData = 0xfedcba9876543210;
Require(sceNpCommerceDialogOpen(&param) == 0);
RequireCanceledResult(param.userData, true);
sdkVersion = 0x01600000;
std::memcpy(process.data() + 16, &sdkVersion, sizeof(sdkVersion));
param.size = 0;
@@ -183,9 +187,10 @@ int main() {
param.reserved[31] = 1;
param.argument = 7;
Require(sceNpCommerceDialogOpen(&param) == 0);
RequireCanceledResult(param.userData, false);
Require(sceNpCommerceDialogOpen2(&param2) == 0);
Require(sceNpCommerceDialogUpdateStatus() == statusFinished);
RequireCanceledResult();
RequireCanceledResult(param2.userData, false);
Require(sceNpCommerceDialogTerminate() == 0);
Require(sceNpCommerceDialogGetStatus() == statusNone);
Require(sceUserServiceTerminate() == 0);
+1 -1
View File
@@ -7,6 +7,6 @@
### Unknown function info
- [sceNpCommerceDialogInitializeInternal](../../../core/libs/prx/libSceNpCommerce/Export.cpp) (libSceNpCommerce) - its name and NID are in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceNpCommerce.c); the no-parameter prototype follows [shadPS4](https://github.com/shadps4-emu/shadPS4/blob/f68923fe807f657348e6719ce658bcbd0a2b1c72/src/core/libraries/np/np_commerce/np_commerce.cpp#L61) and is not measured on a console. It is declared without parameters solely to resolve known imports; this is not an ABI claim, and every call throws.
- [sceNpCommerceDialogOpen2](../../../core/libs/prx/libSceNpCommerce/Export.cpp): extended content combinations outside content mode 0 and content mode 1 with dialog mode 1 throw when otherwise valid. The native restriction reads process sysctl field 68; its relation to host process metadata is unresolved. Result-buffer semantics and mode-specific meanings of the option and 64-bit argument remain unresolved.
- [sceNpCommerceDialogOpen2](../../../core/libs/prx/libSceNpCommerce/Export.cpp): extended content combinations outside content mode 0 and content mode 1 with dialog mode 1 throw when otherwise valid. The native restriction reads process sysctl field 68; its relation to host process metadata is unresolved. Mode-specific meanings of the option and 64-bit argument remain unresolved.
- [sceNpCommerceDialogOpen](../../../core/libs/prx/libSceNpCommerce/Export.cpp): Product copying and service submission remain part of the cancelled UI stub.