From 41de63f13c6fcfbafb291bd3f2287081e22de092 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sat, 5 Mar 2022 19:58:09 +0700 Subject: [PATCH] Moving sceNpMatching2-stuff to sceNp2.cpp/h. PS: Register_sceNpMatching2 not being added to HLETables because currently the callback didn't work properly yet and could crash the game. --- CMakeLists.txt | 2 + Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 + Core/HLE/sceNp.cpp | 539 -------------------------- Core/HLE/sceNp.h | 233 +----------- Core/HLE/sceNp2.cpp | 566 ++++++++++++++++++++++++++++ Core/HLE/sceNp2.h | 254 +++++++++++++ UWP/CoreUWP/CoreUWP.vcxproj | 2 + UWP/CoreUWP/CoreUWP.vcxproj.filters | 6 + android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 11 files changed, 843 insertions(+), 769 deletions(-) create mode 100644 Core/HLE/sceNp2.cpp create mode 100644 Core/HLE/sceNp2.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fe807763f..bfa85f981c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1894,6 +1894,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/scePspNpDrm_user.h Core/HLE/sceNp.cpp Core/HLE/sceNp.h + Core/HLE/sceNp2.cpp + Core/HLE/sceNp2.h Core/HLE/scePauth.cpp Core/HLE/scePauth.h Core/HW/SimpleAudioDec.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index bb5688fb30..bdfaea4361 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -535,6 +535,7 @@ + @@ -1087,6 +1088,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 8fc7db771d..3a24903dbc 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -1187,6 +1187,9 @@ HW + + HLE\Libraries + @@ -1916,6 +1919,9 @@ HW + + HLE\Libraries + diff --git a/Core/HLE/sceNp.cpp b/Core/HLE/sceNp.cpp index fd6eb1563c..c7328a8ed0 100644 --- a/Core/HLE/sceNp.cpp +++ b/Core/HLE/sceNp.cpp @@ -18,9 +18,6 @@ // This is pretty much a stub implementation. Doesn't actually do anything, just tries to return values // to keep games happy anyway. -#include -#include -#include #include #include "Core/MemMapHelpers.h" #include @@ -32,7 +29,6 @@ bool npAuthInited = false; int npSigninState = NP_SIGNIN_STATUS_NONE; SceNpAuthMemoryStat npAuthMemStat = {}; -SceNpAuthMemoryStat npMatching2MemStat = {}; PSPTimeval npSigninTimestamp{}; // TODO: These should probably be grouped in a struct, since they're used to generate an auth ticket @@ -46,19 +42,12 @@ std::string npOnlineId = "DummyOnlineId"; // SceNpOnlineId struct? std::string npServiceId = ""; // UNO game uses EP2006-NPEH00020_00 std::string npAvatarUrl = "http://DummyAvatarUrl"; // SceNpAvatarUrl struct? -bool npMatching2Inited = false; SceNpCommunicationId npTitleId; std::recursive_mutex npAuthEvtMtx; std::deque npAuthEvents; std::map npAuthHandlers; -// TODO: Moves NpMatching2-related stuff to sceNp2.cpp -std::recursive_mutex npMatching2EvtMtx; -std::deque npMatching2Events; -std::map npMatching2Handlers; -//std::map npMatching2Contexts; - // 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) { @@ -113,20 +102,6 @@ void notifyNpAuthHandlers(u32 id, u32 result, u32 argAddr) { npAuthEvents.push_back({ id, result, argAddr }); } -// serverId: 0 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d (ie. when already joined to a server?) -// unk1~unk5 usually 0, -// unk1: 1st 32-bit of LeaveRoom/etc's Arg2 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d/0x010e -// unk2: 2nd 32-bit of LeaveRoom/etc's Arg2 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d/0x010e -// unk5: 1 on 0x0002/0x0003/0x0005/0x0006/0x0007/0x0101/0x0102/0x0106 -// unk6 (new state?): 8-bit?(masked with 0xff) 0x01 on 0x0001, 0x03 on 0x0002, 0x04 on 0x0003, 0x05 on 0x0004, 0x06 on 0x0005, 0x07 on 0x0006, 0x08 on 0x0007, -// 0x09 on 0x0101, 0x0A on 0x0102, 0x0C on 0x0103, 0x0D on 0x0104, 0x0E on 0x0105, 0x0F on 0x0106, 0x10 on 0x0107, 0x11 on 0x0108, -// 0x12 on 0x0109, 0x13 on 0x010a, 0x14 on 0x010b, 0x15 on 0x010c, 0x16 on 0x010d, 0x17 on 0x010e, 0x18 on 0xa102 -void notifyNpMatching2Handlers(NpMatching2Args &args, u32 ctxId, u32 serverId, u32 cbFuncAddr, u32 cbArgAddr, u32 unk3, u32 unk4, u32 unk5, u8 unk6) { - std::lock_guard npMatching2Guard(npMatching2EvtMtx); - // TODO: separate/map each list per ctxId - npMatching2Events.push_back(args); -} - static int sceNpInit() { ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__); @@ -654,517 +629,3 @@ void Register_sceNpCommerce2() RegisterModule("sceNpCommerce2", ARRAY_SIZE(sceNpCommerce2), sceNpCommerce2); } -static int sceNpMatching2Init(int poolSize, int threadPriority, int cpuAffinityMask, int threadStackSize) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %d, %d, %d) at %08x", __FUNCTION__, poolSize, threadPriority, cpuAffinityMask, threadStackSize, currentMIPS->pc); - //if (npMatching2Inited) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_ALREADY_INITIALIZED); - - npMatching2MemStat.npMemSize = poolSize - 0x20; - npMatching2MemStat.npMaxMemSize = 0x4050; // Dummy maximum foot print - npMatching2MemStat.npFreeMemSize = npMatching2MemStat.npMemSize; - - npMatching2Handlers.clear(); - npMatching2Events.clear(); - npMatching2Inited = true; - return 0; -} - -static int sceNpMatching2Term() -{ - ERROR_LOG(SCENET, "UNIMPL %s() at %08x", __FUNCTION__, currentMIPS->pc); - npMatching2Inited = false; - npMatching2Handlers.clear(); - npMatching2Events.clear(); - - return 0; -} - -static int sceNpMatching2CreateContext(u32 communicationIdPtr, u32 passPhrasePtr, u32 ctxIdPtr, int unknown) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%08x[%s], %08x[%08x], %08x[%d], %d) at %08x", __FUNCTION__, communicationIdPtr, Memory::GetCharPointer(communicationIdPtr), passPhrasePtr, Memory::Read_U32(passPhrasePtr), ctxIdPtr, Memory::Read_U16(ctxIdPtr), unknown, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(communicationIdPtr) || !Memory::IsValidAddress(passPhrasePtr) || !Memory::IsValidAddress(ctxIdPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); - - // FIXME: It seems Context are mapped to TitleID? may return 0x80550C05 or 0x80550C06 when finding an existing context - SceNpCommunicationId* titleid = (SceNpCommunicationId*)Memory::GetCharPointer(communicationIdPtr); - memcpy(npTitleId.data, titleid->data, sizeof(npTitleId)); - - SceNpCommunicationPassphrase* passph = (SceNpCommunicationPassphrase*)Memory::GetCharPointer(passPhrasePtr); - - SceNpId npid{}; - int retval = NpGetNpId(&npid); - if (retval < 0) - return hleLogError(SCENET, retval); - - INFO_LOG(SCENET, "%s - Title ID: %s", __FUNCTION__, titleid->data); - INFO_LOG(SCENET, "%s - Online ID: %s", __FUNCTION__, npid.handle.data); - std::string datahex; - DataToHexString(npid.opt, sizeof(npid.opt), &datahex); - INFO_LOG(SCENET, "%s - Options?: %s", __FUNCTION__, datahex.c_str()); - datahex.clear(); - DataToHexString(10, 0, passph->data, sizeof(passph->data), &datahex); - INFO_LOG(SCENET, "%s - Passphrase: \n%s", __FUNCTION__, datahex.c_str()); - - // TODO: Allocate & zeroed a memory of 68 bytes where npId (36 bytes) is copied to offset 8, offset 44 = 0x00026808, offset 48 = 0 - - // Returning dummy Id, a 16-bit variable according to JPCSP - // FIXME: It seems ctxId need to be in the range of 1 to 7 to be valid ? - Memory::Write_U16(1, ctxIdPtr); - return 0; -} - -static int sceNpMatching2ContextStart(int ctxId) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d) at %08x", __FUNCTION__, ctxId, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - //if (!npMatching2Ctx) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID - - //if (npMatching2Ctx.started) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_STARTED); - - // TODO: use sceNpGetUserProfile and check server availability using sceNpService_76867C01 - //npMatching2Ctx.started = true; - Url url("http://static-resource.np.community.playstation.net/np/resource/psp-title/" + std::string(npTitleId.data) + "_00/matching/" + std::string(npTitleId.data) + "_00-matching.xml"); - http::Client client; - http::RequestProgress progress; - if (!client.Resolve(url.Host().c_str(), url.Port())) { - return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP failed to resolve %s", url.Resource().c_str()); - } - - client.SetDataTimeout(20.0); - if (client.Connect()) { - char requestHeaders[4096]; - snprintf(requestHeaders, sizeof(requestHeaders), - "User-Agent: PS3Community-agent/1.0.0 libhttp/1.0.0\r\n"); - - DEBUG_LOG(SCENET, "GET URI: %s", url.ToString().c_str()); - http::RequestParams req(url.Resource(), "*/*"); - int err = client.SendRequest("GET", req, requestHeaders, &progress); - if (err < 0) { - client.Disconnect(); - return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP GET Error = %d", err); - } - - net::Buffer readbuf; - std::vector responseHeaders; - int code = client.ReadResponseHeaders(&readbuf, responseHeaders, &progress); - if (code != 200) { - client.Disconnect(); - return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP Error Code = %d", code); - } - - net::Buffer output; - int res = client.ReadResponseEntity(&readbuf, responseHeaders, &output, &progress); - if (res != 0) { - WARN_LOG(SCENET, "Unable to read HTTP response entity: %d", res); - } - client.Disconnect(); - - std::string entity; - size_t readBytes = output.size(); - output.Take(readBytes, &entity); - - // TODO: Use XML Parser to get the Tag and it's attributes instead of searching for keywords on the string - std::string text; - size_t ofs = entity.find("titleid="); - if (ofs == std::string::npos) - return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "titleid not found"); - - ofs += 9; - size_t ofs2 = entity.find('"', ofs); - text = entity.substr(ofs, ofs2-ofs); - INFO_LOG(SCENET, "%s - Title ID: %s", __FUNCTION__, text.c_str()); - - int i = 1; - while (true) { - ofs = entity.find("", ++ofs2); - if (ofs == std::string::npos) - return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "agent host not found"); - - ofs2 = entity.find("pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - //if (!npMatching2Ctx) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID - - //if (!npMatching2Ctx.started) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED); - - //TODO: Stop any in-progress HTTPClient communication used on sceNpMatching2ContextStart - //npMatching2Ctx.started = false; - - return 0; -} - -static int sceNpMatching2DestroyContext(int ctxId) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d) at %08x", __FUNCTION__, ctxId, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - //if (!npMatching2Ctx) - // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID - - // Remove callback handler - int handlerID = ctxId - 1; - if (npMatching2Handlers.find(handlerID) != npMatching2Handlers.end()) { - npMatching2Handlers.erase(handlerID); - WARN_LOG(SCENET, "%s: Deleted handler %d", __FUNCTION__, handlerID); - } - else { - ERROR_LOG(SCENET, "%s: Invalid Context ID %d", __FUNCTION__, ctxId); - } - - return 0; -} - -static int sceNpMatching2GetMemoryStat(u32 memStatPtr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%08x) at %08x", __FUNCTION__, memStatPtr, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(memStatPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT); - - Memory::WriteStruct(memStatPtr, &npMatching2MemStat); - - return 0; -} - -static int sceNpMatching2RegisterSignalingCallback(int ctxId, u32 callbackFunctionAddr, u32 callbackArgument) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x) at %08x", __FUNCTION__, ctxId, callbackFunctionAddr, callbackArgument, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (ctxId <= 0) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID); - - int id = ctxId - 1; - if (callbackFunctionAddr != 0) { - bool foundHandler = false; - - struct NpMatching2Handler handler; - memset(&handler, 0, sizeof(handler)); - - handler.entryPoint = callbackFunctionAddr; - handler.argument = callbackArgument; - - for (std::map::iterator it = npMatching2Handlers.begin(); it != npMatching2Handlers.end(); it++) { - if (it->second.entryPoint == handler.entryPoint) { - foundHandler = true; - id = it->first; - break; - } - } - - if (!foundHandler && Memory::IsValidAddress(handler.entryPoint)) { - npMatching2Handlers[id] = handler; - WARN_LOG(SCENET, "%s - Added handler(%08x, %08x) : %d", __FUNCTION__, handler.entryPoint, handler.argument, id); - } - else { - ERROR_LOG(SCENET, "%s - Same handler(%08x, %08x) already exists", __FUNCTION__, handler.entryPoint, handler.argument); - } - - //u32 dataLength = 4097; - //notifyNpMatching2Handlers(retval, dataLength, handler.argument); - - // callback struct have 57 * u32? where [0]=0, [40]=flags, [55]=callbackFunc, and [56]=callbackArgs? - //hleEnqueueCall(callbackFunctionAddr, 7, (u32*)Memory::GetPointer(callbackArgument), nullptr); // 7 args? since the callback handler is trying to use t2 register - } - return 0; -} - -static int sceNpMatching2GetServerIdListLocal(int ctxId, u32 serverIdsPtr, int maxServerIds) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %d) at %08x", __FUNCTION__, ctxId, serverIdsPtr, maxServerIds, currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(serverIdsPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT); - - // Returning dummy Id, a 16-bit variable according to JPCSP - for (int i = 0; i < maxServerIds; i++) - Memory::Write_U16(1234+i, serverIdsPtr+(i*2)); - - return maxServerIds; // dummy value -} - -// Unknown1 = optParam, unknown2 = assignedReqId according to https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/sceNp2.cpp ? -static int sceNpMatching2GetServerInfo(int ctxId, u32 serverIdPtr, u32 unknown1Ptr, u32 unknown2Ptr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x[%d], %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, serverIdPtr, Memory::Read_U16(serverIdPtr), unknown1Ptr, unknown2Ptr, Memory::Read_U32(unknown2Ptr), currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(serverIdPtr) || !Memory::IsValidAddress(unknown2Ptr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? - - // Server ID is a 16-bit variable according to JPCSP - int serverId = Memory::Read_U16(serverIdPtr); - - if (serverId == 0) - return hleLogError(SCENET, 0x80550CBF); // Should be SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID ? - - // Output to unknown1(infoBuffer)? and unknown2(infoLength or flags)? - // Patapon 3 is using serverId at 09FFF2F4, unknown1 at 09FFF2E4, unknown2 at 09FFF2E0, which mean unknown1's can only fit upto 16-bytes - // Patapon 3 seems to be copying data from unknown1 with a fixed size of 20-bytes? - // input unknown1 struct: based on Fat Princess (US) - // 0000 32-bit function address (callback?) 0x08A08B40 - // 0004 32-bit pointer to a struct? (callback args?) 0x09888158 (contains 32-bit (-1) + 32-bit (1) + 16-bit ctxId(0001) + 32bit 0x06913801? + 16-bit serverId(1234), so on), probably only 2x 32-bit struct? - // 0008 32-bit set to 0 - // 000a 16-bit set to 0 - // - u32 cbFunc = Memory::Read_U32(unknown1Ptr); - u32 cbArg = Memory::Read_U32(unknown1Ptr + 0x04); - - // Notify callback handler - if (Memory::IsValidAddress(cbFunc)) { - // The cbFunc seems to be storing s0~s4(s0 pointing to 0x0996DD58 containing data similar to 0x09888158 above on the 1st 2x 32-bit data, s1 seems to be ctxId, s2~s4=0xdeadbeef) into stack and use a0~t1 (6 args?): - // Arg1(a0) & Arg3(a2) are being masked with 0xffff (16-bit id?) - // This callback tried to load data from address 0x08BD4860+8 (not part of arg? which being set using content of unknown2 not long after returning from sceNpMatching2GetServerInfo, so we may need to give some delay before calling this callback) - // and comparing it with Arg2(a1), repeated by increasing the address 0x08BD4860 by 288 bytes on each loop for 64 times or until it found a matching one. - // When a match is found the callback will process the address further, otherwise exit the callback. - // Matching address struct: (zeroed before calling sceNpMatching2GetServerInfo? and set after returning from sceNpMatching2GetServerInfo?) - // 0000 32-bit func address (another callback?) 0x08A07EF4 - // 0008 32-bit value from unknown2 content, being set not long after returning from sceNpMatching2GetServerInfo - // 000c 32-bit unknown - // 0010 8-bit status to indicate not updated from callback yet? initially 0, set to 1 not long after returning from sceNpMatching2GetServerInfo (along with unknown2 content) - // - // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere - NpMatching2Args args = {}; - args.data[0] = PSP_NP_MATCHING2_EVENT_0001; - args.data[1] = PSP_NP_MATCHING2_STATE_1001; // or size of data? - args.data[2] = serverIdPtr; // serverId or was it pointing to optional data at last arg (ie. args[10] where serverId is stored)? - args.data[3] = unknown1Ptr; - //args.data[4] = a boolean(0/1) related to a u8 value from the struct at args[9] (value XOR 0x04 == 0) - args.data[5] = unknown2Ptr; - args.data[6] = 0; - //args.data[8] = 0 or a pointer to a struct related to context? - //args.data[9] = 0 or a pointer to a struct related to context and matched serverId? - //args.data[10] = serverId; - - notifyNpMatching2Handlers(args, ctxId, serverId, 0, 0, 0, 0, 0, 1); - - Memory::Write_U32(args.data[1], unknown2Ptr); // server status or flags? - } - - // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? - return 0; -} - -static int sceNpMatching2LeaveRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? - - u32 cbFunc = Memory::Read_U32(reqParamPtr); - u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); - - // Notify callback handler - if (Memory::IsValidAddress(cbFunc)) { - // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere - NpMatching2Args args = {}; - args.data[0] = PSP_NP_MATCHING2_EVENT_0103; - args.data[1] = PSP_NP_MATCHING2_STATE_3202; - //args.data[2] = pointer to arg[8], where the 1st 20 bytes copied from (reqParamPtr+0x08), the rest of the struct are zeroed - args.data[3] = optParamPtr; - args.data[4] = 0; - args.data[5] = assignedReqIdPtr; - args.data[6] = 0; - //args.data[8] = an initially zeroed struct of 536 bytes where the 1st 20 bytes were taken from reqParam offset 0x08 - - notifyNpMatching2Handlers(args, ctxId, 0, cbFunc, cbArg, 0, 0, 0, 0x0c); - - Memory::Write_U32(args.data[1], assignedReqIdPtr); - } - - // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? - return 0; -} - -static int sceNpMatching2JoinRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 unknown1, u32 unknown2, u32 assignedReqIdPtr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? - - // Server ID is a 16-bit variable according to JPCSP - int serverId = Memory::Read_U16(reqParamPtr + 0x06); - - if (serverId == 0) - return hleLogError(SCENET, 0x80550CBF); // Should be SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID ? - - u32 cbFunc = Memory::Read_U32(reqParamPtr); - u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); - - // Notify callback handler - if (Memory::IsValidAddress(cbFunc)) { - // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere - NpMatching2Args args = {}; - args.data[0] = PSP_NP_MATCHING2_EVENT_0102; - args.data[1] = PSP_NP_MATCHING2_STATE_1209; - //args.data[2] = pointer to arg[8] (optional data?) - args.data[3] = optParamPtr; - args.data[4] = 0; - args.data[5] = assignedReqIdPtr; - args.data[6] = 0; - // Followed by optional data? - args.data[8] = reqParamPtr; // an initially zeroed struct of 1224 bytes, where the 1st 32bit is set to reqParamPtr - args.data[9] = unknown1; - args.data[10] = unknown2; - - notifyNpMatching2Handlers(args, ctxId, serverId, 0, 0, 0, 0, 1, 0x0a); - - Memory::Write_U32(args.data[1], assignedReqIdPtr); - } - - // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? - return 0; -} - -static int sceNpMatching2SearchRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? - - u32 cbFunc = Memory::Read_U32(reqParamPtr); - u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); - - // Notify callback handler - if (Memory::IsValidAddress(cbFunc)) { - // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere - NpMatching2Args args = {}; - // TODO: Set the correct callback args - - Memory::Write_U32(args.data[1], assignedReqIdPtr); // server status or flags? - } - - return 0; -} - -static int sceNpMatching2SendRoomChatMessage(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) -{ - ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); - if (!npMatching2Inited) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); - - if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) - return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? - - u32 cbFunc = Memory::Read_U32(reqParamPtr); - u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); - - // Notify callback handler - if (Memory::IsValidAddress(cbFunc)) { - // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere - NpMatching2Args args = {}; - args.data[0] = PSP_NP_MATCHING2_EVENT_0107; - args.data[1] = PSP_NP_MATCHING2_STATE_3208; - //args.data[2] = pointer to arg[8] - args.data[3] = optParamPtr; - args.data[4] = 0; - args.data[5] = assignedReqIdPtr; - args.data[6] = 0; - //args.data[8] = reqParamPtr; - - notifyNpMatching2Handlers(args, ctxId, 0, cbFunc, cbArg, 0, 0, 0, 0x10); - - Memory::Write_U32(args.data[1], assignedReqIdPtr); // server status or flags? - } - - // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? - return 0; -} - -const HLEFunction sceNpMatching2[] = { - {0x2E61F6E1, &WrapI_IIII, "sceNpMatching2Init", 'i', "iiii" }, - {0x8BF37D8C, &WrapI_V, "sceNpMatching2Term", 'i', "" }, - {0x5030CC53, &WrapI_UUUI, "sceNpMatching2CreateContext", 'i', "xxxi" }, - {0x190FF903, &WrapI_I, "sceNpMatching2ContextStart", 'i', "i" }, - {0x2B3892FC, &WrapI_I, "sceNpMatching2ContextStop", 'i', "i" }, - {0x3DE70241, &WrapI_I, "sceNpMatching2DestroyContext", 'i', "i" }, - {0x22F38DAF, &WrapI_U, "sceNpMatching2GetMemoryStat", 'i', "x" }, - {0xA3C298D1, &WrapI_IUU, "sceNpMatching2RegisterSignalingCallback", 'i', "ixx" }, - {0xF47342FC, &WrapI_IUI, "sceNpMatching2GetServerIdListLocal", 'i', "ixi" }, - {0x4EE3A8EC, &WrapI_IUUU, "sceNpMatching2GetServerInfo", 'i', "ixxx" }, - {0xC870535A, &WrapI_IUUU, "sceNpMatching2LeaveRoom", 'i', "ixxx" }, - {0xAAD0946A, &WrapI_IUUUUU, "sceNpMatching2JoinRoom", 'i', "ixxxxx" }, - {0x81C13E6D, &WrapI_IUUU, "sceNpMatching2SearchRoom", 'i', "ixxx" }, - {0x55F7837F, &WrapI_IUUU, "sceNpMatching2SendRoomChatMessage", 'i', "ixxx" }, -}; - -void Register_sceNpMatching2() -{ - RegisterModule("sceNpMatching2", ARRAY_SIZE(sceNpMatching2), sceNpMatching2); -} diff --git a/Core/HLE/sceNp.h b/Core/HLE/sceNp.h index 0be9f0ca54..ed2a30646d 100644 --- a/Core/HLE/sceNp.h +++ b/Core/HLE/sceNp.h @@ -17,6 +17,9 @@ #pragma once +#include +#include +#include #include #include "Common/Net/HTTPClient.h" #include "Common/Net/Resolve.h" @@ -159,128 +162,7 @@ #define SCE_NP_COMMUNITY_SERVER_ERROR_UBS_MAINTENANCE 0x805508b3 #define SCE_NP_COMMUNITY_SERVER_ERROR_UNSPECIFIED 0x805508ff -// TODO: Moves NpMatching2-related stuff to sceNp2.h // Based on https://gist.githubusercontent.com/raw/4140449/PS%20Vita (Might be slightly different with PSP?) -#define SCE_NP_MATCHING2_ERROR_OUT_OF_MEMORY 0x80550c01 -#define SCE_NP_MATCHING2_ERROR_ALREADY_INITIALIZED 0x80550c02 -#define SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED 0x80550c03 -#define SCE_NP_MATCHING2_ERROR_CONTEXT_MAX 0x80550c04 // might be "Invalid Argument" on PSP? -#define SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_EXISTS 0x80550c05 // might be "Context Max/Context Id higher than 7" on PSP? -#define SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND 0x80550c06 -#define SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_STARTED 0x80550c07 -#define SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED 0x80550c08 -#define SCE_NP_MATCHING2_ERROR_SERVER_NOT_FOUND 0x80550c09 -#define SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT 0x80550c0a -#define SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID 0x80550c0b -#define SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID 0x80550c0c -#define SCE_NP_MATCHING2_ERROR_INVALID_LOBBY_ID 0x80550c0e -#define SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID 0x80550c0f -#define SCE_NP_MATCHING2_ERROR_INVALID_MEMBER_ID 0x80550c10 -#define SCE_NP_MATCHING2_ERROR_INVALID_ATTRIBUTE_ID 0x80550c11 -#define SCE_NP_MATCHING2_ERROR_INVALID_CASTTYPE 0x80550c12 -#define SCE_NP_MATCHING2_ERROR_INVALID_SORT_METHOD 0x80550c13 -#define SCE_NP_MATCHING2_ERROR_INVALID_MAX_SLOT 0x80550c14 -#define SCE_NP_MATCHING2_ERROR_INVALID_OPT_SIZE 0x80550c15 -#define SCE_NP_MATCHING2_ERROR_INVALID_MATCHING_SPACE 0x80550c16 -#define SCE_NP_MATCHING2_ERROR_INVALID_BLOCK_KICK_FLAG 0x80550c18 -#define SCE_NP_MATCHING2_ERROR_INVALID_MESSAGE_TARGET 0x80550c19 -#define SCE_NP_MATCHING2_ERROR_RANGE_FILTER_MAX 0x80550c1a -#define SCE_NP_MATCHING2_ERROR_INVALID_ALIGNMENT 0x80550c1e -#define SCE_NP_MATCHING2_ERROR_CONNECTION_CLOSED_BY_SERVER 0x80550c22 -#define SCE_NP_MATCHING2_ERROR_SSL_VERIFY_FAILED 0x80550c23 -#define SCE_NP_MATCHING2_ERROR_SSL_HANDSHAKE 0x80550c24 -#define SCE_NP_MATCHING2_ERROR_SSL_SEND 0x80550c25 -#define SCE_NP_MATCHING2_ERROR_SSL_RECV 0x80550c26 -#define SCE_NP_MATCHING2_ERROR_JOINED_SESSION_MAX 0x80550c27 -#define SCE_NP_MATCHING2_ERROR_ALREADY_JOINED 0x80550c28 -#define SCE_NP_MATCHING2_ERROR_INVALID_SESSION_TYPE 0x80550c29 -#define SCE_NP_MATCHING2_ERROR_NP_SIGNED_OUT 0x80550c2b -#define SCE_NP_MATCHING2_ERROR_BUSY 0x80550c2c -#define SCE_NP_MATCHING2_ERROR_SERVER_NOT_AVAILABLE 0x80550c2d -#define SCE_NP_MATCHING2_ERROR_NOT_ALLOWED 0x80550c2e -#define SCE_NP_MATCHING2_ERROR_ABORTED 0x80550c2f -#define SCE_NP_MATCHING2_ERROR_REQUEST_NOT_FOUND 0x80550c30 -#define SCE_NP_MATCHING2_ERROR_SESSION_DESTROYED 0x80550c31 -#define SCE_NP_MATCHING2_ERROR_CONTEXT_STOPPED 0x80550c32 -#define SCE_NP_MATCHING2_ERROR_INVALID_REQUEST_PARAMETER 0x80550c33 -#define SCE_NP_MATCHING2_ERROR_NOT_NP_SIGN_IN 0x80550c34 -#define SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND 0x80550c35 -#define SCE_NP_MATCHING2_ERROR_ROOM_MEMBER_NOT_FOUND 0x80550c36 -#define SCE_NP_MATCHING2_ERROR_LOBBY_NOT_FOUND 0x80550c37 -#define SCE_NP_MATCHING2_ERROR_LOBBY_MEMBER_NOT_FOUND 0x80550c38 -#define SCE_NP_MATCHING2_ERROR_KEEPALIVE_TIMEOUT 0x80550c3a -#define SCE_NP_MATCHING2_ERROR_TIMEOUT_TOO_SHORT 0x80550c3b -#define SCE_NP_MATCHING2_ERROR_TIMEDOUT 0x80550c3c -#define SCE_NP_MATCHING2_ERROR_INVALID_SLOTGROUP 0x80550c3d -#define SCE_NP_MATCHING2_ERROR_INVALID_ATTRIBUTE_SIZE 0x80550c3e -#define SCE_NP_MATCHING2_ERROR_CANNOT_ABORT 0x80550c3f -#define SCE_NP_MATCHING2_ERROR_SESSION_NOT_FOUND 0x80550c40 - -#define SCE_NP_MATCHING2_SERVER_ERROR_BAD_REQUEST 0x80550d01 -#define SCE_NP_MATCHING2_SERVER_ERROR_SERVICE_UNAVAILABLE 0x80550d02 -#define SCE_NP_MATCHING2_SERVER_ERROR_BUSY 0x80550d03 -#define SCE_NP_MATCHING2_SERVER_ERROR_END_OF_SERVICE 0x80550d04 -#define SCE_NP_MATCHING2_SERVER_ERROR_INTERNAL_SERVER_ERROR 0x80550d05 -#define SCE_NP_MATCHING2_SERVER_ERROR_PLAYER_BANNED 0x80550d06 -#define SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN 0x80550d07 -#define SCE_NP_MATCHING2_SERVER_ERROR_BLOCKED 0x80550d08 -#define SCE_NP_MATCHING2_SERVER_ERROR_UNSUPPORTED_NP_ENV 0x80550d09 -#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_TICKET 0x80550d0a -#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_SIGNATURE 0x80550d0b -#define SCE_NP_MATCHING2_SERVER_ERROR_EXPIRED_TICKET 0x80550d0c -#define SCE_NP_MATCHING2_SERVER_ERROR_ENTITLEMENT_REQUIRED 0x80550d0d -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_CONTEXT 0x80550d0e -#define SCE_NP_MATCHING2_SERVER_ERROR_CLOSED 0x80550d0f -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_TITLE 0x80550d10 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_WORLD 0x80550d11 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_LOBBY 0x80550d12 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM 0x80550d13 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_LOBBY_INSTANCE 0x80550d14 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE 0x80550d15 -#define SCE_NP_MATCHING2_SERVER_ERROR_PASSWORD_MISMATCH 0x80550d17 -#define SCE_NP_MATCHING2_SERVER_ERROR_LOBBY_FULL 0x80550d18 -#define SCE_NP_MATCHING2_SERVER_ERROR_ROOM_FULL 0x80550d19 -#define SCE_NP_MATCHING2_SERVER_ERROR_GROUP_FULL 0x80550d1b -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER 0x80550d1c -#define SCE_NP_MATCHING2_SERVER_ERROR_TITLE_PASSPHRASE_MISMATCH 0x80550d1e -#define SCE_NP_MATCHING2_SERVER_ERROR_CONSOLE_BANNED 0x80550d28 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_ROOMGROUP 0x80550d29 -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_GROUP 0x80550d2a -#define SCE_NP_MATCHING2_SERVER_ERROR_NO_PASSWORD 0x80550d2b -#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_GROUP_SLOT_NUM 0x80550d2c -#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_PASSWORD_SLOT_MASK 0x80550d2d -#define SCE_NP_MATCHING2_SERVER_ERROR_DUPLICATE_GROUP_LABEL 0x80550d2e -#define SCE_NP_MATCHING2_SERVER_ERROR_REQUEST_OVERFLOW 0x80550d2f -#define SCE_NP_MATCHING2_SERVER_ERROR_ALREADY_JOINED 0x80550d30 -#define SCE_NP_MATCHING2_SERVER_ERROR_NAT_TYPE_MISMATCH 0x80550d31 -#define SCE_NP_MATCHING2_SERVER_ERROR_ROOM_INCONSISTENCY 0x80550d32 - -#define SCE_NP_MATCHING2_SIGNALING_ERROR_NOT_INITIALIZED 0x80550e01 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_ALREADY_INITIALIZED 0x80550e02 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_OUT_OF_MEMORY 0x80550e03 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTXID_NOT_AVAILABLE 0x80550e04 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTX_NOT_FOUND 0x80550e05 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_REQID_NOT_AVAILABLE 0x80550e06 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_REQ_NOT_FOUND 0x80550e07 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_PARSER_CREATE_FAILED 0x80550e08 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_PARSER_FAILED 0x80550e09 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_INVALID_NAMESPACE 0x80550e0a -#define SCE_NP_MATCHING2_SIGNALING_ERROR_NETINFO_NOT_AVAILABLE 0x80550e0b -#define SCE_NP_MATCHING2_SIGNALING_ERROR_PEER_NOT_RESPONDING 0x80550e0c -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONNID_NOT_AVAILABLE 0x80550e0d -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONN_NOT_FOUND 0x80550e0e -#define SCE_NP_MATCHING2_SIGNALING_ERROR_PEER_UNREACHABLE 0x80550e0f -#define SCE_NP_MATCHING2_SIGNALING_ERROR_TERMINATED_BY_PEER 0x80550e10 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_TIMEOUT 0x80550e11 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTX_MAX 0x80550e12 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_RESULT_NOT_FOUND 0x80550e13 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONN_IN_PROGRESS 0x80550e14 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_INVALID_ARGUMENT 0x80550e15 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_OWN_NP_ID 0x80550e16 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_TOO_MANY_CONN 0x80550e17 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_TERMINATED_BY_MYSELF 0x80550e18 -#define SCE_NP_MATCHING2_SIGNALING_ERROR_MATCHING2_PEER_NOT_FOUND 0x80550e19 - #define SCE_NP_TROPHY_ERROR_UNKNOWN 0x80551600 #define SCE_NP_TROPHY_ERROR_NOT_INITIALIZED 0x80551601 #define SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED 0x80551602 @@ -526,114 +408,6 @@ struct SceNpAuthMemoryStat { int npFreeMemSize; // Free memory available to use by the NP utility. }; - -// Based on https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/sceNp2.h (Just as reference, might be slightly different than PSP) -// Event of request functions -enum PS3Matching2RequestEvent -{ - SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo = 0x0001, - SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList = 0x0002, - SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataExternalList = 0x0003, - SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal = 0x0004, - SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList = 0x0005, - SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyInfoList = 0x0006, - SCE_NP_MATCHING2_REQUEST_EVENT_SetUserInfo = 0x0007, - SCE_NP_MATCHING2_REQUEST_EVENT_GetUserInfoList = 0x0008, - SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext = 0x0009, - SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext = 0x000a, - SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom = 0x0101, - SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom = 0x0102, - SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom = 0x0103, - SCE_NP_MATCHING2_REQUEST_EVENT_GrantRoomOwner = 0x0104, - SCE_NP_MATCHING2_REQUEST_EVENT_KickoutRoomMember = 0x0105, - SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom = 0x0106, - SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomChatMessage = 0x0107, - SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage = 0x0108, - SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal = 0x0109, - SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal = 0x010a, - SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal = 0x010b, - SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataInternal = 0x010c, - SCE_NP_MATCHING2_REQUEST_EVENT_SetSignalingOptParam = 0x010d, - SCE_NP_MATCHING2_REQUEST_EVENT_JoinLobby = 0x0201, - SCE_NP_MATCHING2_REQUEST_EVENT_LeaveLobby = 0x0202, - SCE_NP_MATCHING2_REQUEST_EVENT_SendLobbyChatMessage = 0x0203, - SCE_NP_MATCHING2_REQUEST_EVENT_SendLobbyInvitation = 0x0204, - SCE_NP_MATCHING2_REQUEST_EVENT_SetLobbyMemberDataInternal = 0x0205, - SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyMemberDataInternal = 0x0206, - SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyMemberDataInternalList = 0x0207, - SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo = 0x0e01, -}; - -// Based on decompiled np_matching2.prx, commented with syscalls where the event id is being used -#define PSP_NP_MATCHING2_EVENT_0001 0x0001 // GetServerInfo -#define PSP_NP_MATCHING2_EVENT_0002 0x0002 // GetWorldInfoList -#define PSP_NP_MATCHING2_EVENT_0003 0x0003 // SetUserInfo -#define PSP_NP_MATCHING2_EVENT_0004 0x0004 // GetUserInfoList -#define PSP_NP_MATCHING2_EVENT_0005 0x0005 // GetRoomMemberDataExternalList -#define PSP_NP_MATCHING2_EVENT_0006 0x0006 // SetRoomDataExternal -#define PSP_NP_MATCHING2_EVENT_0007 0x0007 // GetRoomDataExternalList - -#define PSP_NP_MATCHING2_EVENT_0101 0x0101 // CreateJoinRoom -#define PSP_NP_MATCHING2_EVENT_0102 0x0102 // JoinRoom -#define PSP_NP_MATCHING2_EVENT_0103 0x0103 // LeaveRoom -#define PSP_NP_MATCHING2_EVENT_0104 0x0104 // GrantRoomOwner -#define PSP_NP_MATCHING2_EVENT_0105 0x0105 // KickoutRoomMember -#define PSP_NP_MATCHING2_EVENT_0106 0x0106 // SearchRoom -#define PSP_NP_MATCHING2_EVENT_0107 0x0107 // SendRoomChatMessage -#define PSP_NP_MATCHING2_EVENT_0108 0x0108 // SendRoomMessage, also used on various places (internal function) -#define PSP_NP_MATCHING2_EVENT_0109 0x0109 // SetRoomDataInternal -#define PSP_NP_MATCHING2_EVENT_010A 0x010A // GetRoomDataInternal -#define PSP_NP_MATCHING2_EVENT_010B 0x010B // SetRoomMemberDataInternal -#define PSP_NP_MATCHING2_EVENT_010C 0x010C // GetRoomMemberDataInternal -#define PSP_NP_MATCHING2_EVENT_010D 0x010D // GetRoomMemberDataInternalList -#define PSP_NP_MATCHING2_EVENT_010E 0x010E // SetSignalingOptParam - -#define PSP_NP_MATCHING2_EVENT_A102 0xA102 // Used on various places (internal function) - -// Either this is an ID, state/status, flags, or might be size of data? -#define PSP_NP_MATCHING2_STATE_1001 0x1001 -#define PSP_NP_MATCHING2_STATE_1006 0x1006 -#define PSP_NP_MATCHING2_STATE_1007 0x1007 -#define PSP_NP_MATCHING2_STATE_1008 0x1008 - -#define PSP_NP_MATCHING2_STATE_1200 0x1200 -#define PSP_NP_MATCHING2_STATE_1206 0x1206 -#define PSP_NP_MATCHING2_STATE_1207 0x1207 -#define PSP_NP_MATCHING2_STATE_1208 0x1208 -#define PSP_NP_MATCHING2_STATE_1209 0x1209 -#define PSP_NP_MATCHING2_STATE_120B 0x120B -#define PSP_NP_MATCHING2_STATE_120C 0x120C - -#define PSP_NP_MATCHING2_STATE_3202 0x3202 -#define PSP_NP_MATCHING2_STATE_3203 0x3203 -#define PSP_NP_MATCHING2_STATE_3204 0x3204 -#define PSP_NP_MATCHING2_STATE_3205 0x3205 -#define PSP_NP_MATCHING2_STATE_3206 0x3206 -#define PSP_NP_MATCHING2_STATE_3207 0x3207 -#define PSP_NP_MATCHING2_STATE_3208 0x3208 -#define PSP_NP_MATCHING2_STATE_320A 0x320A -#define PSP_NP_MATCHING2_STATE_3210 0x3210 -#define PSP_NP_MATCHING2_STATE_3211 0x3211 - -#define PSP_NP_MATCHING2_MAX_CONTEXTID 7; - -struct NpMatching2Handler { - u32 entryPoint; - u32 argument; -}; - -// Arg1 and Arg2 seems to be a pair and predefined: 0x0001 with 0x1001, 0x0002 with 0x1008, 0x0003 with 0x1006, 0x0004 with 0x1007, -// 0x0005 with 0x1206, 0x0006 with 0x1207, 0x0007 with 0x1208, 0x0101 with 0x1209, 0x0102 with 0x1209, 0x0103 with 0x3202, -// 0x0104 with 0x3210, 0x0105 with 0x3211, 0x0106 with 2 possibilities (0x1200 and 0x120c), 0x0107 with 0x3208, 0x0108 with 0x320a, -// 0x0109 with 0x3204, 0x010a with 0x3205, 0x010b with 0x3206, 0x010c with 0x3207, 0x010d with 0x3203, 0x010e with 0x3204, -// 0xa102 with 0x120b. -// Arg5 seems to be boolean (0/1), mostly 0, conditional when Arg1=0x0001 -// Arg7 seems to be integer/state? (0..2), mostly 0, conditional when Arg1=0x0108 (0 on SendRoomMessage, 2 on others), 1 when Arg1=0xa102 -struct NpMatching2Args { - u32_le data[11]; // 7 elements (excluding optional data)? or may be 11 elements (including optional data)? - // May be followed by optional data? since these Args usually created on the stack -}; - #pragma pack(pop) @@ -675,4 +449,3 @@ void Register_sceNp(); void Register_sceNpService(); void Register_sceNpAuth(); void Register_sceNpCommerce2(); -void Register_sceNpMatching2(); diff --git a/Core/HLE/sceNp2.cpp b/Core/HLE/sceNp2.cpp new file mode 100644 index 0000000000..588471ba37 --- /dev/null +++ b/Core/HLE/sceNp2.cpp @@ -0,0 +1,566 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +// This is pretty much a stub implementation. Doesn't actually do anything, just tries to return values +// to keep games happy anyway. + +#include +#include "Core/MemMapHelpers.h" +#include +#include "Core/HLE/HLE.h" +#include "Core/HLE/FunctionWrappers.h" +#include "Core/HLE/sceNp.h" +#include "Core/HLE/sceNp2.h" + + +bool npMatching2Inited = false; +SceNpAuthMemoryStat npMatching2MemStat = {}; + +std::recursive_mutex npMatching2EvtMtx; +std::deque npMatching2Events; +std::map npMatching2Handlers; +//std::map npMatching2Contexts; + + +// serverId: 0 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d (ie. when already joined to a server?) +// unk1~unk5 usually 0, +// unk1: 1st 32-bit of LeaveRoom/etc's Arg2 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d/0x010e +// unk2: 2nd 32-bit of LeaveRoom/etc's Arg2 on 0x0103/0x0104/0x0105/0x0107/0x0108/0x0109/0x010a/0x010b/0x010c/0x010d/0x010e +// unk5: 1 on 0x0002/0x0003/0x0005/0x0006/0x0007/0x0101/0x0102/0x0106 +// unk6 (new state?): 8-bit?(masked with 0xff) 0x01 on 0x0001, 0x03 on 0x0002, 0x04 on 0x0003, 0x05 on 0x0004, 0x06 on 0x0005, 0x07 on 0x0006, 0x08 on 0x0007, +// 0x09 on 0x0101, 0x0A on 0x0102, 0x0C on 0x0103, 0x0D on 0x0104, 0x0E on 0x0105, 0x0F on 0x0106, 0x10 on 0x0107, 0x11 on 0x0108, +// 0x12 on 0x0109, 0x13 on 0x010a, 0x14 on 0x010b, 0x15 on 0x010c, 0x16 on 0x010d, 0x17 on 0x010e, 0x18 on 0xa102 +void notifyNpMatching2Handlers(NpMatching2Args &args, u32 ctxId, u32 serverId, u32 cbFuncAddr, u32 cbArgAddr, u32 unk3, u32 unk4, u32 unk5, u8 unk6) { + std::lock_guard npMatching2Guard(npMatching2EvtMtx); + // TODO: separate/map each list per ctxId + npMatching2Events.push_back(args); +} + +static int sceNpMatching2Init(int poolSize, int threadPriority, int cpuAffinityMask, int threadStackSize) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %d, %d, %d) at %08x", __FUNCTION__, poolSize, threadPriority, cpuAffinityMask, threadStackSize, currentMIPS->pc); + //if (npMatching2Inited) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_ALREADY_INITIALIZED); + + npMatching2MemStat.npMemSize = poolSize - 0x20; + npMatching2MemStat.npMaxMemSize = 0x4050; // Dummy maximum foot print + npMatching2MemStat.npFreeMemSize = npMatching2MemStat.npMemSize; + + npMatching2Handlers.clear(); + npMatching2Events.clear(); + npMatching2Inited = true; + return 0; +} + +static int sceNpMatching2Term() +{ + ERROR_LOG(SCENET, "UNIMPL %s() at %08x", __FUNCTION__, currentMIPS->pc); + npMatching2Inited = false; + npMatching2Handlers.clear(); + npMatching2Events.clear(); + + return 0; +} + +static int sceNpMatching2CreateContext(u32 communicationIdPtr, u32 passPhrasePtr, u32 ctxIdPtr, int unknown) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%08x[%s], %08x[%08x], %08x[%d], %d) at %08x", __FUNCTION__, communicationIdPtr, Memory::GetCharPointer(communicationIdPtr), passPhrasePtr, Memory::Read_U32(passPhrasePtr), ctxIdPtr, Memory::Read_U16(ctxIdPtr), unknown, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(communicationIdPtr) || !Memory::IsValidAddress(passPhrasePtr) || !Memory::IsValidAddress(ctxIdPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); + + // FIXME: It seems Context are mapped to TitleID? may return 0x80550C05 or 0x80550C06 when finding an existing context + SceNpCommunicationId* titleid = (SceNpCommunicationId*)Memory::GetCharPointer(communicationIdPtr); + memcpy(npTitleId.data, titleid->data, sizeof(npTitleId)); + + SceNpCommunicationPassphrase* passph = (SceNpCommunicationPassphrase*)Memory::GetCharPointer(passPhrasePtr); + + SceNpId npid{}; + int retval = NpGetNpId(&npid); + if (retval < 0) + return hleLogError(SCENET, retval); + + INFO_LOG(SCENET, "%s - Title ID: %s", __FUNCTION__, titleid->data); + INFO_LOG(SCENET, "%s - Online ID: %s", __FUNCTION__, npid.handle.data); + std::string datahex; + DataToHexString(npid.opt, sizeof(npid.opt), &datahex); + INFO_LOG(SCENET, "%s - Options?: %s", __FUNCTION__, datahex.c_str()); + datahex.clear(); + DataToHexString(10, 0, passph->data, sizeof(passph->data), &datahex); + INFO_LOG(SCENET, "%s - Passphrase: \n%s", __FUNCTION__, datahex.c_str()); + + // TODO: Allocate & zeroed a memory of 68 bytes where npId (36 bytes) is copied to offset 8, offset 44 = 0x00026808, offset 48 = 0 + + // Returning dummy Id, a 16-bit variable according to JPCSP + // FIXME: It seems ctxId need to be in the range of 1 to 7 to be valid ? + Memory::Write_U16(1, ctxIdPtr); + return 0; +} + +static int sceNpMatching2ContextStart(int ctxId) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d) at %08x", __FUNCTION__, ctxId, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + //if (!npMatching2Ctx) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID + + //if (npMatching2Ctx.started) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_STARTED); + + // TODO: use sceNpGetUserProfile and check server availability using sceNpService_76867C01 + //npMatching2Ctx.started = true; + Url url("http://static-resource.np.community.playstation.net/np/resource/psp-title/" + std::string(npTitleId.data) + "_00/matching/" + std::string(npTitleId.data) + "_00-matching.xml"); + http::Client client; + http::RequestProgress progress; + if (!client.Resolve(url.Host().c_str(), url.Port())) { + return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP failed to resolve %s", url.Resource().c_str()); + } + + client.SetDataTimeout(20.0); + if (client.Connect()) { + char requestHeaders[4096]; + snprintf(requestHeaders, sizeof(requestHeaders), + "User-Agent: PS3Community-agent/1.0.0 libhttp/1.0.0\r\n"); + + DEBUG_LOG(SCENET, "GET URI: %s", url.ToString().c_str()); + http::RequestParams req(url.Resource(), "*/*"); + int err = client.SendRequest("GET", req, requestHeaders, &progress); + if (err < 0) { + client.Disconnect(); + return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP GET Error = %d", err); + } + + net::Buffer readbuf; + std::vector responseHeaders; + int code = client.ReadResponseHeaders(&readbuf, responseHeaders, &progress); + if (code != 200) { + client.Disconnect(); + return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "HTTP Error Code = %d", code); + } + + net::Buffer output; + int res = client.ReadResponseEntity(&readbuf, responseHeaders, &output, &progress); + if (res != 0) { + WARN_LOG(SCENET, "Unable to read HTTP response entity: %d", res); + } + client.Disconnect(); + + std::string entity; + size_t readBytes = output.size(); + output.Take(readBytes, &entity); + + // TODO: Use XML Parser to get the Tag and it's attributes instead of searching for keywords on the string + std::string text; + size_t ofs = entity.find("titleid="); + if (ofs == std::string::npos) + return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "titleid not found"); + + ofs += 9; + size_t ofs2 = entity.find('"', ofs); + text = entity.substr(ofs, ofs2-ofs); + INFO_LOG(SCENET, "%s - Title ID: %s", __FUNCTION__, text.c_str()); + + int i = 1; + while (true) { + ofs = entity.find("", ++ofs2); + if (ofs == std::string::npos) + return hleLogError(SCENET, SCE_NP_COMMUNITY_SERVER_ERROR_NO_SUCH_TITLE, "agent host not found"); + + ofs2 = entity.find("pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + //if (!npMatching2Ctx) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID + + //if (!npMatching2Ctx.started) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED); + + //TODO: Stop any in-progress HTTPClient communication used on sceNpMatching2ContextStart + //npMatching2Ctx.started = false; + + return 0; +} + +static int sceNpMatching2DestroyContext(int ctxId) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d) at %08x", __FUNCTION__, ctxId, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + //if (!npMatching2Ctx) + // return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND); //SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID + + // Remove callback handler + int handlerID = ctxId - 1; + if (npMatching2Handlers.find(handlerID) != npMatching2Handlers.end()) { + npMatching2Handlers.erase(handlerID); + WARN_LOG(SCENET, "%s: Deleted handler %d", __FUNCTION__, handlerID); + } + else { + ERROR_LOG(SCENET, "%s: Invalid Context ID %d", __FUNCTION__, ctxId); + } + + return 0; +} + +static int sceNpMatching2GetMemoryStat(u32 memStatPtr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%08x) at %08x", __FUNCTION__, memStatPtr, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(memStatPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT); + + Memory::WriteStruct(memStatPtr, &npMatching2MemStat); + + return 0; +} + +static int sceNpMatching2RegisterSignalingCallback(int ctxId, u32 callbackFunctionAddr, u32 callbackArgument) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x) at %08x", __FUNCTION__, ctxId, callbackFunctionAddr, callbackArgument, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (ctxId <= 0) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID); + + int id = ctxId - 1; + if (callbackFunctionAddr != 0) { + bool foundHandler = false; + + struct NpMatching2Handler handler; + memset(&handler, 0, sizeof(handler)); + + handler.entryPoint = callbackFunctionAddr; + handler.argument = callbackArgument; + + for (std::map::iterator it = npMatching2Handlers.begin(); it != npMatching2Handlers.end(); it++) { + if (it->second.entryPoint == handler.entryPoint) { + foundHandler = true; + id = it->first; + break; + } + } + + if (!foundHandler && Memory::IsValidAddress(handler.entryPoint)) { + npMatching2Handlers[id] = handler; + WARN_LOG(SCENET, "%s - Added handler(%08x, %08x) : %d", __FUNCTION__, handler.entryPoint, handler.argument, id); + } + else { + ERROR_LOG(SCENET, "%s - Same handler(%08x, %08x) already exists", __FUNCTION__, handler.entryPoint, handler.argument); + } + + //u32 dataLength = 4097; + //notifyNpMatching2Handlers(retval, dataLength, handler.argument); + + // callback struct have 57 * u32? where [0]=0, [40]=flags, [55]=callbackFunc, and [56]=callbackArgs? + //hleEnqueueCall(callbackFunctionAddr, 7, (u32*)Memory::GetPointer(callbackArgument), nullptr); // 7 args? since the callback handler is trying to use t2 register + } + return 0; +} + +static int sceNpMatching2GetServerIdListLocal(int ctxId, u32 serverIdsPtr, int maxServerIds) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %d) at %08x", __FUNCTION__, ctxId, serverIdsPtr, maxServerIds, currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(serverIdsPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT); + + // Returning dummy Id, a 16-bit variable according to JPCSP + for (int i = 0; i < maxServerIds; i++) + Memory::Write_U16(1234+i, serverIdsPtr+(i*2)); + + return maxServerIds; // dummy value +} + +// Unknown1 = optParam, unknown2 = assignedReqId according to https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/sceNp2.cpp ? +static int sceNpMatching2GetServerInfo(int ctxId, u32 serverIdPtr, u32 unknown1Ptr, u32 unknown2Ptr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x[%d], %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, serverIdPtr, Memory::Read_U16(serverIdPtr), unknown1Ptr, unknown2Ptr, Memory::Read_U32(unknown2Ptr), currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(serverIdPtr) || !Memory::IsValidAddress(unknown2Ptr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? + + // Server ID is a 16-bit variable according to JPCSP + int serverId = Memory::Read_U16(serverIdPtr); + + if (serverId == 0) + return hleLogError(SCENET, 0x80550CBF); // Should be SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID ? + + // Output to unknown1(infoBuffer)? and unknown2(infoLength or flags)? + // Patapon 3 is using serverId at 09FFF2F4, unknown1 at 09FFF2E4, unknown2 at 09FFF2E0, which mean unknown1's can only fit upto 16-bytes + // Patapon 3 seems to be copying data from unknown1 with a fixed size of 20-bytes? + // input unknown1 struct: based on Fat Princess (US) + // 0000 32-bit function address (callback?) 0x08A08B40 + // 0004 32-bit pointer to a struct? (callback args?) 0x09888158 (contains 32-bit (-1) + 32-bit (1) + 16-bit ctxId(0001) + 32bit 0x06913801? + 16-bit serverId(1234), so on), probably only 2x 32-bit struct? + // 0008 32-bit set to 0 + // 000a 16-bit set to 0 + // + u32 cbFunc = Memory::Read_U32(unknown1Ptr); + u32 cbArg = Memory::Read_U32(unknown1Ptr + 0x04); + + // Notify callback handler + if (Memory::IsValidAddress(cbFunc)) { + // The cbFunc seems to be storing s0~s4(s0 pointing to 0x0996DD58 containing data similar to 0x09888158 above on the 1st 2x 32-bit data, s1 seems to be ctxId, s2~s4=0xdeadbeef) into stack and use a0~t1 (6 args?): + // Arg1(a0) & Arg3(a2) are being masked with 0xffff (16-bit id?) + // This callback tried to load data from address 0x08BD4860+8 (not part of arg? which being set using content of unknown2 not long after returning from sceNpMatching2GetServerInfo, so we may need to give some delay before calling this callback) + // and comparing it with Arg2(a1), repeated by increasing the address 0x08BD4860 by 288 bytes on each loop for 64 times or until it found a matching one. + // When a match is found the callback will process the address further, otherwise exit the callback. + // Matching address struct: (zeroed before calling sceNpMatching2GetServerInfo? and set after returning from sceNpMatching2GetServerInfo?) + // 0000 32-bit func address (another callback?) 0x08A07EF4 + // 0008 32-bit value from unknown2 content, being set not long after returning from sceNpMatching2GetServerInfo + // 000c 32-bit unknown + // 0010 8-bit status to indicate not updated from callback yet? initially 0, set to 1 not long after returning from sceNpMatching2GetServerInfo (along with unknown2 content) + // + // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere + NpMatching2Args args = {}; + args.data[0] = PSP_NP_MATCHING2_EVENT_0001; + args.data[1] = PSP_NP_MATCHING2_STATE_1001; // or size of data? + args.data[2] = serverIdPtr; // serverId or was it pointing to optional data at last arg (ie. args[10] where serverId is stored)? + args.data[3] = unknown1Ptr; + //args.data[4] = a boolean(0/1) related to a u8 value from the struct at args[9] (value XOR 0x04 == 0) + args.data[5] = unknown2Ptr; + args.data[6] = 0; + //args.data[8] = 0 or a pointer to a struct related to context? + //args.data[9] = 0 or a pointer to a struct related to context and matched serverId? + //args.data[10] = serverId; + + notifyNpMatching2Handlers(args, ctxId, serverId, 0, 0, 0, 0, 0, 1); + + Memory::Write_U32(args.data[1], unknown2Ptr); // server status or flags? + } + + // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? + return 0; +} + +static int sceNpMatching2LeaveRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? + + u32 cbFunc = Memory::Read_U32(reqParamPtr); + u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); + + // Notify callback handler + if (Memory::IsValidAddress(cbFunc)) { + // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere + NpMatching2Args args = {}; + args.data[0] = PSP_NP_MATCHING2_EVENT_0103; + args.data[1] = PSP_NP_MATCHING2_STATE_3202; + //args.data[2] = pointer to arg[8], where the 1st 20 bytes copied from (reqParamPtr+0x08), the rest of the struct are zeroed + args.data[3] = optParamPtr; + args.data[4] = 0; + args.data[5] = assignedReqIdPtr; + args.data[6] = 0; + //args.data[8] = an initially zeroed struct of 536 bytes where the 1st 20 bytes were taken from reqParam offset 0x08 + + notifyNpMatching2Handlers(args, ctxId, 0, cbFunc, cbArg, 0, 0, 0, 0x0c); + + Memory::Write_U32(args.data[1], assignedReqIdPtr); + } + + // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? + return 0; +} + +static int sceNpMatching2JoinRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 unknown1, u32 unknown2, u32 assignedReqIdPtr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? + + // Server ID is a 16-bit variable according to JPCSP + int serverId = Memory::Read_U16(reqParamPtr + 0x06); + + if (serverId == 0) + return hleLogError(SCENET, 0x80550CBF); // Should be SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID ? + + u32 cbFunc = Memory::Read_U32(reqParamPtr); + u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); + + // Notify callback handler + if (Memory::IsValidAddress(cbFunc)) { + // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere + NpMatching2Args args = {}; + args.data[0] = PSP_NP_MATCHING2_EVENT_0102; + args.data[1] = PSP_NP_MATCHING2_STATE_1209; + //args.data[2] = pointer to arg[8] (optional data?) + args.data[3] = optParamPtr; + args.data[4] = 0; + args.data[5] = assignedReqIdPtr; + args.data[6] = 0; + // Followed by optional data? + args.data[8] = reqParamPtr; // an initially zeroed struct of 1224 bytes, where the 1st 32bit is set to reqParamPtr + args.data[9] = unknown1; + args.data[10] = unknown2; + + notifyNpMatching2Handlers(args, ctxId, serverId, 0, 0, 0, 0, 1, 0x0a); + + Memory::Write_U32(args.data[1], assignedReqIdPtr); + } + + // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? + return 0; +} + +static int sceNpMatching2SearchRoom(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? + + u32 cbFunc = Memory::Read_U32(reqParamPtr); + u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); + + // Notify callback handler + if (Memory::IsValidAddress(cbFunc)) { + // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere + NpMatching2Args args = {}; + // TODO: Set the correct callback args + + Memory::Write_U32(args.data[1], assignedReqIdPtr); // server status or flags? + } + + return 0; +} + +static int sceNpMatching2SendRoomChatMessage(int ctxId, u32 reqParamPtr, u32 optParamPtr, u32 assignedReqIdPtr) +{ + ERROR_LOG(SCENET, "UNIMPL %s(%d, %08x, %08x, %08x[%08x]) at %08x", __FUNCTION__, ctxId, reqParamPtr, optParamPtr, assignedReqIdPtr, Memory::Read_U32(assignedReqIdPtr), currentMIPS->pc); + if (!npMatching2Inited) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED); + + if (!Memory::IsValidAddress(reqParamPtr) || !Memory::IsValidAddress(assignedReqIdPtr)) + return hleLogError(SCENET, SCE_NP_MATCHING2_ERROR_CONTEXT_MAX); // Should be SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT ? + + u32 cbFunc = Memory::Read_U32(reqParamPtr); + u32 cbArg = Memory::Read_U32(reqParamPtr + 0x04); + + // Notify callback handler + if (Memory::IsValidAddress(cbFunc)) { + // There args are supposed to be constructed in the stack and the data need to be available even after returning from this function, so these args + optional data probably copied to somewhere + NpMatching2Args args = {}; + args.data[0] = PSP_NP_MATCHING2_EVENT_0107; + args.data[1] = PSP_NP_MATCHING2_STATE_3208; + //args.data[2] = pointer to arg[8] + args.data[3] = optParamPtr; + args.data[4] = 0; + args.data[5] = assignedReqIdPtr; + args.data[6] = 0; + //args.data[8] = reqParamPtr; + + notifyNpMatching2Handlers(args, ctxId, 0, cbFunc, cbArg, 0, 0, 0, 0x10); + + Memory::Write_U32(args.data[1], assignedReqIdPtr); // server status or flags? + } + + // After returning, Fat Princess will loop for 64 times (increasing the address by 288 bytes on each loop) or until found a zero status byte (0x08BD4860 + 0x10), looking for empty/available entry to set? + return 0; +} + +const HLEFunction sceNpMatching2[] = { + {0x2E61F6E1, &WrapI_IIII, "sceNpMatching2Init", 'i', "iiii" }, + {0x8BF37D8C, &WrapI_V, "sceNpMatching2Term", 'i', "" }, + {0x5030CC53, &WrapI_UUUI, "sceNpMatching2CreateContext", 'i', "xxxi" }, + {0x190FF903, &WrapI_I, "sceNpMatching2ContextStart", 'i', "i" }, + {0x2B3892FC, &WrapI_I, "sceNpMatching2ContextStop", 'i', "i" }, + {0x3DE70241, &WrapI_I, "sceNpMatching2DestroyContext", 'i', "i" }, + {0x22F38DAF, &WrapI_U, "sceNpMatching2GetMemoryStat", 'i', "x" }, + {0xA3C298D1, &WrapI_IUU, "sceNpMatching2RegisterSignalingCallback", 'i', "ixx" }, + {0xF47342FC, &WrapI_IUI, "sceNpMatching2GetServerIdListLocal", 'i', "ixi" }, + {0x4EE3A8EC, &WrapI_IUUU, "sceNpMatching2GetServerInfo", 'i', "ixxx" }, + {0xC870535A, &WrapI_IUUU, "sceNpMatching2LeaveRoom", 'i', "ixxx" }, + {0xAAD0946A, &WrapI_IUUUUU, "sceNpMatching2JoinRoom", 'i', "ixxxxx" }, + {0x81C13E6D, &WrapI_IUUU, "sceNpMatching2SearchRoom", 'i', "ixxx" }, + {0x55F7837F, &WrapI_IUUU, "sceNpMatching2SendRoomChatMessage", 'i', "ixxx" }, +}; + +void Register_sceNpMatching2() +{ + RegisterModule("sceNpMatching2", ARRAY_SIZE(sceNpMatching2), sceNpMatching2); +} diff --git a/Core/HLE/sceNp2.h b/Core/HLE/sceNp2.h new file mode 100644 index 0000000000..712688f22d --- /dev/null +++ b/Core/HLE/sceNp2.h @@ -0,0 +1,254 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + + +#pragma pack(push,1) + +// Based on https://gist.githubusercontent.com/raw/4140449/PS%20Vita (Might be slightly different with PSP?) +#define SCE_NP_MATCHING2_ERROR_OUT_OF_MEMORY 0x80550c01 +#define SCE_NP_MATCHING2_ERROR_ALREADY_INITIALIZED 0x80550c02 +#define SCE_NP_MATCHING2_ERROR_NOT_INITIALIZED 0x80550c03 +#define SCE_NP_MATCHING2_ERROR_CONTEXT_MAX 0x80550c04 // might be "Invalid Argument" on PSP? +#define SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_EXISTS 0x80550c05 // might be "Context Max/Context Id higher than 7" on PSP? +#define SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_FOUND 0x80550c06 +#define SCE_NP_MATCHING2_ERROR_CONTEXT_ALREADY_STARTED 0x80550c07 +#define SCE_NP_MATCHING2_ERROR_CONTEXT_NOT_STARTED 0x80550c08 +#define SCE_NP_MATCHING2_ERROR_SERVER_NOT_FOUND 0x80550c09 +#define SCE_NP_MATCHING2_ERROR_INVALID_ARGUMENT 0x80550c0a +#define SCE_NP_MATCHING2_ERROR_INVALID_CONTEXT_ID 0x80550c0b +#define SCE_NP_MATCHING2_ERROR_INVALID_SERVER_ID 0x80550c0c +#define SCE_NP_MATCHING2_ERROR_INVALID_LOBBY_ID 0x80550c0e +#define SCE_NP_MATCHING2_ERROR_INVALID_ROOM_ID 0x80550c0f +#define SCE_NP_MATCHING2_ERROR_INVALID_MEMBER_ID 0x80550c10 +#define SCE_NP_MATCHING2_ERROR_INVALID_ATTRIBUTE_ID 0x80550c11 +#define SCE_NP_MATCHING2_ERROR_INVALID_CASTTYPE 0x80550c12 +#define SCE_NP_MATCHING2_ERROR_INVALID_SORT_METHOD 0x80550c13 +#define SCE_NP_MATCHING2_ERROR_INVALID_MAX_SLOT 0x80550c14 +#define SCE_NP_MATCHING2_ERROR_INVALID_OPT_SIZE 0x80550c15 +#define SCE_NP_MATCHING2_ERROR_INVALID_MATCHING_SPACE 0x80550c16 +#define SCE_NP_MATCHING2_ERROR_INVALID_BLOCK_KICK_FLAG 0x80550c18 +#define SCE_NP_MATCHING2_ERROR_INVALID_MESSAGE_TARGET 0x80550c19 +#define SCE_NP_MATCHING2_ERROR_RANGE_FILTER_MAX 0x80550c1a +#define SCE_NP_MATCHING2_ERROR_INVALID_ALIGNMENT 0x80550c1e +#define SCE_NP_MATCHING2_ERROR_CONNECTION_CLOSED_BY_SERVER 0x80550c22 +#define SCE_NP_MATCHING2_ERROR_SSL_VERIFY_FAILED 0x80550c23 +#define SCE_NP_MATCHING2_ERROR_SSL_HANDSHAKE 0x80550c24 +#define SCE_NP_MATCHING2_ERROR_SSL_SEND 0x80550c25 +#define SCE_NP_MATCHING2_ERROR_SSL_RECV 0x80550c26 +#define SCE_NP_MATCHING2_ERROR_JOINED_SESSION_MAX 0x80550c27 +#define SCE_NP_MATCHING2_ERROR_ALREADY_JOINED 0x80550c28 +#define SCE_NP_MATCHING2_ERROR_INVALID_SESSION_TYPE 0x80550c29 +#define SCE_NP_MATCHING2_ERROR_NP_SIGNED_OUT 0x80550c2b +#define SCE_NP_MATCHING2_ERROR_BUSY 0x80550c2c +#define SCE_NP_MATCHING2_ERROR_SERVER_NOT_AVAILABLE 0x80550c2d +#define SCE_NP_MATCHING2_ERROR_NOT_ALLOWED 0x80550c2e +#define SCE_NP_MATCHING2_ERROR_ABORTED 0x80550c2f +#define SCE_NP_MATCHING2_ERROR_REQUEST_NOT_FOUND 0x80550c30 +#define SCE_NP_MATCHING2_ERROR_SESSION_DESTROYED 0x80550c31 +#define SCE_NP_MATCHING2_ERROR_CONTEXT_STOPPED 0x80550c32 +#define SCE_NP_MATCHING2_ERROR_INVALID_REQUEST_PARAMETER 0x80550c33 +#define SCE_NP_MATCHING2_ERROR_NOT_NP_SIGN_IN 0x80550c34 +#define SCE_NP_MATCHING2_ERROR_ROOM_NOT_FOUND 0x80550c35 +#define SCE_NP_MATCHING2_ERROR_ROOM_MEMBER_NOT_FOUND 0x80550c36 +#define SCE_NP_MATCHING2_ERROR_LOBBY_NOT_FOUND 0x80550c37 +#define SCE_NP_MATCHING2_ERROR_LOBBY_MEMBER_NOT_FOUND 0x80550c38 +#define SCE_NP_MATCHING2_ERROR_KEEPALIVE_TIMEOUT 0x80550c3a +#define SCE_NP_MATCHING2_ERROR_TIMEOUT_TOO_SHORT 0x80550c3b +#define SCE_NP_MATCHING2_ERROR_TIMEDOUT 0x80550c3c +#define SCE_NP_MATCHING2_ERROR_INVALID_SLOTGROUP 0x80550c3d +#define SCE_NP_MATCHING2_ERROR_INVALID_ATTRIBUTE_SIZE 0x80550c3e +#define SCE_NP_MATCHING2_ERROR_CANNOT_ABORT 0x80550c3f +#define SCE_NP_MATCHING2_ERROR_SESSION_NOT_FOUND 0x80550c40 + +#define SCE_NP_MATCHING2_SERVER_ERROR_BAD_REQUEST 0x80550d01 +#define SCE_NP_MATCHING2_SERVER_ERROR_SERVICE_UNAVAILABLE 0x80550d02 +#define SCE_NP_MATCHING2_SERVER_ERROR_BUSY 0x80550d03 +#define SCE_NP_MATCHING2_SERVER_ERROR_END_OF_SERVICE 0x80550d04 +#define SCE_NP_MATCHING2_SERVER_ERROR_INTERNAL_SERVER_ERROR 0x80550d05 +#define SCE_NP_MATCHING2_SERVER_ERROR_PLAYER_BANNED 0x80550d06 +#define SCE_NP_MATCHING2_SERVER_ERROR_FORBIDDEN 0x80550d07 +#define SCE_NP_MATCHING2_SERVER_ERROR_BLOCKED 0x80550d08 +#define SCE_NP_MATCHING2_SERVER_ERROR_UNSUPPORTED_NP_ENV 0x80550d09 +#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_TICKET 0x80550d0a +#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_SIGNATURE 0x80550d0b +#define SCE_NP_MATCHING2_SERVER_ERROR_EXPIRED_TICKET 0x80550d0c +#define SCE_NP_MATCHING2_SERVER_ERROR_ENTITLEMENT_REQUIRED 0x80550d0d +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_CONTEXT 0x80550d0e +#define SCE_NP_MATCHING2_SERVER_ERROR_CLOSED 0x80550d0f +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_TITLE 0x80550d10 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_WORLD 0x80550d11 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_LOBBY 0x80550d12 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM 0x80550d13 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_LOBBY_INSTANCE 0x80550d14 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_ROOM_INSTANCE 0x80550d15 +#define SCE_NP_MATCHING2_SERVER_ERROR_PASSWORD_MISMATCH 0x80550d17 +#define SCE_NP_MATCHING2_SERVER_ERROR_LOBBY_FULL 0x80550d18 +#define SCE_NP_MATCHING2_SERVER_ERROR_ROOM_FULL 0x80550d19 +#define SCE_NP_MATCHING2_SERVER_ERROR_GROUP_FULL 0x80550d1b +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_USER 0x80550d1c +#define SCE_NP_MATCHING2_SERVER_ERROR_TITLE_PASSPHRASE_MISMATCH 0x80550d1e +#define SCE_NP_MATCHING2_SERVER_ERROR_CONSOLE_BANNED 0x80550d28 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_ROOMGROUP 0x80550d29 +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_SUCH_GROUP 0x80550d2a +#define SCE_NP_MATCHING2_SERVER_ERROR_NO_PASSWORD 0x80550d2b +#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_GROUP_SLOT_NUM 0x80550d2c +#define SCE_NP_MATCHING2_SERVER_ERROR_INVALID_PASSWORD_SLOT_MASK 0x80550d2d +#define SCE_NP_MATCHING2_SERVER_ERROR_DUPLICATE_GROUP_LABEL 0x80550d2e +#define SCE_NP_MATCHING2_SERVER_ERROR_REQUEST_OVERFLOW 0x80550d2f +#define SCE_NP_MATCHING2_SERVER_ERROR_ALREADY_JOINED 0x80550d30 +#define SCE_NP_MATCHING2_SERVER_ERROR_NAT_TYPE_MISMATCH 0x80550d31 +#define SCE_NP_MATCHING2_SERVER_ERROR_ROOM_INCONSISTENCY 0x80550d32 + +#define SCE_NP_MATCHING2_SIGNALING_ERROR_NOT_INITIALIZED 0x80550e01 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_ALREADY_INITIALIZED 0x80550e02 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_OUT_OF_MEMORY 0x80550e03 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTXID_NOT_AVAILABLE 0x80550e04 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTX_NOT_FOUND 0x80550e05 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_REQID_NOT_AVAILABLE 0x80550e06 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_REQ_NOT_FOUND 0x80550e07 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_PARSER_CREATE_FAILED 0x80550e08 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_PARSER_FAILED 0x80550e09 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_INVALID_NAMESPACE 0x80550e0a +#define SCE_NP_MATCHING2_SIGNALING_ERROR_NETINFO_NOT_AVAILABLE 0x80550e0b +#define SCE_NP_MATCHING2_SIGNALING_ERROR_PEER_NOT_RESPONDING 0x80550e0c +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONNID_NOT_AVAILABLE 0x80550e0d +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONN_NOT_FOUND 0x80550e0e +#define SCE_NP_MATCHING2_SIGNALING_ERROR_PEER_UNREACHABLE 0x80550e0f +#define SCE_NP_MATCHING2_SIGNALING_ERROR_TERMINATED_BY_PEER 0x80550e10 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_TIMEOUT 0x80550e11 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CTX_MAX 0x80550e12 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_RESULT_NOT_FOUND 0x80550e13 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_CONN_IN_PROGRESS 0x80550e14 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_INVALID_ARGUMENT 0x80550e15 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_OWN_NP_ID 0x80550e16 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_TOO_MANY_CONN 0x80550e17 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_TERMINATED_BY_MYSELF 0x80550e18 +#define SCE_NP_MATCHING2_SIGNALING_ERROR_MATCHING2_PEER_NOT_FOUND 0x80550e19 + +// Based on https://github.com/RPCS3/rpcs3/blob/master/rpcs3/Emu/Cell/Modules/sceNp2.h (Just as reference, might be slightly different than PSP) +// Event of request functions +enum PS3Matching2RequestEvent +{ + SCE_NP_MATCHING2_REQUEST_EVENT_GetServerInfo = 0x0001, + SCE_NP_MATCHING2_REQUEST_EVENT_GetWorldInfoList = 0x0002, + SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataExternalList = 0x0003, + SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataExternal = 0x0004, + SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataExternalList = 0x0005, + SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyInfoList = 0x0006, + SCE_NP_MATCHING2_REQUEST_EVENT_SetUserInfo = 0x0007, + SCE_NP_MATCHING2_REQUEST_EVENT_GetUserInfoList = 0x0008, + SCE_NP_MATCHING2_REQUEST_EVENT_CreateServerContext = 0x0009, + SCE_NP_MATCHING2_REQUEST_EVENT_DeleteServerContext = 0x000a, + SCE_NP_MATCHING2_REQUEST_EVENT_CreateJoinRoom = 0x0101, + SCE_NP_MATCHING2_REQUEST_EVENT_JoinRoom = 0x0102, + SCE_NP_MATCHING2_REQUEST_EVENT_LeaveRoom = 0x0103, + SCE_NP_MATCHING2_REQUEST_EVENT_GrantRoomOwner = 0x0104, + SCE_NP_MATCHING2_REQUEST_EVENT_KickoutRoomMember = 0x0105, + SCE_NP_MATCHING2_REQUEST_EVENT_SearchRoom = 0x0106, + SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomChatMessage = 0x0107, + SCE_NP_MATCHING2_REQUEST_EVENT_SendRoomMessage = 0x0108, + SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomDataInternal = 0x0109, + SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomDataInternal = 0x010a, + SCE_NP_MATCHING2_REQUEST_EVENT_SetRoomMemberDataInternal = 0x010b, + SCE_NP_MATCHING2_REQUEST_EVENT_GetRoomMemberDataInternal = 0x010c, + SCE_NP_MATCHING2_REQUEST_EVENT_SetSignalingOptParam = 0x010d, + SCE_NP_MATCHING2_REQUEST_EVENT_JoinLobby = 0x0201, + SCE_NP_MATCHING2_REQUEST_EVENT_LeaveLobby = 0x0202, + SCE_NP_MATCHING2_REQUEST_EVENT_SendLobbyChatMessage = 0x0203, + SCE_NP_MATCHING2_REQUEST_EVENT_SendLobbyInvitation = 0x0204, + SCE_NP_MATCHING2_REQUEST_EVENT_SetLobbyMemberDataInternal = 0x0205, + SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyMemberDataInternal = 0x0206, + SCE_NP_MATCHING2_REQUEST_EVENT_GetLobbyMemberDataInternalList = 0x0207, + SCE_NP_MATCHING2_REQUEST_EVENT_SignalingGetPingInfo = 0x0e01, +}; + +// Based on decompiled np_matching2.prx, commented with syscalls where the event id is being used +#define PSP_NP_MATCHING2_EVENT_0001 0x0001 // GetServerInfo +#define PSP_NP_MATCHING2_EVENT_0002 0x0002 // GetWorldInfoList +#define PSP_NP_MATCHING2_EVENT_0003 0x0003 // SetUserInfo +#define PSP_NP_MATCHING2_EVENT_0004 0x0004 // GetUserInfoList +#define PSP_NP_MATCHING2_EVENT_0005 0x0005 // GetRoomMemberDataExternalList +#define PSP_NP_MATCHING2_EVENT_0006 0x0006 // SetRoomDataExternal +#define PSP_NP_MATCHING2_EVENT_0007 0x0007 // GetRoomDataExternalList + +#define PSP_NP_MATCHING2_EVENT_0101 0x0101 // CreateJoinRoom +#define PSP_NP_MATCHING2_EVENT_0102 0x0102 // JoinRoom +#define PSP_NP_MATCHING2_EVENT_0103 0x0103 // LeaveRoom +#define PSP_NP_MATCHING2_EVENT_0104 0x0104 // GrantRoomOwner +#define PSP_NP_MATCHING2_EVENT_0105 0x0105 // KickoutRoomMember +#define PSP_NP_MATCHING2_EVENT_0106 0x0106 // SearchRoom +#define PSP_NP_MATCHING2_EVENT_0107 0x0107 // SendRoomChatMessage +#define PSP_NP_MATCHING2_EVENT_0108 0x0108 // SendRoomMessage, also used on various places (internal function) +#define PSP_NP_MATCHING2_EVENT_0109 0x0109 // SetRoomDataInternal +#define PSP_NP_MATCHING2_EVENT_010A 0x010A // GetRoomDataInternal +#define PSP_NP_MATCHING2_EVENT_010B 0x010B // SetRoomMemberDataInternal +#define PSP_NP_MATCHING2_EVENT_010C 0x010C // GetRoomMemberDataInternal +#define PSP_NP_MATCHING2_EVENT_010D 0x010D // GetRoomMemberDataInternalList +#define PSP_NP_MATCHING2_EVENT_010E 0x010E // SetSignalingOptParam + +#define PSP_NP_MATCHING2_EVENT_A102 0xA102 // Used on various places (internal function) + +// Either this is an ID, state/status, flags, or might be size of data? +#define PSP_NP_MATCHING2_STATE_1001 0x1001 +#define PSP_NP_MATCHING2_STATE_1006 0x1006 +#define PSP_NP_MATCHING2_STATE_1007 0x1007 +#define PSP_NP_MATCHING2_STATE_1008 0x1008 + +#define PSP_NP_MATCHING2_STATE_1200 0x1200 +#define PSP_NP_MATCHING2_STATE_1206 0x1206 +#define PSP_NP_MATCHING2_STATE_1207 0x1207 +#define PSP_NP_MATCHING2_STATE_1208 0x1208 +#define PSP_NP_MATCHING2_STATE_1209 0x1209 +#define PSP_NP_MATCHING2_STATE_120B 0x120B +#define PSP_NP_MATCHING2_STATE_120C 0x120C + +#define PSP_NP_MATCHING2_STATE_3202 0x3202 +#define PSP_NP_MATCHING2_STATE_3203 0x3203 +#define PSP_NP_MATCHING2_STATE_3204 0x3204 +#define PSP_NP_MATCHING2_STATE_3205 0x3205 +#define PSP_NP_MATCHING2_STATE_3206 0x3206 +#define PSP_NP_MATCHING2_STATE_3207 0x3207 +#define PSP_NP_MATCHING2_STATE_3208 0x3208 +#define PSP_NP_MATCHING2_STATE_320A 0x320A +#define PSP_NP_MATCHING2_STATE_3210 0x3210 +#define PSP_NP_MATCHING2_STATE_3211 0x3211 + +#define PSP_NP_MATCHING2_MAX_CONTEXTID 7; + +struct NpMatching2Handler { + u32 entryPoint; + u32 argument; +}; + +// Arg1 and Arg2 seems to be a pair and predefined: 0x0001 with 0x1001, 0x0002 with 0x1008, 0x0003 with 0x1006, 0x0004 with 0x1007, +// 0x0005 with 0x1206, 0x0006 with 0x1207, 0x0007 with 0x1208, 0x0101 with 0x1209, 0x0102 with 0x1209, 0x0103 with 0x3202, +// 0x0104 with 0x3210, 0x0105 with 0x3211, 0x0106 with 2 possibilities (0x1200 and 0x120c), 0x0107 with 0x3208, 0x0108 with 0x320a, +// 0x0109 with 0x3204, 0x010a with 0x3205, 0x010b with 0x3206, 0x010c with 0x3207, 0x010d with 0x3203, 0x010e with 0x3204, +// 0xa102 with 0x120b. +// Arg5 seems to be boolean (0/1), mostly 0, conditional when Arg1=0x0001 +// Arg7 seems to be integer/state? (0..2), mostly 0, conditional when Arg1=0x0108 (0 on SendRoomMessage, 2 on others), 1 when Arg1=0xa102 +struct NpMatching2Args { + u32_le data[11]; // 7 elements (excluding optional data)? or may be 11 elements (including optional data)? + // May be followed by optional data? since these Args usually created on the stack +}; + +#pragma pack(pop) + + +void Register_sceNpMatching2(); diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 16863bd6e9..0777e28251 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -441,6 +441,7 @@ + @@ -677,6 +678,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 6ceb09e6b5..b1f23b19fb 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -1115,6 +1115,9 @@ + + HLE + @@ -1761,6 +1764,9 @@ + + HLE + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 33db892245..a0c9774d37 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -518,6 +518,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/HLE/scePspNpDrm_user.cpp \ $(SRC)/Core/HLE/sceGameUpdate.cpp \ $(SRC)/Core/HLE/sceNp.cpp \ + $(SRC)/Core/HLE/sceNp2.cpp \ $(SRC)/Core/HLE/scePauth.cpp \ $(SRC)/Core/FileSystems/BlobFileSystem.cpp \ $(SRC)/Core/FileSystems/BlockDevices.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index dca3bde0d1..9143600e09 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -547,6 +547,7 @@ SOURCES_CXX += \ $(COREDIR)/HLE/sceVaudio.cpp \ $(COREDIR)/HLE/scePspNpDrm_user.cpp \ $(COREDIR)/HLE/sceNp.cpp \ + $(COREDIR)/HLE/sceNp2.cpp \ $(COREDIR)/HLE/scePauth.cpp \ $(COREDIR)/HLE/sceUsbGps.cpp \ $(COREDIR)/HW/BufferQueue.cpp \