From a1accc87d4f744b1f84829c12e56f552a9a024f0 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Wed, 5 Jan 2022 12:12:18 +0700 Subject: [PATCH 1/6] Added comment related to EVENT_HELLO --- Core/HLE/proAdhoc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index e725950fa36a..f1e8e0dd06cf 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -732,7 +732,7 @@ enum { #define PSP_ADHOC_MATCHING_MODE_P2P 3 // Matching Events -#define PSP_ADHOC_MATCHING_EVENT_HELLO 1 +#define PSP_ADHOC_MATCHING_EVENT_HELLO 1 // Should be ignored when Join Request is in progress ? #define PSP_ADHOC_MATCHING_EVENT_REQUEST 2 #define PSP_ADHOC_MATCHING_EVENT_LEAVE 3 #define PSP_ADHOC_MATCHING_EVENT_DENY 4 From 03b6d1ed0137e1c7d25dbccfd357a7d3669f7ea1 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Wed, 5 Jan 2022 12:13:11 +0700 Subject: [PATCH 2/6] Updated MatchingArgs comment --- Core/HLE/sceNetAdhoc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceNetAdhoc.h b/Core/HLE/sceNetAdhoc.h index 9027012b850e..114e7cec726a 100644 --- a/Core/HLE/sceNetAdhoc.h +++ b/Core/HLE/sceNetAdhoc.h @@ -24,7 +24,7 @@ #pragma pack(push,1) #endif typedef struct MatchingArgs { - u32_le data[6]; //ContextID, Opcode, bufAddr[ to MAC], OptLen, OptAddr[, EntryPoint] + u32_le data[6]; // ContextID, EventID, bufAddr[ to MAC], OptLen, OptAddr[, EntryPoint] } PACK MatchingArgs; typedef struct SceNetAdhocDiscoverParam { From 0755dc0bbd42957b6a54bc83acf22f1dbaad6f28 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Wed, 5 Jan 2022 12:14:06 +0700 Subject: [PATCH 3/6] Updated notifyMatchingHandler comments --- Core/HLE/proAdhoc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 94b5fe205888..b2419a799096 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1241,7 +1241,7 @@ void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * // Don't share buffer address space with other mipscall in the queue since mipscalls aren't immediately executed MatchingArgs argsNew = { 0 }; u32_le dataBufLen = msg->optlen + 8; //max(bufLen, msg->optlen + 8); - u32_le dataBufAddr = userMemory.Alloc(dataBufLen); // We will free this memory after returning from mipscall + u32_le dataBufAddr = userMemory.Alloc(dataBufLen); // We will free this memory after returning from mipscall. FIXME: Are these buffers supposed to be taken/pre-allocated from the memory pool during sceNetAdhocMatchingInit? uint8_t * dataPtr = Memory::GetPointer(dataBufAddr); if (dataPtr) { memcpy(dataPtr, &msg->mac, sizeof(msg->mac)); @@ -1255,6 +1255,7 @@ void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage * } else { argsNew.data[1] = PSP_ADHOC_MATCHING_EVENT_ERROR; // not sure where to put the error code for EVENT_ERROR tho + //argsNew.data[2] = dataBufAddr; // FIXME: Is the MAC address mandatory (ie. can't be null pointer) even for EVENT_ERROR? Where should we put this MAC data in the case we failed to allocate the memory? may be on the memory pool? } argsNew.data[0] = context->id; argsNew.data[5] = context->handler.entryPoint; //not part of callback argument, just borrowing a space to store callback address so i don't need to search the context first later From 71f08a3db89bdfb7708509a70fce20f46c0d90c0 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Wed, 5 Jan 2022 12:22:11 +0700 Subject: [PATCH 4/6] Discard HELLO Events when in the middle of Joining --- Core/HLE/sceNetAdhoc.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 12bbe547525a..d6d91432fc91 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -5751,18 +5751,27 @@ void __NetMatchingCallbacks() //(int matchingId) auto params = matchingEvents.begin(); if (params != matchingEvents.end()) { u32_le *args = params->data; - //auto context = findMatchingContext(args[0]); + auto context = findMatchingContext(args[0]); if (actionAfterMatchingMipsCall < 0) { actionAfterMatchingMipsCall = __KernelRegisterActionType(AfterMatchingMipsCall::Create); } DEBUG_LOG(SCENET, "AdhocMatching - Remaining Events: %zu", matchingEvents.size()); - DEBUG_LOG(SCENET, "AdhocMatchingCallback: [ID=%i][EVENT=%i][%s]", args[0], args[1], mac2str((SceNetEtherAddr *)Memory::GetPointer(args[2])).c_str()); - AfterMatchingMipsCall *after = (AfterMatchingMipsCall *)__KernelCreateAction(actionAfterMatchingMipsCall); - after->SetData(args[0], args[1], args[2]); - hleEnqueueCall(args[5], 5, args, after); - matchingEvents.pop_front(); - delayus = adhocMatchingEventDelay; // Add extra delay to prevent I/O Timing method from causing disconnection, but delaying too long may cause matchingEvents to pile up + auto peer = findPeer(context, (SceNetEtherAddr*)Memory::GetPointer(args[2])); + // Discard HELLO Events when in the middle of joining, as some games (ie. Super Pocket Tennis) might tried to join again (TODO: Need to confirm whether sceNetAdhocMatchingSelectTarget supposed to be blocking the current thread or not) + if (peer == NULL || (args[1] != PSP_ADHOC_MATCHING_EVENT_HELLO || (peer->state != PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST && peer->state != PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST))) { + DEBUG_LOG(SCENET, "AdhocMatchingCallback: [ID=%i][EVENT=%i][%s]", args[0], args[1], mac2str((SceNetEtherAddr *)Memory::GetPointer(args[2])).c_str()); + + AfterMatchingMipsCall* after = (AfterMatchingMipsCall*)__KernelCreateAction(actionAfterMatchingMipsCall); + after->SetData(args[0], args[1], args[2]); + hleEnqueueCall(args[5], 5, args, after); + matchingEvents.pop_front(); + delayus = adhocMatchingEventDelay; // Add extra delay to prevent I/O Timing method from causing disconnection, but delaying too long may cause matchingEvents to pile up, and Super Pocket Tennis didn't like to wait for more than 5ms + } + else { + DEBUG_LOG(SCENET, "AdhocMatching - Discarding Callback: [ID=%i][EVENT=%i][%s]", args[0], args[1], mac2str((SceNetEtherAddr*)Memory::GetPointer(args[2])).c_str()); + matchingEvents.pop_front(); + } } // Must be delayed long enough whenever there is a pending callback. Should it be 10-100ms for Matching Events? or Not Less than the delays on sceNetAdhocMatching HLE? From bfd532561a4aae0979ccc201a5e4c75b1bab5aeb Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Thu, 20 Jan 2022 00:30:03 +0700 Subject: [PATCH 5/6] Report sceNetAdhocMatchingInit to find out a list of games that use AdhocMatching library to be tested with. --- Core/HLE/sceNetAdhoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index d6d91432fc91..4c2e5e46c073 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -4674,7 +4674,7 @@ int sceNetAdhocMatchingDelete(int matchingId) { } int sceNetAdhocMatchingInit(u32 memsize) { - WARN_LOG(SCENET, "sceNetAdhocMatchingInit(%d) at %08x", memsize, currentMIPS->pc); + WARN_LOG_REPORT_ONCE(sceNetAdhocMatchingInit, SCENET, "sceNetAdhocMatchingInit(%d) at %08x", memsize, currentMIPS->pc); // Uninitialized Library if (netAdhocMatchingInited) From fbb1246cfde425b2b18858870ad84167624b878a Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Thu, 20 Jan 2022 02:49:14 +0700 Subject: [PATCH 6/6] Reducing MatchingEvents processing delays. Fixes timing issue on a few games (Super Pocket Tennis, Thrillville Off the Rails, Lord of Arcana, Gundam: Senjou No Kizuna Portable, StarWars The Force Unleashed) --- Core/HLE/sceNetAdhoc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 4c2e5e46c073..a97fda72df07 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -5746,7 +5746,10 @@ void __NetMatchingCallbacks() //(int matchingId) { std::lock_guard adhocGuard(adhocEvtMtx); hleSkipDeadbeef(); - int delayus = adhocDefaultDelay; + // Note: Super Pocket Tennis / Thrillville Off the Rails seems to have a very short timeout (ie. ~5ms) while waiting for the event to arrived on the callback handler, but Lord of Arcana may not work well with 5ms (~3m or ~10ms seems to be good) + // Games with 4-players or more (ie. Gundam: Senjou No Kizuna Portable) will also need lower delay/latency (ie. ~3ms seems to be good, 2ms or lower doesn't work well) so MatchingEvents can be processed faster, thus won't be piling up in the queue. + // Using 3ms seems to fix Player list issue on StarWars The Force Unleashed. + int delayus = 3000; auto params = matchingEvents.begin(); if (params != matchingEvents.end()) { @@ -5766,7 +5769,6 @@ void __NetMatchingCallbacks() //(int matchingId) after->SetData(args[0], args[1], args[2]); hleEnqueueCall(args[5], 5, args, after); matchingEvents.pop_front(); - delayus = adhocMatchingEventDelay; // Add extra delay to prevent I/O Timing method from causing disconnection, but delaying too long may cause matchingEvents to pile up, and Super Pocket Tennis didn't like to wait for more than 5ms } else { DEBUG_LOG(SCENET, "AdhocMatching - Discarding Callback: [ID=%i][EVENT=%i][%s]", args[0], args[1], mac2str((SceNetEtherAddr*)Memory::GetPointer(args[2])).c_str());