Skip to content

Commit

Permalink
Fix frozen (0 FPS) issue on Kao Challengers and Asterix & Obelix XX (…
Browse files Browse the repository at this point in the history
…probably also fix other games from the same developer with similar issue) #14103
  • Loading branch information
anr2me committed Feb 10, 2021
1 parent 7095115 commit fc452c0
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Core/HLE/proAdhoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#undef EISCONN
#undef EALREADY
#undef ETIMEDOUT
#undef EOPNOTSUPP
#define errno WSAGetLastError()
#define ESHUTDOWN WSAESHUTDOWN
#define ECONNABORTED WSAECONNABORTED
Expand All @@ -77,6 +78,7 @@
#define EISCONN WSAEISCONN
#define EALREADY WSAEALREADY
#define ETIMEDOUT WSAETIMEDOUT
#define EOPNOTSUPP WSAEOPNOTSUPP
inline bool connectInProgress(int errcode){ return (errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEALREADY); }
inline bool isDisconnected(int errcode) { return (errcode == WSAECONNRESET || errcode == WSAECONNABORTED || errcode == WSAESHUTDOWN); }
#else
Expand Down
7 changes: 5 additions & 2 deletions Core/HLE/sceNetAdhoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
memset(&sin, 0, sizeof(sin));
socklen_t sinlen = sizeof(sin);

// On Windows: Using MSG_TRUNC can sometimes getting socket error WSAEOPNOTSUPP, may be the socket wasn't ready to received anything right after created & binded?
int ret = recvfrom(uid, (char*)req.buffer, *req.length, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, (sockaddr*)&sin, &sinlen);
int sockerr = errno;

Expand Down Expand Up @@ -452,7 +453,7 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
result = 0;
}
// On Windows: recvfrom on UDP can get error WSAECONNRESET when previous sendto's destination is unreachable (or destination port is not bound yet), may need to disable SIO_UDP_CONNRESET error
else if (sockerr == EAGAIN || sockerr == EWOULDBLOCK || sockerr == ECONNRESET) {
else if (sockerr == EAGAIN || sockerr == EWOULDBLOCK || sockerr == ECONNRESET || sockerr == EOPNOTSUPP) {
u64 now = (u64)(time_now_d() * 1000000.0);
if (req.timeout == 0 || now - req.startTime <= req.timeout) {
// Try again later
Expand Down Expand Up @@ -483,6 +484,7 @@ int DoBlockingPdpRecv(int uid, AdhocSocketRequest& req, s64& result) {
}
result = ERROR_NET_ADHOC_NOT_ENOUGH_SPACE;
}
// FIXME: Blocking operation with infinite timeout(0) should never get a TIMEOUT error, right? May be we should return INVALID_ARG instead if it was infinite timeout (0)?
else
result = ERROR_NET_ADHOC_TIMEOUT; // ERROR_NET_ADHOC_INVALID_ARG; // ERROR_NET_ADHOC_DISCONNECTED

Expand Down Expand Up @@ -1689,6 +1691,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *

// Receive Data. PDP always sent in full size or nothing(failed), recvfrom will always receive in full size as requested (blocking) or failed (non-blocking). If available UDP data is larger than buffer, excess data is lost.
// Should peek first for the available data size if it's more than len return ERROR_NET_ADHOC_NOT_ENOUGH_SPACE along with required size in len to prevent losing excess data
// On Windows: Using MSG_TRUNC can sometimes getting socket error WSAEOPNOTSUPP, may be the socket wasn't ready to received anything right after created & binded?
received = recvfrom(pdpsocket.id, (char*)buf, *len, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, (sockaddr*)&sin, &sinlen);
if (received != SOCKET_ERROR && *len < received) {
WARN_LOG(SCENET, "sceNetAdhocPdpRecv[%i:%u]: Peeked %u/%u bytes from %s:%u\n", id, getLocalPort(pdpsocket.id), received, *len, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
Expand Down Expand Up @@ -1719,7 +1722,7 @@ static int sceNetAdhocPdpRecv(int id, void *addr, void * port, void *buf, void *
error = errno;

// On Windows: recvfrom on UDP can get error WSAECONNRESET when previous sendto's destination is unreachable (or destination port is not bound), may need to disable SIO_UDP_CONNRESET
if (received == SOCKET_ERROR && (error == EAGAIN || error == EWOULDBLOCK || error == ECONNRESET)) {
if (received == SOCKET_ERROR && (error == EAGAIN || error == EWOULDBLOCK || error == ECONNRESET || error == EOPNOTSUPP)) {
if (flag == 0) {
// Simulate blocking behaviour with non-blocking socket
u64 threadSocketId = ((u64)__KernelGetCurThread()) << 32 | pdpsocket.id;
Expand Down

0 comments on commit fc452c0

Please sign in to comment.