Files
AnyPS5/core/libs/tests/GuestGameUpdate.cpp
T
KernelPanicNTandClaude Opus 5.5 f31479bb0c fix(libSceGameUpdate): return the module's lifecycle and argument errors
Following the PS5 3.20 module as read by prosper:

- a second sceGameUpdateInitialize returns 0x80412802, and
  sceGameUpdateTerminate without initialization returns 0x80412801;
- sceGameUpdateCreateRequest returns 0x80412801 before initialization;
- sceGameUpdateCheck checks the id, the pointers, the 0x30 sizes and
  the zero option and reserved words before initialization;
- sceGameUpdateAbortRequest and sceGameUpdateDeleteRequest return
  0x80412805 for an id that was never created instead of success;
- sceGameUpdateGetAddcontLatestVersion checks its pointers before
  initialization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:36:53 +00:00

100 lines
4.3 KiB
C++

#include "SceTypes.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <initializer_list>
#include <stdexcept>
extern "C" {
int APS5_VABI sceGameUpdateInitialize(void);
int APS5_VABI sceGameUpdateTerminate(void);
int APS5_VABI sceGameUpdateGetAddcontLatestVersion(std::uint32_t, const void*, GameUpdateAddcontVersionInfo*);
int APS5_VABI sceGameUpdateCreateRequest(void);
int APS5_VABI sceGameUpdateCheck(int, const GameUpdateCheckParam*, GameUpdateCheckResult*);
int APS5_VABI sceGameUpdateAbortRequest(int);
int APS5_VABI sceGameUpdateDeleteRequest(int);
}
static void Require(bool value) { if (!value) std::abort(); }
static void TestRequestArguments(int notInitialized, int invalidArgument, int invalidSize, int notFound) {
GameUpdateCheckParam param{};
param.size = sizeof(param);
GameUpdateCheckResult result{};
result.size = sizeof(result);
constexpr int requestId = 0x20000000;
for (int id : {0, -1}) {
Require(sceGameUpdateCheck(id, nullptr, nullptr) == notFound);
Require(sceGameUpdateAbortRequest(id) == notFound);
Require(sceGameUpdateDeleteRequest(id) == notFound);
}
Require(sceGameUpdateCheck(requestId, nullptr, &result) == invalidArgument);
Require(sceGameUpdateCheck(requestId, &param, nullptr) == invalidArgument);
param.size = sizeof(param) - 1;
Require(sceGameUpdateCheck(requestId, &param, &result) == invalidSize);
param.size = sizeof(param);
result.size = sizeof(result) + 8;
Require(sceGameUpdateCheck(requestId, &param, &result) == invalidSize);
result.size = sizeof(result);
param.option = 1;
Require(sceGameUpdateCheck(requestId, &param, &result) == invalidArgument);
param.option = 0;
param.reserved[8] = 1;
Require(sceGameUpdateCheck(requestId, &param, &result) == invalidArgument);
param.reserved[8] = 0;
Require(sceGameUpdateCreateRequest() == notInitialized);
Require(sceGameUpdateCheck(requestId, &param, &result) == notInitialized);
Require(sceGameUpdateAbortRequest(requestId) == notInitialized);
Require(sceGameUpdateDeleteRequest(requestId) == notInitialized);
Require(sceGameUpdateInitialize() == 0);
Require(sceGameUpdateCheck(requestId, &param, &result) == notFound);
Require(sceGameUpdateAbortRequest(requestId) == notFound);
Require(sceGameUpdateDeleteRequest(requestId) == notFound);
Require(sceGameUpdateTerminate() == 0);
}
int main() {
constexpr int notInitialized = static_cast<int>(0x80412801);
constexpr int invalidArgument = static_cast<int>(0x80412803);
constexpr int invalidSize = static_cast<int>(0x80412804);
static_assert(sizeof(GameUpdateAddcontVersionInfo) == 0x30);
const std::uint8_t label[16] = {};
GameUpdateAddcontVersionInfo info{};
info.size = sizeof(info);
constexpr int alreadyInitialized = static_cast<int>(0x80412802);
constexpr int notFound = static_cast<int>(0x80412805);
Require(sceGameUpdateTerminate() == notInitialized);
TestRequestArguments(notInitialized, invalidArgument, invalidSize, notFound);
Require(sceGameUpdateGetAddcontLatestVersion(0, label, &info) == notInitialized);
Require(sceGameUpdateGetAddcontLatestVersion(0, label, nullptr) == invalidArgument);
Require(sceGameUpdateGetAddcontLatestVersion(0, nullptr, &info) == invalidArgument);
Require(sceGameUpdateInitialize() == 0);
Require(sceGameUpdateInitialize() == alreadyInitialized);
Require(sceGameUpdateGetAddcontLatestVersion(0, label, nullptr) == invalidArgument);
Require(sceGameUpdateGetAddcontLatestVersion(0, nullptr, &info) == invalidArgument);
info.size = sizeof(info) - 1;
Require(sceGameUpdateGetAddcontLatestVersion(0, label, &info) == invalidSize);
std::memset(&info, 0xAB, sizeof(info));
info.size = sizeof(info) + 8;
Require(sceGameUpdateGetAddcontLatestVersion(0, label, &info) == 0);
Require(info.size == sizeof(info) + 8 && !info.found);
const auto* bytes = reinterpret_cast<const std::uint8_t*>(&info);
for (std::size_t i = sizeof(info.size); i < sizeof(info); ++i) Require(bytes[i] == 0);
Require(sceGameUpdateTerminate() == 0);
Require(sceGameUpdateTerminate() == notInitialized);
info.size = sizeof(info);
Require(sceGameUpdateGetAddcontLatestVersion(0, label, &info) == notInitialized);
}