Fix connection issue on Dynasty Warriors (Shin Sangoku Musou) games when playing with more than 2 players.

This commit is contained in:
ANR2ME 2021-01-28 22:38:49 +07:00
parent 54849075aa
commit d907906c74
3 changed files with 12 additions and 7 deletions

View File

@ -128,16 +128,19 @@ bool isPDPPortInUse(uint16_t port) {
return false;
}
bool isPTPPortInUse(uint16_t port, bool forListen) {
bool isPTPPortInUse(uint16_t port, bool forListen, SceNetEtherAddr* dstmac, uint16_t dstport) {
// Iterate Sockets
for (int i = 0; i < MAX_SOCKET; i++) {
auto sock = adhocSockets[i];
if (sock != NULL && sock->type == SOCK_PTP)
// It's allowed to Listen and Open the same PTP port, But it's not allowed to Listen or Open the same PTP port twice.
if (sock->data.ptp.lport == port &&
((forListen && sock->data.ptp.state == ADHOC_PTP_STATE_LISTEN) ||
(!forListen && sock->data.ptp.state != ADHOC_PTP_STATE_LISTEN)))
// It's allowed to Listen and Open the same PTP port, But it's not allowed to Listen or Open the same PTP port twice (unless destination mac or port are different).
if (sock->data.ptp.lport == port &&
((forListen && sock->data.ptp.state == ADHOC_PTP_STATE_LISTEN) ||
(!forListen && sock->data.ptp.state != ADHOC_PTP_STATE_LISTEN &&
sock->data.ptp.pport == dstport && dstmac != nullptr && isMacMatch(&sock->data.ptp.paddr, dstmac))))
{
return true;
}
}
// Unused Port
return false;

View File

@ -972,9 +972,11 @@ bool isPDPPortInUse(uint16_t port);
* Check whether PTP Port is in use or not (only sockets with non-Listening state will be considered as in use)
* @param port To-be-checked Port Number
* @param forListen to check for listening or non-listening port
* @param dstmac destination address (non-listening only)
* @param dstport destination port (non-listening only)
* @return 1 if in use or... 0
*/
bool isPTPPortInUse(uint16_t port, bool forListen);
bool isPTPPortInUse(uint16_t port, bool forListen, SceNetEtherAddr* dstmac = nullptr, uint16_t dstport = 0);
// Convert MAC address to string
std::string mac2str(SceNetEtherAddr* mac);

View File

@ -3103,7 +3103,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac,
// Valid Addresses. FIXME: MAC only valid after successful attempt to Create/Connect/Join a Group? (ie. adhocctlCurrentMode != ADHOCCTL_MODE_NONE)
if ((adhocctlCurrentMode != ADHOCCTL_MODE_NONE) && saddr != NULL && isLocalMAC(saddr) && daddr != NULL && !isBroadcastMAC(daddr) && !isZeroMAC(daddr)) {
// Dissidia 012 will try to reOpen the port without Closing the old one first when PtpConnect failed to try again.
if (isPTPPortInUse(sport, false)) {
if (isPTPPortInUse(sport, false, daddr, dport)) {
// FIXME: When PORT_IN_USE error occured it seems the index to the socket id also increased, which means it tries to create & bind the socket first and then closes it due to failed to bind
return hleLogDebug(SCENET, ERROR_NET_ADHOC_PORT_IN_USE, "port in use");
}