mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
An attempt to simulate a fake PSN authentication on Patapon 3
This commit is contained in:
parent
92db25e486
commit
2620957aba
3 changed files with 577 additions and 38 deletions
|
@ -44,6 +44,7 @@
|
|||
#include "Core/HLE/proAdhoc.h"
|
||||
#include "Core/HLE/sceNetAdhoc.h"
|
||||
#include "Core/HLE/sceNet.h"
|
||||
#include "Core/HLE/sceNp.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Instance.h"
|
||||
|
||||
|
@ -481,6 +482,27 @@ void __NetApctlCallbacks()
|
|||
}
|
||||
}
|
||||
|
||||
// We are temporarily borrowing APctl thread for NpAuth callbacks for testing to simulate authentication
|
||||
if (!npAuthEvents.empty())
|
||||
{
|
||||
auto args = npAuthEvents.front();
|
||||
auto id = &args.data[0];
|
||||
auto result = &args.data[1];
|
||||
auto argAddr = &args.data[2];
|
||||
npAuthEvents.pop_front();
|
||||
|
||||
delayus = (adhocEventDelayMS + 2 * adhocExtraPollDelayMS) * 1000;
|
||||
|
||||
int handlerID = *id - 1;
|
||||
for (std::map<int, NpAuthHandler>::iterator it = npAuthHandlers.begin(); it != npAuthHandlers.end(); ++it) {
|
||||
if (it->first == handlerID) {
|
||||
DEBUG_LOG(SCENET, "NpAuthCallback [HandlerID=%i][RequestID=%d][Result=%d][ArgsPtr=%08x]", it->first, *id, *result, it->second.argument);
|
||||
// TODO: Update result / args.data[1] with the actual ticket length (or error code?)
|
||||
hleEnqueueCall(it->second.entryPoint, 3, args.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Must be delayed long enough whenever there is a pending callback.
|
||||
hleDelayResult(0, "Prevent Apctl thread from blocking", delayus);
|
||||
}
|
||||
|
|
|
@ -18,14 +18,89 @@
|
|||
// This is pretty much a stub implementation. Doesn't actually do anything, just tries to return values
|
||||
// to keep games happy anyway.
|
||||
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <StringUtils.h>
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include <Core/CoreTiming.h>
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
|
||||
#include "Core/HLE/sceNp.h"
|
||||
#include <Core/HLE/sceRtc.h>
|
||||
|
||||
static int sceNpInit(u32 poolsize, u32 poolptr)
|
||||
|
||||
bool npAuthInited = false;
|
||||
SceNpAuthMemoryStat npAuthMemStat = {};
|
||||
std::string serviceId = "";
|
||||
|
||||
int parentalControl = PARENTAL_CONTROL_ENABLED;
|
||||
int userAge = 24; // faking user Age to 24 yo
|
||||
int chatRestriction = 0; // default/initial value on Patapon 3 is 1 (restricted boolean?)
|
||||
std::string onlineId = "DummyOnlineId";
|
||||
std::string avatarUrl = "http://DummyAvatarUrl";
|
||||
|
||||
std::recursive_mutex npAuthEvtMtx;
|
||||
std::deque<NpAuthArgs> npAuthEvents;
|
||||
std::map<int, NpAuthHandler> npAuthHandlers;
|
||||
|
||||
|
||||
// Tickets data are in big-endian based on captured packets
|
||||
int writeTicketParam(u8* buffer, const u16_be type, const char* data = nullptr, const u16_be size = 0) {
|
||||
if (buffer == nullptr) return 0;
|
||||
|
||||
u16_be sz = (data == nullptr)? static_cast<u16_be>(0): size;
|
||||
memcpy(buffer, &type, 2);
|
||||
memcpy(buffer + 2, &sz, 2);
|
||||
if (sz>0) memcpy(buffer + 4, data, sz);
|
||||
|
||||
return sz + 4;
|
||||
}
|
||||
|
||||
int writeTicketStringParam(u8* buffer, const u16_be type, const char* data = nullptr, const u16_be size = 0) {
|
||||
if (buffer == nullptr) return 0;
|
||||
|
||||
u16_be sz = (data == nullptr) ? static_cast<u16_be>(0) : size;
|
||||
memcpy(buffer, &type, 2);
|
||||
memcpy(buffer + 2, &sz, 2);
|
||||
if (sz > 0) {
|
||||
memset(buffer + 4, 0, sz);
|
||||
truncate_cpy((char*)buffer + 4, sz, data);
|
||||
}
|
||||
return sz + 4;
|
||||
}
|
||||
|
||||
int writeTicketU32Param(u8* buffer, const u16_be type, const u32_be data) {
|
||||
if (buffer == nullptr) return 0;
|
||||
|
||||
u16_be sz = 4;
|
||||
memcpy(buffer, &type, 2);
|
||||
memcpy(buffer + 2, &sz, 2);
|
||||
memcpy(buffer + 4, &data, 4);
|
||||
|
||||
return sz + 4;
|
||||
}
|
||||
|
||||
int writeTicketU64Param(u8* buffer, const u16_be type, const u64_be data) {
|
||||
if (buffer == nullptr) return 0;
|
||||
|
||||
u16_be sz = 8;
|
||||
memcpy(buffer, &type, 2);
|
||||
memcpy(buffer + 2, &sz, 2);
|
||||
memcpy(buffer + 4, &data, sz);
|
||||
|
||||
return sz + 4;
|
||||
}
|
||||
|
||||
void notifyNpAuthHandlers(u32 id, u32 result, u32 argAddr) {
|
||||
std::lock_guard<std::recursive_mutex> npAuthGuard(npAuthEvtMtx);
|
||||
npAuthEvents.push_back({ id, result, argAddr });
|
||||
}
|
||||
|
||||
static int sceNpInit()
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x, %08x) at %08x", __FUNCTION__, poolsize, poolptr, currentMIPS->pc);
|
||||
ERROR_LOG(HLE, "UNIMPL %s()", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -36,16 +111,36 @@ static int sceNpTerm()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sceNpGetContentRatingFlag()
|
||||
static int sceNpGetContentRatingFlag(u32 parentalControlAddr, u32 userAgeAddr)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s()", __FUNCTION__);
|
||||
WARN_LOG(HLE, "UNTESTED %s(%08x, %08x)", __FUNCTION__, parentalControlAddr, userAgeAddr);
|
||||
|
||||
if (!Memory::IsValidAddress(parentalControlAddr) || !Memory::IsValidAddress(userAgeAddr))
|
||||
return hleLogError(HLE, SCE_NP_ERROR_INVALID_ARGUMENT, "invalid arg");
|
||||
|
||||
Memory::Write_U32(parentalControl, parentalControlAddr);
|
||||
Memory::Write_U32(userAge, userAgeAddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceNpGetChatRestrictionFlag(u32 flagAddr)
|
||||
{
|
||||
WARN_LOG(HLE, "UNTESTED %s(%08x)", __FUNCTION__, flagAddr);
|
||||
|
||||
if (!Memory::IsValidAddress(flagAddr))
|
||||
return hleLogError(HLE, SCE_NP_ERROR_INVALID_ARGUMENT, "invalid arg");
|
||||
|
||||
Memory::Write_U32(chatRestriction, flagAddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceNp[] = {
|
||||
{0X857B47D3, &WrapI_UU<sceNpInit>, "sceNpInit", 'i', "xx" },
|
||||
{0X857B47D3, &WrapI_V<sceNpInit>, "sceNpInit", 'i', "" },
|
||||
{0X37E1E274, &WrapI_V<sceNpTerm>, "sceNpTerm", 'i', "" },
|
||||
{0XBB069A87, &WrapI_V<sceNpGetContentRatingFlag>, "sceNpGetContentRatingFlag", 'i', "" },
|
||||
{0XBB069A87, &WrapI_UU<sceNpGetContentRatingFlag>, "sceNpGetContentRatingFlag", 'i', "xx" },
|
||||
{0X1D60AE4B, &WrapI_U<sceNpGetChatRestrictionFlag>, "sceNpGetChatRestrictionFlag", 'i', "x" },
|
||||
};
|
||||
|
||||
void Register_sceNp()
|
||||
|
@ -57,69 +152,205 @@ static int sceNpAuthTerm()
|
|||
{
|
||||
// No parameters
|
||||
ERROR_LOG(HLE, "UNIMPL %s()", __FUNCTION__);
|
||||
npAuthInited = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceNpAuthInit(u32 poolSize, u32 stackSize, u32 threadPrio)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x, %08x, %08x)", __FUNCTION__, poolSize, stackSize, threadPrio);
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%d, %d, %d)", __FUNCTION__, poolSize, stackSize, threadPrio);
|
||||
npAuthMemStat.npMemSize = poolSize;
|
||||
npAuthMemStat.npMaxMemSize = poolSize / 2; // Dummy
|
||||
npAuthMemStat.npFreeMemSize = poolSize - 16; // Dummy.
|
||||
|
||||
npAuthInited = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sceNpAuthGetMemoryStat(u32 memStatAddr)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x)", __FUNCTION__, memStatAddr);
|
||||
|
||||
if (!Memory::IsValidAddress(memStatAddr))
|
||||
return hleLogError(HLE, SCE_NP_AUTH_ERROR_INVALID_ARGUMENT, "invalid arg");
|
||||
|
||||
Memory::WriteStruct(memStatAddr, &npAuthMemStat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
"Authenticating matching server usage license" on Patapon 3. Could be waiting for a state change for eternity? probably need to trigger a callback handler?
|
||||
unknownPtr seems to be a struct where offset:
|
||||
TODO: Login to "https://auth.np.ac.playstation.net/nav/auth" based on https://www.psdevwiki.com/ps3/Online_Connections
|
||||
param seems to be a struct where offset:
|
||||
+00: 32-bit is the size of the struct (ie. 36 bytes),
|
||||
+04: 32-bit is also a small number (ie. 3) a mode/event/flag enum may be?,
|
||||
+04: 32-bit is also a small number (ie. 3) a mode/event/flag/version may be?,
|
||||
+08: 32-bit is a pointer to a productId? (ie. "EP9000-UCES01421_00"),
|
||||
+0C: 4x 32-bit reserved? all zero
|
||||
+1C: 32-bit random data or callback handler? optional handler? seems to be a valid pointer and pointing to a starting point of a function (have a label on the disassembly)
|
||||
+1C: 32-bit callback handler? optional handler? seems to be a valid pointer and pointing to a starting point of a function (have a label on the disassembly)
|
||||
+20: 32-bit a pointer to a random data (4 to 8-bytes data max? both 2x 32-bit seems to be a valid pointer). optional handler args?
|
||||
return value >= 0 and <0 seems to be stored at a different location by the game (valid result vs error code?)
|
||||
*/
|
||||
static int sceNpAuthCreateStartRequest(u32 unknownPtr)
|
||||
static int sceNpAuthCreateStartRequest(u32 paramAddr)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x) at %08x", __FUNCTION__, unknownPtr, currentMIPS->pc);
|
||||
if (!Memory::IsValidAddress(unknownPtr))
|
||||
return hleLogError(HLE, -1, "invalid arg");
|
||||
WARN_LOG(HLE, "UNTESTED %s(%08x) at %08x", __FUNCTION__, paramAddr, currentMIPS->pc);
|
||||
|
||||
u32* params = (u32*)Memory::GetPointer(unknownPtr);
|
||||
INFO_LOG(HLE, "%s - Product ID: %s", __FUNCTION__, Memory::IsValidAddress(params[2]) ? Memory::GetCharPointer(params[2]):"");
|
||||
// Forcing callback args to bypass all the proper procedure and attempt to go straight to a fake success, might not works properly tho.
|
||||
// 1st Arg usually either an ID returned from Create/AddHandler function or an Event ID if the game expecting a sequence of events.
|
||||
// 2nd Arg seems to be used if not a negative number and exits the handler if it's negative (error code?)
|
||||
// 3rd Arg seems to be a data (ie. 92 bytes of data?) pointer and tested for null within callback handler (optional callback args?)
|
||||
if (params[0] >= 32) {
|
||||
// These callback's args seems to be similar to the args of Adhocctl handler? (ie. event/flag, error, handlerArg)
|
||||
u32 args[3] = { 0, 0, (params[0] >= 36) ? params[8] : 0 };
|
||||
hleEnqueueCall(params[7], 3, args);
|
||||
if (!Memory::IsValidAddress(paramAddr))
|
||||
return hleLogError(HLE, SCE_NP_AUTH_ERROR_INVALID_ARGUMENT, "invalid arg");
|
||||
|
||||
SceNpAuthRequestParameter params = {};
|
||||
int size = Memory::Read_U32(paramAddr);
|
||||
Memory::Memcpy(¶ms, paramAddr, size);
|
||||
serviceId = Memory::GetCharPointer(params.serviceIdAddr);
|
||||
|
||||
INFO_LOG(HLE, "%s - Max Version: %u.%u", __FUNCTION__, params.version.major, params.version.minor);
|
||||
INFO_LOG(HLE, "%s - Service ID: %s", __FUNCTION__, Memory::GetCharPointer(params.serviceIdAddr));
|
||||
INFO_LOG(HLE, "%s - Entitlement ID: %s", __FUNCTION__, Memory::GetCharPointer(params.entitlementIdAddr));
|
||||
INFO_LOG(HLE, "%s - Cookie (size = %d): %s", __FUNCTION__, params.cookieSize, Memory::GetCharPointer(params.cookieAddr));
|
||||
|
||||
u32 retval = 0;
|
||||
if (params.size >= 32 && params.ticketCbAddr != 0) {
|
||||
bool foundHandler = false;
|
||||
|
||||
struct NpAuthHandler handler;
|
||||
memset(&handler, 0, sizeof(handler));
|
||||
|
||||
while (npAuthHandlers.find(retval) != npAuthHandlers.end())
|
||||
++retval;
|
||||
|
||||
handler.entryPoint = params.ticketCbAddr;
|
||||
handler.argument = params.cbArgAddr;
|
||||
|
||||
for (std::map<int, NpAuthHandler>::iterator it = npAuthHandlers.begin(); it != npAuthHandlers.end(); it++) {
|
||||
if (it->second.entryPoint == handler.entryPoint) {
|
||||
foundHandler = true;
|
||||
retval = it->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundHandler && Memory::IsValidAddress(handler.entryPoint)) {
|
||||
npAuthHandlers[retval] = handler;
|
||||
WARN_LOG(SCENET, "%s - Added handler(%08x, %08x) : %d", __FUNCTION__, handler.entryPoint, handler.argument, retval);
|
||||
}
|
||||
else {
|
||||
ERROR_LOG(SCENET, "%s - Same handler(%08x, %08x) already exists", __FUNCTION__, handler.entryPoint, handler.argument);
|
||||
}
|
||||
// Patapon 3 will only Abort & Destroy AuthRequest if the ID is larger than 0. Is 0 a valid request id?
|
||||
retval++;
|
||||
|
||||
// 1st Arg usually either an ID returned from Create/AddHandler function or an Event ID if the game is expecting a sequence of events.
|
||||
// 2nd Arg seems to be used if not a negative number and exits the handler if it's negative (error code?)
|
||||
// 3rd Arg seems to be a data (ie. 92 bytes of data?) pointer and tested for null within callback handler (optional callback args?)
|
||||
u32 ticketLength = 248; // default ticket length? should be updated using the ticket length returned from login
|
||||
notifyNpAuthHandlers(retval, ticketLength, (params.size >= 36) ? params.cbArgAddr : 0);
|
||||
}
|
||||
|
||||
hleDelayResult(0, "give time", 500000);
|
||||
//hleDelayResult(0, "give time", 500000);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Used within callback of sceNpAuthCreateStartRequest (arg1 = callback's args[0], arg2 = output structPtr?, arg3 = callback's args[1])
|
||||
// Is this using request id for Arg1 or cbId?
|
||||
// JPCSP is using length = 248 for dummy ticket
|
||||
static int sceNpAuthGetTicket(u32 requestId, u32 bufferAddr, u32 length)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%d, %08x, %d) at %08x", __FUNCTION__, requestId, bufferAddr, length, currentMIPS->pc);
|
||||
|
||||
if (!Memory::IsValidAddress(bufferAddr))
|
||||
return hleLogError(HLE, SCE_NP_AUTH_ERROR_INVALID_ARGUMENT, "invalid arg");
|
||||
|
||||
int result = length;
|
||||
Memory::Memset(bufferAddr, 0, length);
|
||||
SceNpTicket ticket = {};
|
||||
// Dummy Login ticket returned as Login response. Dummy ticket contents were taken from https://www.psdevwiki.com/ps3/X-I-5-Ticket
|
||||
ticket.header.version = TICKET_VER_2_1;
|
||||
ticket.header.size = 0xF0; // size excluding the header
|
||||
u8* buf = Memory::GetPointer(bufferAddr + sizeof(ticket));
|
||||
int ofs = 0;
|
||||
ofs += writeTicketParam(buf, PARAM_TYPE_STRING_ASCII, "\x4c\x47\x56\x3b\x81\x39\x4a\x22\xd8\x6b\xc1\x57\x71\x6e\xfd\xb8\xab\x63\xcc\x51", 20); // 20 random letters, token key?
|
||||
ofs += writeTicketU32Param(buf + ofs, PARAM_TYPE_INT, 0x0100); // a flags?
|
||||
PSPTimeval tv;
|
||||
__RtcTimeOfDay(&tv);
|
||||
u64 now = 1000ULL*tv.tv_sec + tv.tv_usec/1000ULL; // in milliseconds, since 1900?
|
||||
ofs += writeTicketU64Param(buf + ofs, PARAM_TYPE_DATE, now);
|
||||
ofs += writeTicketU64Param(buf + ofs, PARAM_TYPE_DATE, now + 10 * 60 * 1000); // now + 10 minutes, expired time?
|
||||
ofs += writeTicketU64Param(buf + ofs, PARAM_TYPE_LONG, 0x592e71c546e86859); // seems to be consistent, 8-bytes password hash may be? or related to entitlement? or console id?
|
||||
ofs += writeTicketStringParam(buf + ofs, PARAM_TYPE_STRING, onlineId.c_str(), 32); // username
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_STRING_ASCII, "fr\0\2", 4); // SceNpCountryCode ? ie. "fr" + 00 02
|
||||
ofs += writeTicketStringParam(buf + ofs, PARAM_TYPE_STRING, "c9", 4); // 2-char code? related to country/lang code? ie. "c9" + 00 00
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_STRING_ASCII, serviceId.c_str(), 24);
|
||||
int status = 0;
|
||||
if (parentalControl == PARENTAL_CONTROL_ENABLED) {
|
||||
status |= STATUS_ACCOUNT_PARENTAL_CONTROL_ENABLED;
|
||||
}
|
||||
status |= (userAge & 0x7F) << 24;
|
||||
ofs += writeTicketU32Param(buf + ofs, PARAM_TYPE_INT, status);
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_NULL);
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_NULL);
|
||||
ticket.section.type = SECTION_TYPE_BODY;
|
||||
ticket.section.size = ofs;
|
||||
Memory::WriteStruct(bufferAddr, &ticket);
|
||||
SceNpTicketSection footer = { SECTION_TYPE_FOOTER, 32 }; // footer section? ie. 32-bytes on ver 2.1 containing 4-chars ASCII + 20-chars ASCII
|
||||
Memory::WriteStruct(bufferAddr + sizeof(ticket) + ofs, &footer);
|
||||
ofs += sizeof(footer);
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_STRING_ASCII, "\x34\xcd\x3c\xa9", 4);
|
||||
ofs += writeTicketParam(buf + ofs, PARAM_TYPE_STRING_ASCII, "\x3a\x4b\x42\x66\x92\xda\x6b\x7c\xb7\x4c\xe8\xd9\x4f\x2b\x77\x15\x91\xb8\xa4\xa9", 20);
|
||||
u8 unknownBytes[36] = {};
|
||||
Memory::WriteStruct(bufferAddr + sizeof(ticket) + ofs, unknownBytes);
|
||||
|
||||
result = ticket.header.size + sizeof(ticket.header); // dummy ticket is 248 bytes
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Used within callback of sceNpAuthCreateStartRequest (arg1 = structPtr?, arg2 = callback's args[1], arg3 = DLCcode? ie. "EP9000-UCES01421_00-DLL001", arg4 = Patapon 3 always set to 0?)
|
||||
// Patapon 3 will loop (for each DLC?) through an array of 4+4 bytes, ID addr (pchar) + result (int). Each loop calls this function using the same ticket addr but use different ID addr (arg3) and store the return value in result field (default/initial = -1)
|
||||
static int sceNpAuthGetEntitlementById(u32 ticketBufferAddr, u32 ticketLength, u32 entitlementIdAddr, u32 arg4)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x, %d, %08x, %d)", __FUNCTION__, ticketBufferAddr, ticketLength, entitlementIdAddr, arg4);
|
||||
INFO_LOG(HLE, "%s - Entitlement ID: %s", __FUNCTION__, Memory::GetCharPointer(entitlementIdAddr));
|
||||
// Do we return the entitlement through function result? or update the ticket content? or replace the arg3 data with SceNpEntitlement struct?
|
||||
return 1; // dummy value assuming it's a boolean/flag, since we don't know how to return the entitlement result yet
|
||||
}
|
||||
|
||||
static int sceNpAuthAbortRequest(int requestId)
|
||||
{
|
||||
WARN_LOG(HLE, "UNTESTED %s(%i)", __FUNCTION__, requestId);
|
||||
// TODO: Disconnect HTTPS connection & cancel the callback event
|
||||
std::lock_guard<std::recursive_mutex> npAuthGuard(npAuthEvtMtx);
|
||||
for (auto it = npAuthEvents.begin(); it != npAuthEvents.end(); ) {
|
||||
(it->data[0] == requestId) ? it = npAuthEvents.erase(it) : ++it;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Used within callback of sceNpAuthCreateStartRequest (arg1 = callback's args[0], arg2 = structPtr?, arg3 = args[1])
|
||||
static int sceNpAuthGetTicket(u32 arg1, u32 arg2Ptr, u32 arg3)
|
||||
static int sceNpAuthDestroyRequest(int requestId)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%d, %08x, %d)", __FUNCTION__, arg1, arg2Ptr, arg3);
|
||||
WARN_LOG(HLE, "UNTESTED %s(%i)", __FUNCTION__, requestId);
|
||||
// Remove callback handler
|
||||
int handlerID = requestId - 1;
|
||||
if (npAuthHandlers.find(handlerID) != npAuthHandlers.end()) {
|
||||
npAuthHandlers.erase(handlerID);
|
||||
WARN_LOG(SCENET, "%s: Deleted handler %d", __FUNCTION__, handlerID);
|
||||
}
|
||||
else {
|
||||
ERROR_LOG(SCENET, "%s: Invalid request ID %d", __FUNCTION__, requestId);
|
||||
}
|
||||
// Patapon 3 is checking for error code 0x80550402
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Used within callback of sceNpAuthCreateStartRequest (arg1 = structPtr?, arg2 = args[1], arg3 = DLCcode? ie. "EP9000-UCES01421_00-DLL001", arg4 = 0)
|
||||
static int sceNpAuthGetEntitlementById(u32 arg1Ptr, u32 arg2, u32 arg3Ptr, u32 arg4)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x, %d, %08x, %d)", __FUNCTION__, arg1Ptr, arg2, arg3Ptr, arg4);
|
||||
INFO_LOG(HLE, "%s - Product ID: %s", __FUNCTION__, Memory::IsValidAddress(arg3Ptr) ? Memory::GetCharPointer(arg3Ptr) : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceNpAuth[] = {
|
||||
{0X4EC1F667, &WrapI_V<sceNpAuthTerm>, "sceNpAuthTerm", 'i', "" },
|
||||
{0XA1DE86F8, &WrapI_UUU<sceNpAuthInit>, "sceNpAuthInit", 'i', "xxx" },
|
||||
{0XF4531ADC, &WrapI_U<sceNpAuthGetMemoryStat>, "sceNpAuthGetMemoryStat", 'i', "x" },
|
||||
{0XCD86A656, &WrapI_U<sceNpAuthCreateStartRequest>, "sceNpAuthCreateStartRequest", 'i', "x" },
|
||||
{0X3F1C1F70, &WrapI_UUU<sceNpAuthGetTicket>, "sceNpAuthGetTicket", 'i', "xxx" },
|
||||
{0X6900F084, &WrapI_UUUU<sceNpAuthGetEntitlementById>, "sceNpAuthGetEntitlementById", 'i', "xxxx" },
|
||||
{0XD99455DD, &WrapI_I<sceNpAuthAbortRequest>, "sceNpAuthAbortRequest", 'i', "i" },
|
||||
{0X72BB0467, &WrapI_I<sceNpAuthDestroyRequest>, "sceNpAuthDestroyRequest", 'i', "i" },
|
||||
};
|
||||
|
||||
void Register_sceNpAuth()
|
||||
|
@ -140,9 +371,36 @@ static int sceNpServiceInit(u32 poolSize, u32 stackSize, u32 threadPrio)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sceNpLookupCreateTransactionCtx(u32 lookupTitleCtxIdAddr)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%08x)", __FUNCTION__, lookupTitleCtxIdAddr);
|
||||
INFO_LOG(SCENET, "%s - Title ID: %s", __FUNCTION__, Memory::GetCharPointer(lookupTitleCtxIdAddr));
|
||||
// Patapon 3 will only Destroy if returned Id > 0. Is 0 a valid id?
|
||||
return 1; // returning dummy transaction id
|
||||
}
|
||||
|
||||
// transId: id returned from sceNpLookupCreateTransactionCtx
|
||||
static int sceNpLookupDestroyTransactionCtx(u32 transId)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%d)", __FUNCTION__, transId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// transId: id returned from sceNpLookupCreateTransactionCtx
|
||||
// Patapon 3 always set Arg5 to 0
|
||||
// Addr args have something to do with GameUpdate?
|
||||
static int sceNpLookupTitleSmallStorage(u32 transId, u32 arg2Addr, u32 arg3, u32 arg4Addr, u32 arg5)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL %s(%d, %08x, %08x, %08x, %08x)", __FUNCTION__, transId, arg2Addr, arg3, arg4Addr, arg5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceNpService[] = {
|
||||
{0X00ACFAC3, &WrapI_V<sceNpServiceTerm>, "sceNpServiceTerm", 'i', "" },
|
||||
{0X0F8F5821, &WrapI_UUU<sceNpServiceInit>, "sceNpServiceInit", 'i', "xxx"},
|
||||
{0X00ACFAC3, &WrapI_V<sceNpServiceTerm>, "sceNpServiceTerm", 'i', "" },
|
||||
{0X0F8F5821, &WrapI_UUU<sceNpServiceInit>, "sceNpServiceInit", 'i', "xxx" },
|
||||
{0X5494274B, &WrapI_U<sceNpLookupCreateTransactionCtx>, "sceNpLookupCreateTransactionCtx", 'i', "x" },
|
||||
{0XA670D3A3, &WrapI_U<sceNpLookupDestroyTransactionCtx>, "sceNpLookupDestroyTransactionCtx", 'i', "x" },
|
||||
{0XC76F55ED, &WrapI_UUUUU<sceNpLookupTitleSmallStorage>, "sceNpLookupTitleSmallStorage", 'i', "xxxxx" },
|
||||
};
|
||||
|
||||
void Register_sceNpService()
|
||||
|
|
261
Core/HLE/sceNp.h
261
Core/HLE/sceNp.h
|
@ -17,7 +17,266 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
// Based on https://playstationdev.wiki/psvitadevwiki/index.php?title=Error_Codes
|
||||
#define SCE_NP_ERROR_ALREADY_INITIALIZED 0x80550001
|
||||
#define SCE_NP_ERROR_NOT_INITIALIZED 0x80550002
|
||||
#define SCE_NP_ERROR_INVALID_ARGUMENT 0x80550003
|
||||
|
||||
#define SCE_NP_AUTH_ERROR_ALREADY_INITIALIZED 0x80550301
|
||||
#define SCE_NP_AUTH_ERROR_NOT_INITIALIZED 0x80550302
|
||||
#define SCE_NP_AUTH_ERROR_EINVAL 0x80550303
|
||||
#define SCE_NP_AUTH_ERROR_ENOMEM 0x80550304
|
||||
#define SCE_NP_AUTH_ERROR_ESRCH 0x80550305
|
||||
#define SCE_NP_AUTH_ERROR_EBUSY 0x80550306
|
||||
#define SCE_NP_AUTH_ERROR_ABORTED 0x80550307
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_SERVICE_ID 0x80550308
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_CREDENTIAL 0x80550309
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_ENTITLEMENT_ID 0x8055030a
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_DATA_LENGTH 0x8055030b
|
||||
#define SCE_NP_AUTH_ERROR_UNSUPPORTED_TICKET_VERSION 0x8055030c
|
||||
#define SCE_NP_AUTH_ERROR_STACKSIZE_TOO_SHORT 0x8055030d
|
||||
#define SCE_NP_AUTH_ERROR_TICKET_STATUS_CODE_INVALID 0x8055030e
|
||||
#define SCE_NP_AUTH_ERROR_TICKET_PARAM_NOT_FOUND 0x8055030f
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_TICKET_VERSION 0x80550310
|
||||
#define SCE_NP_AUTH_ERROR_INVALID_ARGUMENT 0x80550311
|
||||
|
||||
#define SCE_NP_AUTH_ERROR_SERVICE_END 0x80550400
|
||||
#define SCE_NP_AUTH_ERROR_SERVICE_DOWN 0x80550401
|
||||
#define SCE_NP_AUTH_ERROR_SERVICE_BUSY 0x80550402
|
||||
|
||||
// Based on https://github.com/RPCS3/rpcs3/blob/psp2/rpcs3/Emu/PSP2/Modules/sceNpCommon.h
|
||||
enum SceNpServiceState : s32
|
||||
{
|
||||
SCE_NP_SERVICE_STATE_UNKNOWN = 0,
|
||||
SCE_NP_SERVICE_STATE_SIGNED_OUT,
|
||||
SCE_NP_SERVICE_STATE_SIGNED_IN,
|
||||
SCE_NP_SERVICE_STATE_ONLINE
|
||||
};
|
||||
|
||||
struct SceNpCommunicationId
|
||||
{
|
||||
char data[9];
|
||||
char term;
|
||||
u8 num;
|
||||
char dummy;
|
||||
};
|
||||
|
||||
struct SceNpCommunicationPassphrase
|
||||
{
|
||||
u8 data[128];
|
||||
};
|
||||
|
||||
struct SceNpCommunicationSignature
|
||||
{
|
||||
u8 data[160];
|
||||
};
|
||||
|
||||
struct SceNpCommunicationConfig
|
||||
{
|
||||
PSPPointer<SceNpCommunicationId> commId;
|
||||
PSPPointer<SceNpCommunicationPassphrase> commPassphrase;
|
||||
PSPPointer<SceNpCommunicationSignature> commSignature;
|
||||
};
|
||||
|
||||
struct SceNpCountryCode
|
||||
{
|
||||
char data[2];
|
||||
char term;
|
||||
char padding[1];
|
||||
};
|
||||
|
||||
// Username?
|
||||
struct SceNpOnlineId
|
||||
{
|
||||
char data[16];
|
||||
char term;
|
||||
char dummy[3];
|
||||
};
|
||||
|
||||
struct SceNpId
|
||||
{
|
||||
SceNpOnlineId handle;
|
||||
u8 opt[8];
|
||||
u8 reserved[8];
|
||||
};
|
||||
|
||||
struct SceNpAvatarUrl
|
||||
{
|
||||
char data[127];
|
||||
char term;
|
||||
};
|
||||
|
||||
struct SceNpUserInformation
|
||||
{
|
||||
SceNpId userId;
|
||||
SceNpAvatarUrl icon;
|
||||
u8 reserved[52];
|
||||
};
|
||||
|
||||
struct SceNpMyLanguages
|
||||
{
|
||||
s32_le language1;
|
||||
s32_le language2;
|
||||
s32_le language3;
|
||||
u8 padding[4];
|
||||
};
|
||||
|
||||
struct SceNpAvatarImage
|
||||
{
|
||||
u8 data[200 * 1024];
|
||||
u32_le size;
|
||||
u8 reserved[12];
|
||||
};
|
||||
|
||||
enum SceNpAvatarSizeType : s32
|
||||
{
|
||||
SCE_NP_AVATAR_SIZE_LARGE,
|
||||
SCE_NP_AVATAR_SIZE_MIDDLE,
|
||||
SCE_NP_AVATAR_SIZE_SMALL
|
||||
};
|
||||
|
||||
struct SceNpAboutMe
|
||||
{
|
||||
char data[64];
|
||||
};
|
||||
|
||||
struct SceNpDate
|
||||
{
|
||||
u16_le year;
|
||||
u8 month;
|
||||
u8 day;
|
||||
};
|
||||
|
||||
union SceNpTicketParam
|
||||
{
|
||||
s32_le _s32;
|
||||
s64_le _s64;
|
||||
u32_le _u32;
|
||||
u64_le _u64;
|
||||
SceNpDate date;
|
||||
u8 data[256];
|
||||
};
|
||||
|
||||
struct SceNpTicketVersion
|
||||
{
|
||||
u16_le major;
|
||||
u16_le minor;
|
||||
};
|
||||
|
||||
struct NpAuthHandler {
|
||||
u32 entryPoint;
|
||||
u32 argument;
|
||||
};
|
||||
|
||||
struct NpAuthArgs {
|
||||
u32_le data[3]; // id, result, ArgAddr
|
||||
};
|
||||
|
||||
using SceNpAuthCallback = s32(s32 id, s32 result, PSPPointer<void> arg);
|
||||
|
||||
struct SceNpAuthRequestParameter
|
||||
{
|
||||
u32_le size; // Size of this struct
|
||||
SceNpTicketVersion version; // Highest ticket version supported by this game/device? so PSN server can return supported ticket
|
||||
u32_le serviceIdAddr; //PSPPointer<char> serviceId; // null-terminated string
|
||||
u32_le cookieAddr; //PSPPointer<char> cookie; // null-terminated string?
|
||||
u32_le cookieSize;
|
||||
u32_le entitlementIdAddr; //PSPPointer<char> entitlementId; // null-terminated string
|
||||
u32_le consumedCount; // related to entitlement?
|
||||
u32 ticketCbAddr; //PSPPointer<SceNpAuthCallback> ticketCb
|
||||
u32_le cbArgAddr; //PSPPointer<void> cbArg
|
||||
};
|
||||
|
||||
struct SceNpEntitlementId
|
||||
{
|
||||
u8 data[32];
|
||||
};
|
||||
|
||||
struct SceNpEntitlement
|
||||
{
|
||||
SceNpEntitlementId id;
|
||||
u64_le createdDate;
|
||||
u64_le expireDate;
|
||||
u32_le type;
|
||||
s32_le remainingCount;
|
||||
u32_le consumedCount;
|
||||
u8 padding[4];
|
||||
};
|
||||
|
||||
#define TICKET_VER_2_0 0x21000000;
|
||||
#define TICKET_VER_2_1 0x21010000;
|
||||
#define TICKET_VER_3_0 0x31000000;
|
||||
#define TICKET_VER_4_0 0x41000000;
|
||||
|
||||
#define NUMBER_PARAMETERS 12
|
||||
|
||||
#define PARAM_TYPE_NULL 0
|
||||
#define PARAM_TYPE_INT 1
|
||||
#define PARAM_TYPE_LONG 2
|
||||
#define PARAM_TYPE_STRING 4 // PSP returns maximum 255 bytes
|
||||
#define PARAM_TYPE_DATE 7
|
||||
#define PARAM_TYPE_STRING_ASCII 8 // PSP returns maximum 255 bytes, can contains control code
|
||||
|
||||
#define SECTION_TYPE_BODY 0x3000
|
||||
#define SECTION_TYPE_FOOTER 0x3002
|
||||
|
||||
// Tickets data are in big-endian based on captured packets
|
||||
struct SceNpTicketParamData
|
||||
{
|
||||
u16_be type;
|
||||
u16_be length;
|
||||
//u8 value[]; // optional data
|
||||
};
|
||||
|
||||
struct SceNpTicketHeader
|
||||
{
|
||||
u32_be version; // Version contents byte are: V1 0M 00 00, where V = major version, M = minor version according to https://www.psdevwiki.com/ps3/X-I-5-Ticket
|
||||
s32_be size; // total ticket size (excluding this 8-bytes header struct)
|
||||
};
|
||||
|
||||
// Section contents byte are: 30 XX 00 YY, where XX = section type, YY = section size according to https://www.psdevwiki.com/ps3/X-I-5-Ticket
|
||||
// A section can contain other sections or param data, thus sharing their enum/def?
|
||||
struct SceNpTicketSection
|
||||
{
|
||||
u16_be type; // section type? ie. 30 XX where known XX are 00, 02, 10, 11
|
||||
u16_be size; // total section size (excluding this 4-bytes section delimiter struct)
|
||||
};
|
||||
|
||||
struct SceNpTicket
|
||||
{
|
||||
SceNpTicketHeader header;
|
||||
SceNpTicketSection section; // Body or Parameter sections?
|
||||
//SceNpTicketParamData parameters[]; // a list of TicketParamData
|
||||
//u8 unknownBytes[]; // optional data?
|
||||
};
|
||||
|
||||
#define PARENTAL_CONTROL_DISABLED 0
|
||||
#define PARENTAL_CONTROL_ENABLED 1
|
||||
|
||||
#define STATUS_ACCOUNT_SUSPENDED 0x80
|
||||
#define STATUS_ACCOUNT_CHAT_RESTRICTED 0x100
|
||||
#define STATUS_ACCOUNT_PARENTAL_CONTROL_ENABLED 0x200
|
||||
|
||||
struct SceNpAuthMemoryStat {
|
||||
int npMemSize; // Memory allocated by the NP utility.
|
||||
int npMaxMemSize; // Maximum memory used by the NP utility.
|
||||
int npFreeMemSize; // Free memory available to use by the NP utility.
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
|
||||
extern std::recursive_mutex npAuthEvtMtx;
|
||||
extern std::deque<NpAuthArgs> npAuthEvents;
|
||||
extern std::map<int, NpAuthHandler> npAuthHandlers;
|
||||
|
||||
void Register_sceNp();
|
||||
void Register_sceNpCommerce2();
|
||||
void Register_sceNpService();
|
||||
void Register_sceNpAuth();
|
||||
void Register_sceNpAuth();
|
||||
|
|
Loading…
Add table
Reference in a new issue