diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 28dfbb43d9..e7e9832ac2 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1062,10 +1062,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); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index e83b35d2f7..91be17bd16 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -4940,7 +4940,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(); @@ -5927,7 +5927,7 @@ void __NetMatchingCallbacks() //(int matchingId) DEBUG_LOG(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(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); @@ -5942,7 +5942,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[] = { @@ -6727,7 +6727,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(); + } } } @@ -6903,7 +6906,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; @@ -7232,7 +7235,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 @@ -7265,7 +7269,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 @@ -7275,7 +7280,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; } } @@ -7291,8 +7297,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 @@ -7302,7 +7309,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 @@ -7312,7 +7320,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; } } } @@ -7460,10 +7469,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? @@ -7524,7 +7534,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(); @@ -7666,7 +7676,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 @@ -7685,15 +7695,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) @@ -7825,9 +7843,8 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Ignore Incoming Trash Data } - - // Handle Peer Timeouts - handleTimeout(context); + else + break; } // Share CPU Time sleep_ms(10); //1 //sceKernelDelayThread(10000);