mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
Merge pull request #9524 from AlxcBTW/pr/game-live-streaming-offline-settings
feat(libSceGameLiveStreaming): answer offline setting and feedback calls locally
This commit is contained in:
4 files changed
+293
-60
No files matched your search
@@ -15,6 +15,27 @@ static constexpr int ErrorInvalidArgument = static_cast<int>(0x80A00002);
|
||||
static constexpr int ErrorAlreadyInitialized = static_cast<int>(0x80A00003);
|
||||
static constexpr int ErrorNotInitialized = static_cast<int>(0x80A00004);
|
||||
static constexpr std::size_t ProgramInfoSize = 0x134C;
|
||||
static constexpr std::size_t MaxMetadataLength = 240;
|
||||
static constexpr std::size_t MaxPresetDescriptionLength = 720;
|
||||
static constexpr std::size_t MaxInvitationSessionIdLength = 45;
|
||||
static constexpr std::size_t MaxSocialMessageLength = 360;
|
||||
static constexpr std::size_t MaxSpoilerTags = 16;
|
||||
static constexpr std::size_t MaxPresetCommands = 5;
|
||||
|
||||
static bool ValidFeedbackType(int type) {
|
||||
return type >= 1 && type <= 3;
|
||||
}
|
||||
|
||||
static bool ValidString(const char* text, std::size_t maxLength) {
|
||||
return text != nullptr && std::memchr(text, 0, maxLength + 1) != nullptr;
|
||||
}
|
||||
|
||||
static bool AllZero(const std::uint8_t* bytes, std::size_t size) {
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
if (bytes[i] != 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static_assert(sizeof(GameLiveStreamingStatus2) == 72);
|
||||
|
||||
@@ -87,13 +108,15 @@ int APS5_VABI sceGameLiveStreamingScreenSetMode(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingPermitLiveStreaming(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingPermitLiveStreaming(bool permit) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetMaxBitrate(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetMaxBitrate(std::uint32_t bitrate) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -102,68 +125,98 @@ int APS5_VABI sceGameLiveStreamingGetCurrentStatus(GameLiveStreamingStatus* stat
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingEnableSocialFeedback(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingEnableSocialFeedback(bool enable) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(int type, std::uint32_t* count) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (count == nullptr || !ValidFeedbackType(type)) return ErrorInvalidArgument;
|
||||
*count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessages(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessages(int type, size_t capacity, GameLiveStreamingFeedbackMessage* messages, size_t* acquired) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (messages == nullptr || acquired == nullptr || !ValidFeedbackType(type)) return ErrorInvalidArgument;
|
||||
*acquired = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingPermitServerSideRecording(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingPermitServerSideRecording(bool permit) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetMetadata(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetMetadata(const char* metadata) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (!ValidString(metadata, MaxMetadataLength)) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetSpoilerTag(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetSpoilerTag(size_t count, const GameLiveStreamingSpoilerTag* tags) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (tags == nullptr || count > MaxSpoilerTags) return ErrorInvalidArgument;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (!AllZero(tags[i].reserved, sizeof(tags[i].reserved))) return ErrorInvalidArgument;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingClearSpoilerTag(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(size_t count, const GameLiveStreamingPresetCommand* commands) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (commands == nullptr || count > MaxPresetCommands) return ErrorInvalidArgument;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (!AllZero(commands[i].reserved, sizeof(commands[i].reserved))) return ErrorInvalidArgument;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingClearPresetSocialFeedbackCommands(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(const char* description) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (!ValidString(description, MaxPresetDescriptionLength)) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingClearSocialFeedbackMessages(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingClearSocialFeedbackMessages(int type) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (!ValidFeedbackType(type)) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingPostSocialMessage(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingPostSocialMessage(const char* message) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (!ValidString(message, MaxSocialMessageLength)) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetCameraFrameSetting(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetCameraFrameSetting(const GameLiveStreamingCameraFrameSetting* setting) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (setting == nullptr || !AllZero(setting->reserved, sizeof(setting->reserved))) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -177,8 +230,10 @@ int APS5_VABI sceGameLiveStreamingSetDefaultServiceProviderPermission(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceGameLiveStreamingSetInvitationSessionId(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
int APS5_VABI sceGameLiveStreamingSetInvitationSessionId(const char* sessionId) {
|
||||
std::lock_guard lock(g_mutex);
|
||||
if (!g_initialized) return ErrorNotInitialized;
|
||||
if (!ValidString(sessionId, MaxInvitationSessionIdLength)) return ErrorInvalidArgument;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,31 @@
|
||||
|
||||
struct GameLiveStreamingProgramInfo;
|
||||
|
||||
struct GameLiveStreamingSpoilerTag {
|
||||
char text[193];
|
||||
std::uint8_t reserved[31];
|
||||
};
|
||||
|
||||
static_assert(offsetof(GameLiveStreamingSpoilerTag, reserved) == 193);
|
||||
static_assert(sizeof(GameLiveStreamingSpoilerTag) == 224);
|
||||
|
||||
struct GameLiveStreamingPresetCommand {
|
||||
std::uint8_t body[197];
|
||||
std::uint8_t reserved[31];
|
||||
};
|
||||
|
||||
static_assert(offsetof(GameLiveStreamingPresetCommand, reserved) == 197);
|
||||
static_assert(sizeof(GameLiveStreamingPresetCommand) == 228);
|
||||
|
||||
struct GameLiveStreamingCameraFrameSetting {
|
||||
std::uint8_t head[9];
|
||||
std::uint8_t reserved[31];
|
||||
};
|
||||
|
||||
static_assert(offsetof(GameLiveStreamingCameraFrameSetting, reserved) == 9);
|
||||
|
||||
struct GameLiveStreamingFeedbackMessage;
|
||||
|
||||
struct GameLiveStreamingStatus {
|
||||
std::uint8_t opaque00[12];
|
||||
std::uint8_t reserved[60];
|
||||
@@ -38,25 +63,25 @@ int APS5_VABI sceGameLiveStreamingScreenCloseSeparateMode(void);
|
||||
int APS5_VABI sceGameLiveStreamingScreenConfigureSeparateMode(void);
|
||||
int APS5_VABI sceGameLiveStreamingScreenOpenSeparateMode(void);
|
||||
int APS5_VABI sceGameLiveStreamingScreenSetMode(void);
|
||||
int APS5_VABI sceGameLiveStreamingPermitLiveStreaming(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetMaxBitrate(void);
|
||||
int APS5_VABI sceGameLiveStreamingPermitLiveStreaming(bool permit);
|
||||
int APS5_VABI sceGameLiveStreamingSetMaxBitrate(std::uint32_t bitrate);
|
||||
int APS5_VABI sceGameLiveStreamingGetCurrentStatus(GameLiveStreamingStatus* status);
|
||||
int APS5_VABI sceGameLiveStreamingEnableSocialFeedback(void);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(void);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessages(void);
|
||||
int APS5_VABI sceGameLiveStreamingPermitServerSideRecording(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetMetadata(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetSpoilerTag(void);
|
||||
int APS5_VABI sceGameLiveStreamingEnableSocialFeedback(bool enable);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessagesCount(int type, std::uint32_t* count);
|
||||
int APS5_VABI sceGameLiveStreamingGetSocialFeedbackMessages(int type, size_t capacity, GameLiveStreamingFeedbackMessage* messages, size_t* acquired);
|
||||
int APS5_VABI sceGameLiveStreamingPermitServerSideRecording(bool permit);
|
||||
int APS5_VABI sceGameLiveStreamingSetMetadata(const char* metadata);
|
||||
int APS5_VABI sceGameLiveStreamingSetSpoilerTag(size_t count, const GameLiveStreamingSpoilerTag* tags);
|
||||
int APS5_VABI sceGameLiveStreamingClearSpoilerTag(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommands(size_t count, const GameLiveStreamingPresetCommand* commands);
|
||||
int APS5_VABI sceGameLiveStreamingClearPresetSocialFeedbackCommands(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(void);
|
||||
int APS5_VABI sceGameLiveStreamingClearSocialFeedbackMessages(void);
|
||||
int APS5_VABI sceGameLiveStreamingPostSocialMessage(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetCameraFrameSetting(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(const char* description);
|
||||
int APS5_VABI sceGameLiveStreamingClearSocialFeedbackMessages(int type);
|
||||
int APS5_VABI sceGameLiveStreamingPostSocialMessage(const char* message);
|
||||
int APS5_VABI sceGameLiveStreamingSetCameraFrameSetting(const GameLiveStreamingCameraFrameSetting* setting);
|
||||
int APS5_VABI sceGameLiveStreamingSetServiceProviderPermission(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetDefaultServiceProviderPermission(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetInvitationSessionId(void);
|
||||
int APS5_VABI sceGameLiveStreamingSetInvitationSessionId(const char* sessionId);
|
||||
int APS5_VABI sceGameLiveStreamingStartGenerateStandbyScreenResource(void);
|
||||
int APS5_VABI sceGameLiveStreamingStopGenerateStandbyScreenResource(void);
|
||||
int APS5_VABI sceGameLiveStreamingRegisterCallback(void);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <span>
|
||||
|
||||
static_assert(sizeof(GameLiveStreamingStatus2) == 72);
|
||||
@@ -26,6 +27,163 @@ bool EnableThrowsNotInitialized(bool isEnableLiveStreaming) {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr int kInvalidArgument = static_cast<int>(0x80A00002);
|
||||
|
||||
GameLiveStreamingFeedbackMessage* AsMessages(std::array<std::uint8_t, 256>& buffer) {
|
||||
return reinterpret_cast<GameLiveStreamingFeedbackMessage*>(buffer.data());
|
||||
}
|
||||
|
||||
void CheckLifecycleFirst() {
|
||||
constexpr int notInitialized = static_cast<int>(0x80A00004);
|
||||
GameLiveStreamingSpoilerTag tag{};
|
||||
GameLiveStreamingPresetCommand preset{};
|
||||
GameLiveStreamingCameraFrameSetting camera{};
|
||||
std::array<std::uint8_t, 256> messages{};
|
||||
std::uint32_t count = 0x55;
|
||||
std::size_t acquired = 0x55;
|
||||
Require(sceGameLiveStreamingPermitLiveStreaming(true) == notInitialized);
|
||||
Require(sceGameLiveStreamingPermitServerSideRecording(false) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetMaxBitrate(6000) == notInitialized);
|
||||
Require(sceGameLiveStreamingEnableSocialFeedback(true) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetMetadata(nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetMetadata("metadata") == notInitialized);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(0, nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(1, &tag) == notInitialized);
|
||||
Require(sceGameLiveStreamingClearSpoilerTag() == notInitialized);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(0, nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(1, &preset) == notInitialized);
|
||||
Require(sceGameLiveStreamingClearPresetSocialFeedbackCommands() == notInitialized);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription(nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(&camera) == notInitialized);
|
||||
Require(sceGameLiveStreamingSetInvitationSessionId(nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessagesCount(0, nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessagesCount(1, &count) == notInitialized);
|
||||
Require(count == 0x55);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(0, 1, nullptr, nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(1, 1, AsMessages(messages), &acquired) == notInitialized);
|
||||
Require(acquired == 0x55);
|
||||
Require(sceGameLiveStreamingClearSocialFeedbackMessages(0) == notInitialized);
|
||||
Require(sceGameLiveStreamingClearSocialFeedbackMessages(1) == notInitialized);
|
||||
Require(sceGameLiveStreamingPostSocialMessage(nullptr) == notInitialized);
|
||||
Require(sceGameLiveStreamingPostSocialMessage("message") == notInitialized);
|
||||
}
|
||||
|
||||
void CheckString(int (APS5_VABI *call)(const char*), std::size_t limit) {
|
||||
Require(call(nullptr) == kInvalidArgument);
|
||||
Require(call("") == 0);
|
||||
Require(call(std::string(limit, 'a').c_str()) == 0);
|
||||
Require(call(std::string(limit + 1, 'a').c_str()) == kInvalidArgument);
|
||||
Require(call(std::string(limit + 100, 'a').c_str()) == kInvalidArgument);
|
||||
}
|
||||
|
||||
void CheckStrings() {
|
||||
CheckString(sceGameLiveStreamingSetMetadata, 240);
|
||||
CheckString(sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription, 720);
|
||||
CheckString(sceGameLiveStreamingSetInvitationSessionId, 45);
|
||||
CheckString(sceGameLiveStreamingPostSocialMessage, 360);
|
||||
}
|
||||
|
||||
void CheckFeedbackTypes() {
|
||||
std::array<std::uint8_t, 256> messages{};
|
||||
for (const int type : {-1, 0, 4, 5, 0x7fffffff}) {
|
||||
std::uint32_t count = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessagesCount(type, &count) == kInvalidArgument);
|
||||
Require(count == 0xdeadbeef);
|
||||
std::size_t acquired = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(type, 1, AsMessages(messages), &acquired) == kInvalidArgument);
|
||||
Require(acquired == 0xdeadbeef);
|
||||
Require(sceGameLiveStreamingClearSocialFeedbackMessages(type) == kInvalidArgument);
|
||||
}
|
||||
for (const int type : {1, 2, 3}) {
|
||||
std::uint32_t count = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessagesCount(type, &count) == 0);
|
||||
Require(count == 0);
|
||||
messages.fill(0xaa);
|
||||
std::size_t acquired = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(type, 1, AsMessages(messages), &acquired) == 0);
|
||||
Require(acquired == 0);
|
||||
for (const std::uint8_t byte : messages) Require(byte == 0xaa);
|
||||
acquired = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(type, 0, AsMessages(messages), &acquired) == 0);
|
||||
Require(acquired == 0);
|
||||
Require(sceGameLiveStreamingClearSocialFeedbackMessages(type) == 0);
|
||||
}
|
||||
std::size_t acquired = 0xdeadbeef;
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(1, 0, nullptr, &acquired) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(1, 1, nullptr, &acquired) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessages(1, 1, AsMessages(messages), nullptr) == kInvalidArgument);
|
||||
Require(acquired == 0xdeadbeef);
|
||||
Require(sceGameLiveStreamingGetSocialFeedbackMessagesCount(1, nullptr) == kInvalidArgument);
|
||||
}
|
||||
|
||||
void CheckArrays() {
|
||||
GameLiveStreamingSpoilerTag tags[17]{};
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(0, nullptr) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(1, nullptr) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(0, tags) == 0);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(1, tags) == 0);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(16, tags) == 0);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(17, tags) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(0x1000, tags) == kInvalidArgument);
|
||||
for (const std::size_t index : {0u, 15u}) {
|
||||
for (const std::size_t byte : {0u, 15u, 30u}) {
|
||||
tags[index].reserved[byte] = 1;
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(16, tags) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(index, tags) == 0);
|
||||
tags[index].reserved[byte] = 0;
|
||||
}
|
||||
}
|
||||
tags[16].reserved[0] = 1;
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(16, tags) == 0);
|
||||
tags[0].text[192] = 'x';
|
||||
Require(sceGameLiveStreamingSetSpoilerTag(1, tags) == 0);
|
||||
Require(sceGameLiveStreamingClearSpoilerTag() == 0);
|
||||
Require(sceGameLiveStreamingClearSpoilerTag() == 0);
|
||||
|
||||
GameLiveStreamingPresetCommand presets[6]{};
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(0, nullptr) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(1, nullptr) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(0, presets) == 0);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(5, presets) == 0);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(6, presets) == kInvalidArgument);
|
||||
for (const std::size_t index : {0u, 4u}) {
|
||||
for (const std::size_t byte : {0u, 30u}) {
|
||||
presets[index].reserved[byte] = 1;
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(5, presets) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(index, presets) == 0);
|
||||
presets[index].reserved[byte] = 0;
|
||||
}
|
||||
}
|
||||
presets[5].reserved[0] = 1;
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(5, presets) == 0);
|
||||
presets[0].body[196] = 1;
|
||||
Require(sceGameLiveStreamingSetPresetSocialFeedbackCommands(5, presets) == 0);
|
||||
Require(sceGameLiveStreamingClearPresetSocialFeedbackCommands() == 0);
|
||||
Require(sceGameLiveStreamingClearPresetSocialFeedbackCommands() == 0);
|
||||
|
||||
GameLiveStreamingCameraFrameSetting camera{};
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(nullptr) == kInvalidArgument);
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(&camera) == 0);
|
||||
camera.head[8] = 1;
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(&camera) == 0);
|
||||
camera.head[8] = 0;
|
||||
for (const std::size_t byte : {0u, 15u, 30u}) {
|
||||
camera.reserved[byte] = 1;
|
||||
Require(sceGameLiveStreamingSetCameraFrameSetting(&camera) == kInvalidArgument);
|
||||
camera.reserved[byte] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckScalars() {
|
||||
for (const bool value : {true, false}) {
|
||||
Require(sceGameLiveStreamingPermitLiveStreaming(value) == 0);
|
||||
Require(sceGameLiveStreamingPermitServerSideRecording(value) == 0);
|
||||
Require(sceGameLiveStreamingEnableSocialFeedback(value) == 0);
|
||||
}
|
||||
for (const std::uint32_t bitrate : {0u, 6000u, 0xffffffffu}) Require(sceGameLiveStreamingSetMaxBitrate(bitrate) == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
@@ -35,6 +193,7 @@ int main() {
|
||||
Require(sceGameLiveStreamingTerminate() == notInitialized);
|
||||
Require(sceGameLiveStreamingGetCurrentStatus2(nullptr) == notInitialized);
|
||||
Require(EnableThrowsNotInitialized(true));
|
||||
CheckLifecycleFirst();
|
||||
for (const std::size_t size : {0u, 1u, 0x3fffu, 0x4001u, 0x100000u}) Require(sceGameLiveStreamingInitialize(size) == invalidArgument);
|
||||
Require(sceGameLiveStreamingInitialize(0x4000) == 0);
|
||||
Require(sceGameLiveStreamingEnableLiveStreaming(true) == 0);
|
||||
@@ -66,8 +225,14 @@ int main() {
|
||||
Require(programInfo[i] == (i < 0x134C ? 0 : 0x7f));
|
||||
}
|
||||
|
||||
CheckScalars();
|
||||
CheckStrings();
|
||||
CheckFeedbackTypes();
|
||||
CheckArrays();
|
||||
|
||||
Require(sceGameLiveStreamingEnableLiveStreaming(false) == 0);
|
||||
Require(sceGameLiveStreamingTerminate() == 0);
|
||||
CheckLifecycleFirst();
|
||||
Require(EnableThrowsNotInitialized(false));
|
||||
std::memset(&status, 0x7f, sizeof(status));
|
||||
Require(sceGameLiveStreamingGetCurrentStatus2(&status) == notInitialized);
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
- [sceGameLiveStreamingGetCurrentStatus2](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) - the supplied module confirms the 72-byte layout and inactive status (user -1, remaining bytes zero). Live service counters, active-user changes and broadcast-resolution conversion are unimplemented. In the 25 instructions after their one call, PPSA01494, PPSA30839 and PPSA31162 read `isOnAir` (the byte at 4) and `spectatorCounts` (the word at 8), so those two are the fields these titles act on; here they stay false and 0.
|
||||
- [sceGameLiveStreamingGetProgramInfo](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - the PS5 13.60 module clears the 0x134C-byte program info, asks the system service for its first 0xFD4 bytes and returns `0x80A00002` for a null pointer and `0x80A00004` before initialization. With nothing broadcast here the info stays zero, which assumes the service reports an empty program when nothing is on air; the field layout is unknown. Two titles (PPSA03001 at 0x1ad86b4, PPSA07426 at 0xe89594) disassembled for this entry pass the address of a stack buffer with no store into it between the start of the block and the call; for a result other than 0 they do not read it, for 0 they copy three text fields at offsets 0, 0x802 and 0xC03, and they do not tell `0x80A00002` from `0x80A00004`. The buffer size is not shown.
|
||||
|
||||
### Silent stubs
|
||||
|
||||
- [sceGameLiveStreamingPermitLiveStreaming](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) - this and fifteen related setting, feedback and message calls (see `Api.hpp`) validate their arguments and store nothing, as no broadcast is ever on air. The checks (not initialized, null pointers, feedback type 1-3, string lengths 240/720/45/360, at most 16 spoiler tags and 5 preset commands, zero reserved tails in the 224-byte spoiler tag, 228-byte preset command and camera setting) come from a report on #9524 that ran each function of the firmware 13.42 module with the service call stubbed. The order between argument checks, the camera setting size and the other struct fields are not measured, nor what the service returns after validation: the calls return 0 and queries report zero messages.
|
||||
|
||||
### Unknown function info
|
||||
|
||||
- [sceGameLiveStreamingScreenInitialize](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
@@ -16,25 +20,9 @@
|
||||
- [sceGameLiveStreamingScreenConfigureSeparateMode](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingScreenOpenSeparateMode](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingScreenSetMode](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingPermitLiveStreaming](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetMaxBitrate](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingGetCurrentStatus](../../../core/libs/prx/libSceGameLiveStreaming/include/Api.hpp) - still throws; the meaning, division and SDK types of the first 12 bytes remain unknown. In the supplied `libSceGameLiveStreaming.sprx`, export `CoPMx369EqM` at 0x1810 takes one output pointer, clears 72 bytes, obtains service command 9's status, copies its first 12 bytes and clears bytes 0x0C..0x47. `GameLiveStreamingStatus` exposes this byte storage without assuming the `GetCurrentStatus2` field layout or SDK alignment. The decompiler's extra SIMD parameter is not an input: the assembly initializes the register before use.
|
||||
- [sceGameLiveStreamingEnableSocialFeedback](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingGetSocialFeedbackMessagesCount](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingGetSocialFeedbackMessages](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingPermitServerSideRecording](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetMetadata](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetSpoilerTag](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingClearSpoilerTag](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetPresetSocialFeedbackCommands](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingClearPresetSocialFeedbackCommands](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetPresetSocialFeedbackCommandsDescription](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingClearSocialFeedbackMessages](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingPostSocialMessage](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetCameraFrameSetting](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetServiceProviderPermission](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetDefaultServiceProviderPermission](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingSetInvitationSessionId](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingStartGenerateStandbyScreenResource](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingStopGenerateStandbyScreenResource](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
- [sceGameLiveStreamingRegisterCallback](../../../core/libs/prx/libSceGameLiveStreaming/Export.cpp) (libSceGameLiveStreaming) - unknown signature
|
||||
|
||||
Reference in new issue
Block a user