fix(playgodialog): restore lifecycle errors and result layout

This commit is contained in:
boykopovar committed 2026-10-21 21:53:58 +03:00
1 parent 73120899a9
commit 6fdcac937c
4 files changed
+38 -21

No files matched your search

+2 -1
View File
@@ -2006,8 +2006,9 @@ union PlayGoOptionalChunk {
};
struct PlayGoDialogResult {
std::int32_t errorCode;
std::int32_t result;
std::int32_t reserved[9];
std::uint8_t reserved[32];
};
struct RudpPollEvent {
+18 -10
View File
@@ -1,4 +1,6 @@
#include <atomic>
#include <algorithm>
#include <iterator>
#include <cstdint>
#include <cstddef>
#include <cstring>
@@ -6,6 +8,8 @@
#include "prx/libc/include/General.hpp"
static_assert(sizeof(PlayGoDialogResult) == 40);
static_assert(offsetof(PlayGoDialogResult, result) == 4);
static_assert(offsetof(PlayGoDialogResult, reserved) == 8);
namespace {
@@ -15,11 +19,13 @@ constexpr std::int32_t STATUS_RUNNING = 2;
constexpr std::int32_t STATUS_FINISHED = 3;
constexpr std::int32_t RESULT_OK = 0;
constexpr std::int32_t ERROR_ARG_NULL = static_cast<std::int32_t>(0x80B8000Du);
constexpr std::int32_t ERROR_NOT_RUNNING = static_cast<std::int32_t>(0x80B8000Bu);
constexpr std::int32_t ERROR_NOT_INITIALIZED = static_cast<std::int32_t>(0x80ED0001);
constexpr std::int32_t ERROR_ALREADY_INITIALIZED = static_cast<std::int32_t>(0x80ED0002);
constexpr std::int32_t ERROR_PARAM_INVALID = static_cast<std::int32_t>(0x80ED0003);
constexpr std::int32_t ERROR_INVALID_STATE = static_cast<std::int32_t>(0x80ED0005);
constexpr std::int32_t ERROR_NOT_INITIALIZED = static_cast<std::int32_t>(0x80B80003);
constexpr std::int32_t ERROR_ALREADY_INITIALIZED = static_cast<std::int32_t>(0x80B80004);
constexpr std::int32_t ERROR_PARAM_INVALID = static_cast<std::int32_t>(0x80B8000A);
constexpr std::int32_t ERROR_INVALID_STATE = static_cast<std::int32_t>(0x80B80007);
constexpr std::int32_t COMMON_DIALOG_ERROR_NOT_FINISHED = static_cast<std::int32_t>(0x80B80005u);
std::atomic<int> g_status{STATUS_NONE};
@@ -44,7 +50,8 @@ int APS5_VABI scePlayGoDialogTerminate(void) {
}
int APS5_VABI scePlayGoDialogOpen(const void* param) {
if (!param) return ERROR_PARAM_INVALID;
if (!param) return ERROR_ARG_NULL;
if (g_status.load() == STATUS_NONE) return ERROR_NOT_INITIALIZED;
int expected = STATUS_INITIALIZED;
if (!g_status.compare_exchange_strong(expected, STATUS_FINISHED)) {
expected = STATUS_FINISHED;
@@ -55,6 +62,7 @@ int APS5_VABI scePlayGoDialogOpen(const void* param) {
int APS5_VABI scePlayGoDialogClose(void) {
if (g_status.load() == STATUS_NONE) return ERROR_NOT_INITIALIZED;
if (g_status.load() != STATUS_RUNNING) return ERROR_NOT_RUNNING;
g_status.store(STATUS_FINISHED);
return 0;
}
@@ -65,13 +73,13 @@ int APS5_VABI scePlayGoDialogUpdateStatus(void) {
return g_status.load();
}
int APS5_VABI scePlayGoDialogGetResult(void* result) {
int APS5_VABI scePlayGoDialogGetResult(PlayGoDialogResult* result) {
if (result == nullptr) return ERROR_ARG_NULL;
if (!std::all_of(std::begin(result->reserved), std::end(result->reserved), [](std::uint8_t value) { return value == 0; })) return ERROR_PARAM_INVALID;
if (g_status.load() == STATUS_NONE) return ERROR_NOT_INITIALIZED;
if (!result) return ERROR_PARAM_INVALID;
if (g_status.load() != STATUS_FINISHED) return COMMON_DIALOG_ERROR_NOT_FINISHED;
auto* r = static_cast<PlayGoDialogResult*>(result);
std::memset(r, 0, sizeof(*r));
r->result = RESULT_OK;
*result = {};
result->result = RESULT_OK;
return 0;
}
+17 -9
View File
@@ -11,27 +11,30 @@ int APS5_VABI scePlayGoDialogOpen(const void* param);
int APS5_VABI scePlayGoDialogClose(void);
int APS5_VABI scePlayGoDialogUpdateStatus(void);
int APS5_VABI scePlayGoDialogGetStatus(void);
int APS5_VABI scePlayGoDialogGetResult(void* result);
int APS5_VABI scePlayGoDialogGetResult(PlayGoDialogResult* result);
}
static void Require(bool value) { if (!value) std::abort(); }
int main() {
constexpr std::int32_t notInitialized = static_cast<std::int32_t>(0x80ED0001);
constexpr std::int32_t alreadyInitialized = static_cast<std::int32_t>(0x80ED0002);
constexpr std::int32_t paramInvalid = static_cast<std::int32_t>(0x80ED0003);
constexpr std::int32_t invalidState = static_cast<std::int32_t>(0x80ED0005);
constexpr std::int32_t notInitialized = static_cast<std::int32_t>(0x80B80003);
constexpr std::int32_t alreadyInitialized = static_cast<std::int32_t>(0x80B80004);
constexpr std::int32_t paramInvalid = static_cast<std::int32_t>(0x80B8000D);
constexpr std::int32_t notFinished = static_cast<std::int32_t>(0x80B80005u);
Require(scePlayGoDialogGetStatus() == 0);
Require(scePlayGoDialogTerminate() == notInitialized);
Require(scePlayGoDialogClose() == notInitialized);
Require(scePlayGoDialogOpen(nullptr) == paramInvalid);
Require(scePlayGoDialogGetResult(nullptr) == notInitialized);
Require(scePlayGoDialogGetResult(nullptr) == paramInvalid);
const int openParam = 1;
Require(scePlayGoDialogOpen(&openParam) == invalidState);
Require(scePlayGoDialogOpen(&openParam) == notInitialized);
PlayGoDialogResult early{};
Require(scePlayGoDialogGetResult(&early) == notInitialized);
early.reserved[31] = 1;
Require(scePlayGoDialogGetResult(&early) == static_cast<std::int32_t>(0x80B8000Au));
Require(scePlayGoDialogInitialize() == 0);
Require(scePlayGoDialogGetStatus() == 1);
Require(scePlayGoDialogInitialize() == alreadyInitialized);
@@ -47,8 +50,13 @@ int main() {
PlayGoDialogResult result{};
Require(scePlayGoDialogGetResult(&result) == 0);
Require(result.result == 0);
Require(scePlayGoDialogClose() == 0);
Require(result.result == 0 && result.errorCode == 0);
result.errorCode = 7;
result.result = 9;
result.reserved[0] = 1;
Require(scePlayGoDialogGetResult(&result) == static_cast<std::int32_t>(0x80B8000Au));
Require(result.errorCode == 7 && result.result == 9 && result.reserved[0] == 1);
Require(scePlayGoDialogClose() == static_cast<std::int32_t>(0x80B8000Bu));
Require(scePlayGoDialogTerminate() == 0);
Require(scePlayGoDialogGetStatus() == 0);
Require(scePlayGoDialogTerminate() == notInitialized);
+1 -1
View File
@@ -2,4 +2,4 @@
### Unknown function info
- [scePlayGoDialogGetResult](../../../core/libs/prx/libScePlayGoDialog/Export.cpp) (libScePlayGoDialog) - checks that the dialog has reached STATUS_FINISHED and returns 0x80B80005 (COMMON_DIALOG_ERROR_NOT_FINISHED) when called before the dialog completes, following the other common dialog modules in the tree (MsgDialog, SigninDialog, PlayerSelectionDialog, SaveDataDialog). shadPS4's scePlayGoDialogGetResult is a dummy that always returns OK and provides no evidence for either value; the exact return code and intermediate state check have not been verified against a real hardware trace or title measurement.
- [scePlayGoDialogOpen](../../../core/libs/prx/libScePlayGoDialog/Export.cpp) does not validate or copy the native nested parameters or query download progress. The host UI stub immediately reports completion; service-driven failures and transitions remain unimplemented.