PRAGMATA (PPSA02530) calls it after sceRazorCpuSync and stops on main with "sceNpEntitlementAccessGetGameTrialsFlag not implemented". From called once; I logged four register values but cannot tell which are arguments. Answering 0 without writing anything carried on." Killing Floor 3 (PPSA08427) and RE4 also import it. The title is reported as a full game, not a game trial: 0 is written to the uint32_t output and 0 returned; a null pointer returns 0x817D0002. Signature, value, one-word write and error follow sharpemu src/SharpEmu.Libs/Np/NpEntitlementAccessExports.cs:98-116 and its test NpEntitlementAccessExportsTests.cs:16-36 (a2983692930564815a77f81e74c151268f5b935f), used as a source of facts; 0x817D0002 is also the parameter error of KytyPS5, prosper and sceNpEntitlementAccessGetEntitlementKey here. The library has no initialization state, so none is checked. The NID y7JD1gfwyfA hashes from the name and is in aerolib. Unverified points are in TechnicalDebt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
100 lines
4.7 KiB
C++
100 lines
4.7 KiB
C++
#include "SceTypes.hpp"
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <stdexcept>
|
|
#include <string_view>
|
|
|
|
extern "C" {
|
|
int APS5_VABI sceHttpSetCookieEnabled(int, int);
|
|
int APS5_VABI sceHttpSendRequest(int, const void*, std::size_t);
|
|
int APS5_VABI sceNpEntitlementAccessGetEntitlementKey(
|
|
std::uint32_t, const NpUnifiedEntitlementLabel*, NpEntitlementAccessEntitlementKey*);
|
|
int APS5_VABI sceNpEntitlementAccessGetGameTrialsFlag(std::uint32_t*);
|
|
int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfoList();
|
|
int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfoList();
|
|
int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfoList();
|
|
int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfoList();
|
|
int APS5_VABI sceNpEntitlementAccessRequestUnifiedEntitlementInfo();
|
|
int APS5_VABI sceNpEntitlementAccessPollUnifiedEntitlementInfo();
|
|
int APS5_VABI sceNpEntitlementAccessRequestServiceEntitlementInfo();
|
|
int APS5_VABI sceNpEntitlementAccessPollServiceEntitlementInfo();
|
|
int APS5_VABI sceRudpInit_nid_postfix(void*, int);
|
|
int APS5_VABI sceRudpActivate();
|
|
int APS5_VABI sceRudpGetStatus(void*, std::size_t);
|
|
int APS5_VABI sceRudpTerminate();
|
|
}
|
|
|
|
static void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
int main() {
|
|
constexpr int invalidValue = static_cast<int>(0x804311FE);
|
|
constexpr int network = static_cast<int>(0x80431063);
|
|
Require(sceHttpSetCookieEnabled(1, 0) == 0);
|
|
Require(sceHttpSendRequest(1, nullptr, 0) == network);
|
|
bool cookieUnsupported = false;
|
|
try {
|
|
sceHttpSetCookieEnabled(1, 1);
|
|
} catch (const std::runtime_error& error) {
|
|
cookieUnsupported = std::string_view(error.what()) == "sceHttpSetCookieEnabled not implemented";
|
|
}
|
|
Require(cookieUnsupported);
|
|
for (int enabled : {-1, 2, 0x100}) {
|
|
Require(sceHttpSetCookieEnabled(1, enabled) == invalidValue);
|
|
}
|
|
|
|
constexpr int parameter = static_cast<int>(0x817D0002);
|
|
constexpr int noEntitlement = static_cast<int>(0x817D0007);
|
|
static_assert(sizeof(NpEntitlementAccessEntitlementKey) == 16);
|
|
NpUnifiedEntitlementLabel label{};
|
|
std::memcpy(label.data, "unowned-addon", 14);
|
|
struct KeyBuffer {
|
|
std::uint64_t before;
|
|
NpEntitlementAccessEntitlementKey key;
|
|
std::uint64_t after;
|
|
} output;
|
|
std::memset(&output, 0xa5, sizeof(output));
|
|
std::array<unsigned char, sizeof(output)> original{};
|
|
std::memcpy(original.data(), &output, sizeof(output));
|
|
Require(sceNpEntitlementAccessGetEntitlementKey(0, nullptr, &output.key) == parameter);
|
|
Require(sceNpEntitlementAccessGetEntitlementKey(0, &label, nullptr) == parameter);
|
|
Require(sceNpEntitlementAccessGetEntitlementKey(0, nullptr, nullptr) == parameter);
|
|
for (std::uint32_t serviceLabel : {0u, 1u, 0xffffffffu}) {
|
|
Require(sceNpEntitlementAccessGetEntitlementKey(serviceLabel, &label, &output.key) == noEntitlement);
|
|
Require(std::memcmp(&output, original.data(), sizeof(output)) == 0);
|
|
}
|
|
|
|
std::array<std::uint32_t, 2> trialsFlag{0xa5a5a5a5u, 0x5a5a5a5au};
|
|
Require(sceNpEntitlementAccessGetGameTrialsFlag(trialsFlag.data()) == 0);
|
|
Require(trialsFlag[0] == 0 && trialsFlag[1] == 0x5a5a5a5au);
|
|
Require(sceNpEntitlementAccessGetGameTrialsFlag(nullptr) == parameter);
|
|
|
|
constexpr int signedOut = static_cast<int>(0x80550006);
|
|
Require(sceNpEntitlementAccessRequestUnifiedEntitlementInfoList() == signedOut);
|
|
Require(sceNpEntitlementAccessPollUnifiedEntitlementInfoList() == signedOut);
|
|
Require(sceNpEntitlementAccessRequestServiceEntitlementInfoList() == signedOut);
|
|
Require(sceNpEntitlementAccessPollServiceEntitlementInfoList() == signedOut);
|
|
Require(sceNpEntitlementAccessRequestUnifiedEntitlementInfo() == signedOut);
|
|
Require(sceNpEntitlementAccessPollUnifiedEntitlementInfo() == signedOut);
|
|
Require(sceNpEntitlementAccessRequestServiceEntitlementInfo() == signedOut);
|
|
Require(sceNpEntitlementAccessPollServiceEntitlementInfo() == signedOut);
|
|
|
|
Require(sceRudpActivate() == 0);
|
|
std::array<unsigned char, 248> status;
|
|
status.fill(0x5a);
|
|
const auto originalStatus = status;
|
|
constexpr int rudpNotInitialized = static_cast<int>(0x80770001);
|
|
Require(sceRudpGetStatus(status.data(), status.size()) == rudpNotInitialized);
|
|
Require(status == originalStatus);
|
|
alignas(8) static unsigned char rudpPool[0xC58];
|
|
Require(sceRudpInit_nid_postfix(rudpPool, sizeof(rudpPool)) == 0);
|
|
Require(sceRudpActivate() == 0);
|
|
Require(sceRudpGetStatus(status.data(), status.size()) == 0);
|
|
for (unsigned char byte : status) Require(byte == 0);
|
|
Require(sceRudpGetStatus(nullptr, 0) == static_cast<int>(0x80770004));
|
|
Require(sceRudpTerminate() == 0);
|
|
return 0;
|
|
}
|