Enough NetDll for games using sockets as IPC.
This commit is contained in:
parent
ebec66f3c2
commit
f128bf8670
|
@ -7,6 +7,7 @@
|
|||
******************************************************************************
|
||||
*/
|
||||
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr
|
||||
#include <winsock2.h>
|
||||
|
||||
#include "xenia/common.h"
|
||||
|
@ -18,6 +19,41 @@
|
|||
namespace xe {
|
||||
namespace kernel {
|
||||
|
||||
void LoadSockaddr(const uint8_t* ptr, sockaddr* out_addr) {
|
||||
out_addr->sa_family = poly::load_and_swap<uint16_t>(ptr + 0);
|
||||
switch (out_addr->sa_family) {
|
||||
case AF_INET: {
|
||||
auto in_addr = reinterpret_cast<sockaddr_in*>(out_addr);
|
||||
in_addr->sin_port = poly::load_and_swap<uint16_t>(ptr + 2);
|
||||
// Maybe? Depends on type.
|
||||
in_addr->sin_addr.S_un.S_addr = poly::load_and_swap<uint32_t>(ptr + 4);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert_unhandled_case(out_addr->sa_family);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void StoreSockaddr(const sockaddr& addr, uint8_t* ptr) {
|
||||
switch (addr.sa_family) {
|
||||
case AF_UNSPEC:
|
||||
memset(ptr, 0, sizeof(addr));
|
||||
break;
|
||||
case AF_INET: {
|
||||
auto& in_addr = reinterpret_cast<const sockaddr_in&>(addr);
|
||||
poly::store_and_swap<uint16_t>(ptr + 0, in_addr.sin_family);
|
||||
poly::store_and_swap<uint16_t>(ptr + 2, in_addr.sin_port);
|
||||
// Maybe? Depends on type.
|
||||
poly::store_and_swap<uint32_t>(ptr + 4, in_addr.sin_addr.S_un.S_addr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert_unhandled_case(addr.sa_family);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_XNetStartup_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t params_ptr = SHIM_GET_ARG_32(1);
|
||||
|
@ -73,18 +109,27 @@ SHIM_CALL NetDll_WSAStartup_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
SHIM_SET_RETURN_64(0);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_WSACleanup_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
XELOGD("NetDll_WSACleanup(%d)", arg0);
|
||||
int ret = WSACleanup();
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_WSAGetLastError_shim(PPCContext* ppc_state,
|
||||
KernelState* state) {
|
||||
XELOGD("NetDll_WSAGetLastError()");
|
||||
SHIM_SET_RETURN_32(10093L); // WSANOTINITIALISED
|
||||
int err = WSAGetLastError();
|
||||
SHIM_SET_RETURN_32(err);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_XNetGetTitleXnAddr_shim(PPCContext* ppc_state,
|
||||
KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t arg1 = SHIM_GET_ARG_32(1);
|
||||
XELOGD("NetDll_XNetGetTitleXnAddr(%d, %.8X)", arg0, arg1);
|
||||
SHIM_SET_RETURN_32(0x00000001);
|
||||
uint32_t addr_ptr = SHIM_GET_ARG_32(1);
|
||||
XELOGD("NetDll_XNetGetTitleXnAddr(%d, %.8X)", arg0, addr_ptr);
|
||||
// TODO(benvanik): set addr info.
|
||||
SHIM_SET_RETURN_32(0x00000002);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_XNetGetEthernetLinkStatus_shim(PPCContext* ppc_state,
|
||||
|
@ -98,8 +143,10 @@ SHIM_CALL NetDll_XNetGetEthernetLinkStatus_shim(PPCContext* ppc_state,
|
|||
|
||||
SHIM_CALL NetDll_inet_addr_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t cp_ptr = SHIM_GET_ARG_32(0);
|
||||
XELOGD("NetDll_inet_addr(%.8X)", cp_ptr);
|
||||
SHIM_SET_RETURN_32(0xFFFFFFFF); // X_INADDR_NONE
|
||||
auto cp = reinterpret_cast<const char*>(SHIM_MEM_ADDR(cp_ptr));
|
||||
XELOGD("NetDll_inet_addr(%.8X(%s))", cp_ptr, cp);
|
||||
uint32_t addr = inet_addr(cp);
|
||||
SHIM_SET_RETURN_32(addr);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_socket_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
|
@ -108,62 +155,173 @@ SHIM_CALL NetDll_socket_shim(PPCContext* ppc_state, KernelState* state) {
|
|||
uint32_t type = SHIM_GET_ARG_32(2);
|
||||
uint32_t protocol = SHIM_GET_ARG_32(3);
|
||||
XELOGD("NetDll_socket(%d, %d, %d, %d)", arg0, af, type, protocol);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
if (protocol == 0xFE) {
|
||||
protocol = IPPROTO_UDP;
|
||||
}
|
||||
SOCKET socket_handle = socket(af, type, protocol);
|
||||
assert_true(socket_handle >> 32 == 0);
|
||||
SHIM_SET_RETURN_32(static_cast<uint32_t>(socket_handle));
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_closesocket_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
XELOGD("NetDll_closesocket(%d, %.8X)", arg0, socket_handle);
|
||||
int ret = closesocket(socket_handle);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_setsockopt_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t level = SHIM_GET_ARG_32(2);
|
||||
uint32_t optname = SHIM_GET_ARG_32(3);
|
||||
uint32_t optval_ptr = SHIM_GET_ARG_32(4);
|
||||
uint32_t optlen = SHIM_GET_ARG_32(5);
|
||||
XELOGD("NetDll_setsockopt(%d, %.8X, %d, %d, %.8X, %d)", arg0, socket_ptr,
|
||||
XELOGD("NetDll_setsockopt(%d, %.8X, %d, %d, %.8X, %d)", arg0, socket_handle,
|
||||
level, optname, optval_ptr, optlen);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
char* optval = reinterpret_cast<char*>(SHIM_MEM_ADDR(optval_ptr));
|
||||
int ret = setsockopt(socket_handle, level, optname, optval, optlen);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_ioctlsocket_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t cmd = SHIM_GET_ARG_32(2);
|
||||
uint32_t arg_ptr = SHIM_GET_ARG_32(3);
|
||||
XELOGD("NetDll_ioctlsocket(%d, %.8X, %.8X, %.8X)", arg0, socket_handle, cmd,
|
||||
arg_ptr);
|
||||
u_long arg = SHIM_MEM_32(arg_ptr);
|
||||
int ret = ioctlsocket(socket_handle, cmd, &arg);
|
||||
SHIM_SET_MEM_32(arg_ptr, arg);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_bind_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t name_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t namelen = SHIM_GET_ARG_32(3);
|
||||
XELOGD("NetDll_bind(%d, %.8X, %.8X, %d)", arg0, socket_handle, name_ptr,
|
||||
namelen);
|
||||
sockaddr name;
|
||||
LoadSockaddr(SHIM_MEM_ADDR(name_ptr), &name);
|
||||
int ret = bind(socket_handle, &name, namelen);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_connect_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t socket_ptr = SHIM_GET_ARG_32(0);
|
||||
uint32_t sockaddr_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t namelen = SHIM_GET_ARG_32(2);
|
||||
XELOGD("NetDll_connect(%.8X, %.8X, %d)", socket_ptr, sockaddr_ptr, namelen);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t name_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t namelen = SHIM_GET_ARG_32(3);
|
||||
XELOGD("NetDll_connect(%d, %.8X, %.8X, %d)", arg0, socket_handle, name_ptr,
|
||||
namelen);
|
||||
sockaddr name;
|
||||
LoadSockaddr(SHIM_MEM_ADDR(name_ptr), &name);
|
||||
int ret = connect(socket_handle, &name, namelen);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_listen_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
int32_t backlog = SHIM_GET_ARG_32(2);
|
||||
XELOGD("NetDll_listen(%d, %.8X, %d)", arg0, socket_handle, backlog);
|
||||
int ret = listen(socket_handle, backlog);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_accept_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t addr_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t addrlen_ptr = SHIM_GET_ARG_32(3);
|
||||
XELOGD("NetDll_accept(%d, %.8X, %d)", arg0, socket_handle, addr_ptr,
|
||||
addrlen_ptr);
|
||||
sockaddr addr;
|
||||
int addrlen;
|
||||
SOCKET ret_socket = accept(socket_handle, &addr, &addrlen);
|
||||
if (ret_socket == INVALID_SOCKET) {
|
||||
memset(SHIM_MEM_ADDR(addr_ptr), 0, sizeof(addr));
|
||||
SHIM_SET_MEM_32(addrlen_ptr, sizeof(addr));
|
||||
SHIM_SET_RETURN_32(-1);
|
||||
} else {
|
||||
assert_true(ret_socket >> 32 == 0);
|
||||
StoreSockaddr(addr, SHIM_MEM_ADDR(addr_ptr));
|
||||
SHIM_SET_MEM_32(addrlen_ptr, addrlen);
|
||||
SHIM_SET_RETURN_32(static_cast<uint32_t>(ret_socket));
|
||||
}
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_recv_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t len = SHIM_GET_ARG_32(3);
|
||||
uint32_t flags = SHIM_GET_ARG_32(4);
|
||||
XELOGD("NetDll_recv(%d, %.8X, %.8X, %d, %d)", arg0, socket_ptr, buf_ptr, len,
|
||||
flags);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
XELOGD("NetDll_recv(%d, %.8X, %.8X, %d, %d)", arg0, socket_handle, buf_ptr,
|
||||
len, flags);
|
||||
int ret = recv(socket_handle, reinterpret_cast<char*>(SHIM_MEM_ADDR(buf_ptr)),
|
||||
len, flags);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_recvfrom_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t len = SHIM_GET_ARG_32(3);
|
||||
uint32_t flags = SHIM_GET_ARG_32(4);
|
||||
uint32_t from_ptr = SHIM_GET_ARG_32(5);
|
||||
uint32_t fromlen_ptr = SHIM_GET_ARG_32(6);
|
||||
XELOGD("NetDll_recvfrom(%d, %.8X, %.8X, %d, %d, %.8X, %.8X)", arg0,
|
||||
socket_ptr, buf_ptr, len, flags, from_ptr, fromlen_ptr);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
socket_handle, buf_ptr, len, flags, from_ptr, fromlen_ptr);
|
||||
sockaddr from;
|
||||
int fromlen = sizeof(from);
|
||||
int ret =
|
||||
recvfrom(socket_handle, reinterpret_cast<char*>(SHIM_MEM_ADDR(buf_ptr)),
|
||||
len, flags, &from, &fromlen);
|
||||
if (ret == -1) {
|
||||
memset(SHIM_MEM_ADDR(from_ptr), 0, sizeof(from));
|
||||
SHIM_SET_MEM_32(fromlen_ptr, sizeof(from));
|
||||
} else {
|
||||
StoreSockaddr(from, SHIM_MEM_ADDR(from_ptr));
|
||||
SHIM_SET_MEM_32(fromlen_ptr, fromlen);
|
||||
}
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_send_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_ptr = SHIM_GET_ARG_32(1);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t len = SHIM_GET_ARG_32(3);
|
||||
uint32_t flags = SHIM_GET_ARG_32(4);
|
||||
XELOGD("NetDll_send(%d,%.8X, %.8X, %d, %d)", arg0, socket_ptr, buf_ptr, len,
|
||||
flags);
|
||||
SHIM_SET_RETURN_32(X_SOCKET_ERROR);
|
||||
XELOGD("NetDll_send(%d, %.8X, %.8X, %d, %d)", arg0, socket_handle, buf_ptr,
|
||||
len, flags);
|
||||
int ret = send(socket_handle, reinterpret_cast<char*>(SHIM_MEM_ADDR(buf_ptr)),
|
||||
len, flags);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
SHIM_CALL NetDll_sendto_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
uint32_t arg0 = SHIM_GET_ARG_32(0);
|
||||
uint32_t socket_handle = SHIM_GET_ARG_32(1);
|
||||
uint32_t buf_ptr = SHIM_GET_ARG_32(2);
|
||||
uint32_t len = SHIM_GET_ARG_32(3);
|
||||
uint32_t flags = SHIM_GET_ARG_32(4);
|
||||
uint32_t to_ptr = SHIM_GET_ARG_32(5);
|
||||
uint32_t tolen = SHIM_GET_ARG_32(6);
|
||||
XELOGD("NetDll_sendto(%d, %.8X, %.8X, %d, %d, %.8X, %d)", arg0, socket_handle,
|
||||
buf_ptr, len, flags, to_ptr, tolen);
|
||||
sockaddr to;
|
||||
LoadSockaddr(SHIM_MEM_ADDR(to_ptr), &to);
|
||||
int ret =
|
||||
sendto(socket_handle, reinterpret_cast<char*>(SHIM_MEM_ADDR(buf_ptr)),
|
||||
len, flags, &to, tolen);
|
||||
SHIM_SET_RETURN_32(ret);
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
|
@ -175,14 +333,21 @@ void xe::kernel::xam::RegisterNetExports(ExportResolver* export_resolver,
|
|||
SHIM_SET_MAPPING("xam.xex", NetDll_XNetCleanup, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_XNetRandom, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_WSAStartup, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_WSACleanup, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_WSAGetLastError, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_XNetGetTitleXnAddr, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_XNetGetEthernetLinkStatus, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_inet_addr, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_socket, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_closesocket, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_setsockopt, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_ioctlsocket, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_bind, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_connect, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_listen, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_accept, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_recv, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_recvfrom, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_send, state);
|
||||
SHIM_SET_MAPPING("xam.xex", NetDll_sendto, state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue