Merge pull request #15331 from ANR2ME/adhoc_matching

[AdhocMatching] Fix timing issue
This commit is contained in:
Henrik Rydgård 2022-01-19 22:09:30 +01:00 committed by GitHub
commit c9dee44cfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 12 deletions

View File

@ -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

View File

@ -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

View File

@ -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)
@ -5746,23 +5746,34 @@ void __NetMatchingCallbacks() //(int matchingId)
{
std::lock_guard<std::recursive_mutex> 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()) {
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();
}
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?

View File

@ -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 {