From 0188920f226db06c007fa96db92e8504e51f42ca Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 9 Oct 2023 22:16:29 +0700 Subject: [PATCH 1/7] Allow TIMEOUT Event to intervene Joining process. --- Core/HLE/proAdhoc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 9a1cfc94bd..f876178231 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1048,10 +1048,12 @@ void handleTimeout(SceNetAdhocMatchingContext * context) // Timeout! Apparently the latest GetGlobalTimeUsScaled (ie. now) have a possibility to be smaller than previous GetGlobalTimeUsScaled (ie. lastping) thus resulting a negative number when subtracted :( if (peer->state != 0 && static_cast(now - peer->lastping) > static_cast(context->timeout)) { - // Spawn Timeout Event + // Spawn Timeout Event. FIXME: Should we allow TIMEOUT Event to intervene joining process of Parent-Child too just like P2P Mode? (ie. Crazy Taxi uses P2P Mode) if ((context->mode == PSP_ADHOC_MATCHING_MODE_CHILD && peer->state == PSP_ADHOC_MATCHING_PEER_PARENT) || (context->mode == PSP_ADHOC_MATCHING_MODE_PARENT && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) || - (context->mode == PSP_ADHOC_MATCHING_MODE_P2P && peer->state == PSP_ADHOC_MATCHING_PEER_P2P)) { + (context->mode == PSP_ADHOC_MATCHING_MODE_P2P && + (peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_OFFER || peer->state == PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS))) + { // FIXME: TIMEOUT event should only be triggered on Parent/P2P mode and for Parent/P2P peer? spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_TIMEOUT, &peer->mac, 0, NULL); From abb196766d181b6ee441daf6429ea7208d954779 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 9 Oct 2023 22:15:32 +0700 Subject: [PATCH 2/7] Allow BYE Event to intervene Joining process. --- Core/HLE/sceNetAdhoc.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 8040926214..2e593ffec2 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -5922,7 +5922,7 @@ void __NetMatchingCallbacks() //(int matchingId) DEBUG_LOG(SCENET, "AdhocMatching - Remaining Events: %zu", matchingEvents.size()); 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))) { + 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 && peer->state != PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS))) { 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); @@ -6722,7 +6722,10 @@ void sendCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * ma } // Delete Peer - else deletePeer(context, peer); + else { + // Instead of removing peer immediately, We should give a little time before removing the peer and let it timed out? so it can send the BYE packet when stopping AdhocMatching after Canceling it + peer->lastping = CoreTiming::GetGlobalTimeUsScaled(); + } } } @@ -6898,7 +6901,7 @@ void sendByePacket(SceNetAdhocMatchingContext * context) for (; peer != NULL; peer = peer->next) { // Peer of Interest - if (peer->state == PSP_ADHOC_MATCHING_PEER_PARENT || peer->state == PSP_ADHOC_MATCHING_PEER_CHILD || peer->state == PSP_ADHOC_MATCHING_PEER_P2P) + if (peer->state == PSP_ADHOC_MATCHING_PEER_PARENT || peer->state == PSP_ADHOC_MATCHING_PEER_CHILD || peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS) { // Bye Opcode uint8_t opcode = PSP_ADHOC_MATCHING_PACKET_BYE; @@ -7455,10 +7458,11 @@ void actOnByePacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * send // We know this guy if (peer != NULL) { - // P2P or Child Bye + // P2P or Child Bye. FIXME: Should we allow BYE Event to intervene joining process of Parent-Child too just like P2P Mode? (ie. Crazy Taxi uses P2P Mode) if ((context->mode == PSP_ADHOC_MATCHING_MODE_PARENT && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) || (context->mode == PSP_ADHOC_MATCHING_MODE_CHILD && peer->state == PSP_ADHOC_MATCHING_PEER_CHILD) || - (context->mode == PSP_ADHOC_MATCHING_MODE_P2P && peer->state == PSP_ADHOC_MATCHING_PEER_P2P)) + (context->mode == PSP_ADHOC_MATCHING_MODE_P2P && + (peer->state == PSP_ADHOC_MATCHING_PEER_P2P || peer->state == PSP_ADHOC_MATCHING_PEER_OFFER || peer->state == PSP_ADHOC_MATCHING_PEER_INCOMING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_OUTGOING_REQUEST || peer->state == PSP_ADHOC_MATCHING_PEER_CANCEL_IN_PROGRESS))) { if (context->mode != PSP_ADHOC_MATCHING_MODE_CHILD) { // Spawn Leave / Kick Event. FIXME: DISCONNECT event should only be triggered on Parent/P2P mode and for Parent/P2P peer? From f63ed56b4e242f1ecd7556ec8fe06686ce6abb5a Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 9 Oct 2023 22:19:50 +0700 Subject: [PATCH 3/7] Extending AdhocMatching's timeout by 500ms should be sufficient for players with high latency. --- 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 2e593ffec2..e9d8e73dd2 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -4935,7 +4935,7 @@ static int sceNetAdhocMatchingCreate(int mode, int maxnum, int port, int rxbufle if (keepalive_int < 1) context->keepalive_int = PSP_ADHOCCTL_PING_TIMEOUT; else context->keepalive_int = keepalive_int; // client might set this to 0 context->keepalivecounter = init_count; // used to multiply keepalive_int as timeout context->timeout = (((u64)(keepalive_int)+(u64)rexmt_int) * (u64)init_count); - context->timeout += adhocDefaultTimeout; // For internet play we need higher timeout than what the game wanted + context->timeout += 500000; // For internet play we need higher timeout than what the game wanted context->handler = handler; context->peerPort = new std::map(); From 5ca44f4ad9b9bdf7abed2c861b39d59cd0c05270 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 9 Oct 2023 22:24:05 +0700 Subject: [PATCH 4/7] Lets not delete the peer immediately, as handleTimeout function need the peer to be existed in order to trigger the TIMEOUT Event. --- Core/HLE/sceNetAdhoc.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index e9d8e73dd2..aa5271ab54 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -7230,7 +7230,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt); // Delete Peer from List - deletePeer(context, peer); + //deletePeer(context, peer); + peer->lastping = 0; } // Kicked from Room @@ -7263,7 +7264,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt); // Delete Peer from List - deletePeer(context, peer); + //deletePeer(context, peer); + peer->lastping = 0; } // Leave Room @@ -7273,7 +7275,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt); // Delete Peer from List - deletePeer(context, peer); + //deletePeer(context, peer); + peer->lastping = 0; } } @@ -7289,8 +7292,9 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s // Spawn Deny Event spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_DENY, sendermac, optlen, opt); - // Delete Peer from List - deletePeer(context, peer); + // FIXME: Delete Peer from List? + // Instead of removing the peer immediately, we should let it timedout, otherwise inviter in Crazy Taxi will wait forever without getting timedout, since handleTimeout need the peer data to exist. + peer->lastping = 0; } // Kicked from Room @@ -7300,7 +7304,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_LEAVE, sendermac, optlen, opt); // Delete Peer from List - deletePeer(context, peer); + //deletePeer(context, peer); + peer->lastping = 0; } // Cancel Join Request @@ -7310,7 +7315,8 @@ void actOnCancelPacket(SceNetAdhocMatchingContext * context, SceNetEtherAddr * s spawnLocalEvent(context, PSP_ADHOC_MATCHING_EVENT_CANCEL, sendermac, optlen, opt); // Delete Peer from List - deletePeer(context, peer); + //deletePeer(context, peer); + peer->lastping = 0; } } } From 88f367f5021db92b3b9c8fa8721a24abf5b517ef Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 9 Oct 2023 22:29:11 +0700 Subject: [PATCH 5/7] Process event messages quicker to prevent event queue from piling up when there are more players. Might also improve the success rate of joining process on Def Jam Fight for NY. --- Core/HLE/sceNetAdhoc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index aa5271ab54..07443a5699 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -5937,7 +5937,7 @@ void __NetMatchingCallbacks() //(int matchingId) } // 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? - sceKernelDelayThread(delayus); + sceKernelDelayThreadCB(delayus); } const HLEFunction sceNetAdhoc[] = { @@ -7529,7 +7529,7 @@ int matchingEventThread(int matchingId) peerlock.unlock(); // Messages on Stack ready for processing - if (context != NULL && context->event_stack != NULL) + while (context != NULL && context->event_stack != NULL) { // Claim Stack context->eventlock->lock(); From f4c2967969308321a197342f534d098649780735 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 13 Oct 2023 00:21:08 +0700 Subject: [PATCH 6/7] Checks timeout before Pinging instead of on each message loop to give time for other event to occurs before timeout event. --- Core/HLE/sceNetAdhoc.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 07443a5699..d07bd1c2dd 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -7690,15 +7690,23 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi } // Ping Required - if (context->keepalive_int > 0) + if (context->keepalive_int > 0) { if (static_cast(now - lastping) >= static_cast(context->keepalive_int)) { + // Handle Peer Timeouts + handleTimeout(context); + // Broadcast Ping Message broadcastPingMessage(context); // Update Ping Timer lastping = now; } + } + else { + // FIXME: Should we checks for Timeout too when the game doesn't set the keep alive interval? + handleTimeout(context); + } // Messages on Stack ready for processing if (context->input_stack != NULL) @@ -7830,9 +7838,6 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Ignore Incoming Trash Data } - - // Handle Peer Timeouts - handleTimeout(context); } // Share CPU Time sleep_ms(10); //1 //sceKernelDelayThread(10000); From 2f3e9073f6adbd572f008cc8263a5018c78caa26 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 13 Oct 2023 01:53:07 +0700 Subject: [PATCH 7/7] Process incoming packets quicker whenever available to handle more than 2 players better, instead of one datagram message per 10ms sleep interval which will delay the event generated from the message by 10ms for each additional player. --- Core/HLE/sceNetAdhoc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index d07bd1c2dd..6b800e6d02 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -7671,7 +7671,7 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Multithreading Unlock peerlock.unlock(); - if (context != NULL) { + while (context != NULL && context->inputRunning && !Core_IsStepping()) { now = CoreTiming::GetGlobalTimeUsScaled(); //time_now_d()*1000000.0; // Hello Message Sending Context with unoccupied Slots @@ -7838,6 +7838,8 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Ignore Incoming Trash Data } + else + break; } // Share CPU Time sleep_ms(10); //1 //sceKernelDelayThread(10000);