[Kernel] Add Linux socket support and ensure binding low ports is remapped.

Remapping ports on both Linux and Windows to ensure games boot under
wine as well.
This commit is contained in:
Herman S.
2025-10-03 10:15:03 +09:00
committed by Radosław Gliński
parent 344e8538e0
commit 4af2fd6513
2 changed files with 138 additions and 25 deletions

View File

@@ -248,38 +248,42 @@ DECLARE_XAM_EXPORT1(NetDll_XNetRandom, kNetworking, kStub);
dword_result_t NetDll_WSAStartup_entry(dword_t caller, word_t version,
pointer_t<X_WSADATA> data_ptr) {
// TODO(benvanik): abstraction layer needed.
// TODO(benvanik): abstraction layer needed.
int ret = 0;
#ifdef XE_PLATFORM_WIN32
WSADATA wsaData;
ZeroMemory(&wsaData, sizeof(WSADATA));
int ret = WSAStartup(version, &wsaData);
auto data_out = kernel_state()->memory()->TranslateVirtual(data_ptr);
ret = WSAStartup(version, &wsaData);
#endif
if (data_ptr) {
auto data_out = kernel_state()->memory()->TranslateVirtual(data_ptr);
#ifdef XE_PLATFORM_WIN32
data_ptr->version = wsaData.wVersion;
data_ptr->version_high = wsaData.wHighVersion;
std::memcpy(&data_ptr->description, wsaData.szDescription, 0x100);
std::memcpy(&data_ptr->system_status, wsaData.szSystemStatus, 0x80);
data_ptr->max_sockets = wsaData.iMaxSockets;
data_ptr->max_udpdg = wsaData.iMaxUdpDg;
std::memcpy(&data_ptr->description, wsaData.szDescription, 0x100);
std::memcpy(&data_ptr->system_status, wsaData.szSystemStatus, 0x80);
#else
// Match Windows behavior with reasonable values
data_ptr->version = version.value();
data_ptr->version_high = version.value();
data_ptr->max_sockets = 100;
data_ptr->max_udpdg = 1024;
// WinSock 2.2 typically returns empty strings for these fields
std::memset(&data_ptr->description, 0, 0x100);
std::memset(&data_ptr->system_status, 0, 0x80);
#endif
// Some games (5841099F) want this value round-tripped - they'll compare if
// it changes and bugcheck if it does.
uint32_t vendor_ptr = xe::load_and_swap<uint32_t>(data_out + 0x190);
xe::store_and_swap<uint32_t>(data_out + 0x190, vendor_ptr);
// vendor_info_ptr is at offset 0x18A (after max_udpdg at 0x188)
uint32_t vendor_ptr = xe::load_and_swap<uint32_t>(data_out + 0x18A);
xe::store_and_swap<uint32_t>(data_out + 0x18A, vendor_ptr);
}
#else
int ret = 0;
if (data_ptr) {
// Guess these values!
data_ptr->version = version.value();
data_ptr->description[0] = '\0';
data_ptr->system_status[0] = '\0';
data_ptr->max_sockets = 100;
data_ptr->max_udpdg = 1024;
}
#endif
// DEBUG
/*
@@ -659,6 +663,8 @@ dword_result_t NetDll_socket_entry(dword_t caller, dword_t af, dword_t type,
socket->Release();
XThread::SetLastError(socket->GetLastWSAError());
XELOGE("NetDll_socket: failed with error {:08X}",
socket->GetLastWSAError());
return -1;
}
@@ -742,6 +748,8 @@ dword_result_t NetDll_ioctlsocket_entry(dword_t caller, dword_t socket_handle,
X_STATUS status = socket->IOControl(cmd, arg_ptr);
if (XFAILED(status)) {
XThread::SetLastError(socket->GetLastWSAError());
XELOGE("NetDll_ioctlsocket: failed with error {:08X}",
socket->GetLastWSAError());
return -1;
}
@@ -757,6 +765,7 @@ dword_result_t NetDll_bind_entry(dword_t caller, dword_t socket_handle,
kernel_state()->object_table()->LookupObject<XSocket>(socket_handle);
if (!socket) {
XThread::SetLastError(uint32_t(X_WSAError::X_WSAENOTSOCK));
XELOGE("NetDll_bind: failed - invalid socket");
return -1;
}
@@ -764,6 +773,7 @@ dword_result_t NetDll_bind_entry(dword_t caller, dword_t socket_handle,
X_STATUS status = socket->Bind(&native_name, namelen);
if (XFAILED(status)) {
XThread::SetLastError(socket->GetLastWSAError());
XELOGE("NetDll_bind: failed with status {:08X}", status);
return -1;
}
@@ -1027,7 +1037,8 @@ dword_result_t NetDll_sendto_entry(dword_t caller, dword_t socket_handle,
}
N_XSOCKADDR_IN native_to(to_ptr);
return socket->SendTo(buf_ptr, buf_len, flags, &native_to, to_len);
int ret = socket->SendTo(buf_ptr, buf_len, flags, &native_to, to_len);
return ret;
}
DECLARE_XAM_EXPORT1(NetDll_sendto, kNetworking, kImplemented);